导语

  在JVM中除了有堆内存参数配置以外,还有一些其他内存例如方法区、线程栈直接内存等等。他们与堆内存来说是相对比较独立的内存空间。与堆内存相比较这些内存与应用程序本身的关系不大,但是如果将其放到整个的系统层面上来说的话在有效的配置之后会使得系统的稳定性和性能有一定程度上的提升。

文章目录

  • 方法区的配置参数
    • 小例子
      • 第一步 创建动态代理逻辑
      • 第二步 填写虚拟机参数
      • 第三步 运行结果分析
    • 测试高级参数
      • 第一步 添加启动参数运行代码
      • 第二步 分析运行结果
    • 为什么Matespace没有发生变化?
  • 总结

方法区的配置参数

  与Java堆类似,方法区也是所有线程共享的一块区域,用于保存系统类的信息,例如字段、方法、常量池等等。方法区的大小决定了系统可以保存多少个类,如果系统在定义了太多的方法就会导致整个的方法区溢出,同样虚拟机也会抛出内存溢出的异常。
  在JDK1.6、JDK1.7中,方法去可以理解为永久代Perm,永久区可以使用下面介绍的参数来进行配置,在默认的情况下最大值设为64MB。在一定程度上,一个大的永久区可以存放跟多的类信息,但是如果系统使用了一些动态代理,那么可能会在运行时生成大量的类,如果这样就可以根据实际情况来合理的设置方法区的大小,从而保证了不会出现方法区内存溢出。
  首先要知道方法区主要存放一些元信息,在JDK1.6和JDK1.7的版本中可以使用如下的两个参数来设置永久区大小
-XX:PermSize 表示初始化永久区大小
-XX:MaxPermSize 表示最大永久区大小

  在JDK1.8中彻底的移除了永久区,使用了新的元数据区存放类的元数据,默认的情况下元数据区只受到系统可用内存的限制,但是还是可以使用如下的参数进行设置

-XX:MaxMetaspceSize 指定元数据区域最大的大小。

小例子

  这里给出的小例子只是为了测试来使用不需要关心起具体的实现逻辑是什么?由于这里使用到了cglib,所以笔者使用的是IDEA工具进行调试。

第一步 创建动态代理逻辑

编写代理接口

package com.nihui.permtest;public class ClassHasNoInterface {public void  method(){System.out.println("测试方法");}public void function(){System.out.println("测试函数");}
}

动态代理类扩展

package com.nihui.permtest;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CglibTs implements MethodInterceptor {private Enhancer enhancer = new Enhancer();public Object getProxy(Class clazz){//生成指定类对象的子类,也就是重写类中的业务函数,在重写中加入intercept()函数而已。enhancer.setSuperclass(clazz);//这里是回调函数,enhancer中肯定有个MethodInterceptor属性。//回调函数是在setSuperclass中的那些重写的方法中调用---猜想enhancer.setCallback(this);//创建这个子类对象return enhancer.create();}public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println(method.getName()+"准备一下");//一不小心写成下面被注释一行代码了。 StackOverflowError//Object result = method.invoke(obj, args); 想不通Object result = proxy.invokeSuper(obj,args);System.out.println(method.getName()+"收拾一下");return result;}
}

测试实现代码

public class PermTest {public static void main(String[] args) {CglibTs ct = new CglibTs();ClassHasNoInterface chni = (ClassHasNoInterface) ct.getProxy(ClassHasNoInterface.class);chni.method();chni.function();}
}

第二步 填写虚拟机参数

在运行配置中添加如下内容 ,要记住这里使用的虚拟机参数,不是程序参数,所以参数填写到虚拟机上,笔者使用的是JDK1.8 所以只需要设置元数据区的大小,

第三步 运行结果分析

运行结果

[GC (Metadata GC Threshold) [PSYoungGen: 11822K->1148K(76288K)] 11822K->1156K(251392K), 0.0009938 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[Full GC (Metadata GC Threshold) [PSYoungGen: 1148K->0K(76288K)] [ParOldGen: 8K->913K(121856K)] 1156K->913K(198144K), [Metaspace: 3751K->3751K(1056768K)], 0.0049719 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]
[GC (Last ditch collection) [PSYoungGen: 0K->0K(76288K)] 913K->913K(198144K), 0.0009063 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[Full GC (Last ditch collection) Exception in thread "main" java.lang.OutOfMemoryError: Metaspaceat java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(ClassLoader.java:760)at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)at java.net.URLClassLoader.access$100(URLClassLoader.java:73)at java.net.URLClassLoader$1.run(URLClassLoader.java:368)at java.net.URLClassLoader$1.run(URLClassLoader.java:362)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(URLClassLoader.java:361)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)at java.lang.ClassLoader.loadClass(ClassLoader.java:357)at net.sf.cglib.proxy.Enhancer.emitMethods(Enhancer.java:921)at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:498)at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)at com.nihui.permtest.CglibTs.getProxy(CglibTs.java:21)at com.nihui.permtest.PermTest.main(PermTest.java:26)
[PSYoungGen: 0K->0K(76288K)] [ParOldGen: 913K->875K(224768K)] 913K->875K(301056K), [Metaspace: 3751K->3751K(1056768K)], 0.0043364 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]
HeapPSYoungGen      total 76288K, used 1638K [0x000000076ab00000, 0x0000000772c00000, 0x00000007c0000000)eden space 65536K, 2% used [0x000000076ab00000,0x000000076ac99b28,0x000000076eb00000)from space 10752K, 0% used [0x000000076f580000,0x000000076f580000,0x0000000770000000)to   space 10752K, 0% used [0x000000076eb00000,0x000000076eb00000,0x000000076f580000)ParOldGen       total 224768K, used 875K [0x00000006c0000000, 0x00000006cdb80000, 0x000000076ab00000)object space 224768K, 0% used [0x00000006c0000000,0x00000006c00dac88,0x00000006cdb80000)Metaspace       used 3789K, capacity 5016K, committed 5120K, reserved 1056768Kclass space    used 417K, capacity 456K, committed 512K, reserved 1048576K

  会看到上面结果中出现了一些在之前的分享中没有出现的内容,下面就来一一分析一下

Metadata GC Threshold GC阈值元数据
  通过上面的直译,对于这个应该不陌生在,在之前的分享中提到过,这个是用来指定GC的类型,之前的GC都是Allocation Failure(分配失败),表示在新生代中无法分配内存而导致的GC。根据这个可以推测,Metadata GC Threshold表示的是在由于元数据区不足而导致的GC操作。

第一步 GC

[GC (Metadata GC Threshold) [PSYoungGen: 11822K->1148K(76288K)] 11822K->1156K(251392K), 0.0009938 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]

第二步 GC

[Full GC (Metadata GC Threshold) [PSYoungGen: 1148K->0K(76288K)] [ParOldGen: 8K->913K(121856K)] 1156K->913K(198144K), [Metaspace: 3751K->3751K(1056768K)], 0.0049719 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]

  可以看到在第二步GC之后,Metaspace 的信息也是被打印出来了,这个时候Metaspace大小为1056768K 并不是在参数中设置的5MB,是为什么呢?

Last ditch collection 最后的收集
  字面意思直译 最后的收集

第三次 GC

[GC (Last ditch collection) [PSYoungGen: 0K->0K(76288K)] 913K->913K(198144K), 0.0009063 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]

第四次 GC

[Full GC (Last ditch collection) Exception in thread "main" java.lang.OutOfMemoryError: Metaspaceat java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(ClassLoader.java:760)at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)at java.net.URLClassLoader.access$100(URLClassLoader.java:73)at java.net.URLClassLoader$1.run(URLClassLoader.java:368)at java.net.URLClassLoader$1.run(URLClassLoader.java:362)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(URLClassLoader.java:361)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)at java.lang.ClassLoader.loadClass(ClassLoader.java:357)at net.sf.cglib.proxy.Enhancer.emitMethods(Enhancer.java:921)at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:498)at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)at com.nihui.permtest.CglibTs.getProxy(CglibTs.java:21)at com.nihui.permtest.PermTest.main(PermTest.java:26)
[PSYoungGen: 0K->0K(76288K)] [ParOldGen: 913K->875K(224768K)] 913K->875K(301056K), [Metaspace: 3751K->3751K(1056768K)], 0.0043364 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]

  在第二次GC操作之后出现了Metaspace 内存溢出的异常,并且这显示的Metaspace大小1056768K,大约是1G左右。既然是这样为什么会出现这种情况呢?这个跟之前的设置又有什么关系呢?继续向下分析,下面来介绍几个参数,并且对上面参数做详细说明

-XX:MetaspaceSize=N
这个参数是初始化的Metaspace大小,该值越大触发Metaspace GC的时机就越晚。随着GC的到来,虚拟机会根据实际情况调控Metaspace的大小,可能增加上线也可能降低。在默认情况下,这个值大小根据不同的平台在12M到20M浮动。使用java -XX:+PrintFlagsInitial命令查看本机的初始化参数,-XX:Metaspacesize为21810376B(大约20.8M)。

-XX:MaxMetaspaceSize=N
这个参数用于限制Metaspace增长的上限,防止因为某些情况导致Metaspace无限的使用本地内存,影响到其他程序。在本机上该参数的默认值为4294967295B(大约4096MB)。

-XX:MinMetaspaceFreeRatio=N
当进行过Metaspace GC之后,会计算当前Metaspace的空闲空间比,如果空闲比小于这个参数,那么虚拟机将增长Metaspace的大小。在本机该参数的默认值为40,也就是40%。设置该参数可以控制Metaspace的增长的速度,太小的值会导致Metaspace增长的缓慢,Metaspace的使用逐渐趋于饱和,可能会影响之后类的加载。而太大的值会导致Metaspace增长的过快,浪费内存。

-XX:MaxMetasaceFreeRatio=N
当进行过Metaspace GC之后, 会计算当前Metaspace的空闲空间比,如果空闲比大于这个参数,那么虚拟机会释放Metaspace的部分空间。在本机该参数的默认值为70,也就是70%。

-XX:MaxMetaspaceExpansion=N
Metaspace增长时的最大幅度。在本机上该参数的默认值为5452592B(大约为5MB)

-XX:MinMetaspaceExpansion=N
Metaspace增长时的最小幅度。在本机上该参数的默认值为340784B(大约330KB为)

测试高级参数

public class Metaspace extends ClassLoader {public static void main(String[] args) {// 类持有List<Class<?>> classes = new ArrayList<Class<?>>();// 循环1000w次生成1000w个不同的类。for (int i = 0; i < 10000000; ++i) {ClassWriter cw = new ClassWriter(0);// 定义一个类名称为Class{i},它的访问域为public,父类为java.lang.Object,不实现任何接口cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null,"java/lang/Object", null);// 定义构造函数<init>方法MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>","()V", null, null);// 第一个指令为加载thismw.visitVarInsn(Opcodes.ALOAD, 0);// 第二个指令为调用父类Object的构造函数mw.visitMethodInsn(Opcodes.INVOKESPECIAL,"java/long/Object","<init>","()V");// 第三条指令为returnmw.visitInsn(Opcodes.RETURN);mw.visitMaxs(1, 1);mw.visitEnd();Metaspace test = new Metaspace();byte[] code = cw.toByteArray();// 定义类Class<?> exampleClass = test.defineClass("Class" + i, code, 0, code.length);classes.add(exampleClass);}}
}

第一步 添加启动参数运行代码

-XX:+PrintGCDetails  -XX:+PrintGCDateStamps

配置结果

第二步 分析运行结果

运行结果

[Full GC (Metadata GC Threshold) [PSYoungGen: 3122K->0K(76288K)] [ParOldGen: 8K->2810K(114176K)] 3130K->2810K(190464K), [Metaspace: 5918K->5918K(1064960K)], 0.0132870 secs] [Times: user=0.08 sys=0.00, real=0.02 secs] [PSYoungGen: 143870K->0K(310272K)] [ParOldGen: 302690K->444717K(2514944K)] 446560K->444717K(2825216K), [Metaspace: 498730K->498730K(3149824K)], 1.3286769 secs] [Times: user=11.27 sys=0.13, real=1.33 secs] at java.lang.ClassLoader.defineClass1(Native Method)
[GC (Last ditch collection) [PSYoungGen: 0K->0K(350720K)] 444717K->444717K(2865664K), 0.0481669 secs] [Times: user=0.62 sys=0.00, real=0.05 secs] at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
[Full GC (Last ditch collection) [PSYoungGen: 0K->0K(350720K)] [ParOldGen: 444717K->444698K(2796544K)] 444717K->444698K(3147264K), [Metaspace: 498730K->498730K(3149824K)], 1.5840200 secs] [Times: user=16.31 sys=0.02, real=1.58 secs] at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
Heapat com.nihui.metaspace.Metaspace.main(Metaspace.java:38)

分析结果
  会发现在初始化如果没有任何参数设置的时候Metaspace 大小为1064960K 大约是1G。在JVM使用-XX:+UseCompressedClassPointers和-XX:+UseCompressedOops开启Compressed Class的功能后,会在Metaspace中开辟出一块新的空间(Compressed Class Space),上面的错误正是由于这个空间出现了OutOfMemory,可以通过设置-XX:CompressedClassSpaceSize(默认值为1G)的大小或者-XX:-UseCompressedClassPointers来关闭该功能。

到这里第一个小例子中出现的第一个问题就被解决了

为什么Matespace没有发生变化?

为什么Metaspace大小为1G并没有被改变为5MB,既然可以对CompressedClassSpaceSize大小进行设置甚至是关闭那么下面就来关闭一下这个设置来看看上面那段代码的运行结果

设置参数

-XX:+PrintGCDetails -XX:-UseCompressedClassPointers -XX:MaxMetaspaceSize=5m

测试结果

测试方法
[GC (Metadata GC Threshold) [PSYoungGen: 55746K->128K(1397248K)] 120040K->64422K(4193792K), 0.0013956 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[Full GC (Metadata GC Threshold) [PSYoungGen: 128K->0K(1397248K)] [ParOldGen: 64294K->64222K(2796544K)] 64422K->64222K(4193792K), [Metaspace: 5026K->5026K(8192K)], 0.0358250 secs] [Times: user=0.41 sys=0.01, real=0.04 secs] 测试方法
[GC (Metadata GC Threshold) [PSYoungGen: 27811K->64K(1397248K)] 91926K->64179K(4193792K), 0.0004278 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Metadata GC Threshold) [PSYoungGen: 64K->0K(1397248K)] [ParOldGen: 64115K->64088K(2796544K)] 64179K->64088K(4193792K), [Metaspace: 5026K->5026K(8192K)], 0.0320449 secs] [Times: user=0.34 sys=0.01, real=0.04 secs] 

  上面这代码是两个不同时间点打印出测试方法之后的GC操作。首先来看看FullGC之后打印出来的Metaspace大小 会看到大小是8192K 并且GC之后的大小和GC之前的大小是一样的,5026K->5026K

[Metaspace: 5026K->5026K(8192K)], 0.0358250 secs] [Times: user=0.41 sys=0.01, real=0.04 secs] 

分析堆内存

[GC (Metadata GC Threshold) [PSYoungGen: 55746K->128K(1397248K)] 120040K->64422K(4193792K), 0.0013956 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] [Full GC (Metadata GC Threshold) [PSYoungGen: 128K->0K(1397248K)] [ParOldGen: 64294K->64222K(2796544K)] 64422K->64222K(4193792K), [Metaspace: 5026K->5026K(8192K)], 0.0358250 secs] [Times: user=0.41 sys=0.01, real=0.04 secs] 

查看上面结果发现在堆内存中新生代变为了1.5G老年代变为2.6G。猜想没有发生内存溢出可能是由于堆内存大小影响。调整虚拟机参数。

-Xmx10m -Xms10m -XX:+PrintGCDetails -XX:-UseCompressedClassPointers -XX:MaxMetaspaceSize=5m

运行结果

[GC (Metadata GC Threshold) [PSYoungGen: 0K->0K(2560K)] 641K->641K(9728K), 0.0003189 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Metadata GC Threshold) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 641K->641K(7168K)] 641K->641K(9728K), [Metaspace: 5029K->5029K(8192K)], 0.0027122 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
[GC (Last ditch collection) [PSYoungGen: 0K->0K(2560K)] 641K->641K(9728K), 0.0004008 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Last ditch collection) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 641K->641K(7168K)] 641K->641K(9728K), [Metaspace: 5029K->5029K(8192K)], 0.0026181 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 

  这里截取了其中的一段时间内的GC操作,从上面的操作内容中可以看出,程序执行过程中根本就没有使用到堆内存,也就是说动态代理使用到的就是Metaspace内存。这个时候对堆内存大小的设置已经不会影响到内存溢出了

调整参数

-Xmx1m -Xms1m -XX:+PrintGCDetails -XX:-UseCompressedClassPointers -XX:MaxMetaspaceSize=5m

运行结果

开始
[GC (Allocation Failure) [PSYoungGen: 512K->496K(1024K)] 512K->496K(1536K), 0.0008448 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1008K->512K(1024K)] 1008K->528K(1536K), 0.0005287 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
运行改变
[Full GC (Ergonomics) [PSYoungGen: 512K->358K(1024K)] [ParOldGen: 438K->187K(512K)] 950K->545K(1536K), [Metaspace: 3425K->3425K(8192K)], 0.0035669 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) --[PSYoungGen: 870K->870K(1024K)] 1057K->1375K(1536K), 0.0025170 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 870K->0K(1024K)] [ParOldGen: 504K->361K(512K)] 1375K->361K(1536K), [Metaspace: 3521K->3521K(8192K)], 0.0051245 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]
运行稳定
[Full GC (Ergonomics) [PSYoungGen: 512K->0K(1024K)] [ParOldGen: 442K->482K(512K)] 954K->482K(1536K), [Metaspace: 3802K->3802K(8192K)], 0.0047872 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 512K->0K(1024K)] [ParOldGen: 482K->476K(512K)] 994K->476K(1536K), [Metaspace: 3878K->3878K(8192K)], 0.0082984 secs] [Times: user=0.04 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 512K->231K(1024K)] [ParOldGen: 476K->425K(512K)] 988K->657K(1536K), [Metaspace: 3951K->3951K(8192K)], 0.0044978 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 512K->188K(1024K)] [ParOldGen: 425K->425K(512K)] 937K->613K(1536K), [Metaspace: 4058K->4058K(8192K)], 0.0042740 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]

这样的配置之后会发现Metaspace 大小也变化了,也就是说在开始的时候堆内存中根本连基本的加载虚拟机系统类的空间都没有,这样就导致整个虚拟机内存分配只能支持虚拟机的运行,根本无法支持应用的运行。这个测试看上去毫无意义,但是为笔者更好的理解java程序虚拟机创建原理有很大的帮助,后续的博客中会更新这部分内容。

注意
  在垃圾回收日志中有两种标识GC和Full GC,这两种标识可以这样理解,GC标识新生代的GC,而FullGC标识老年代GC和Metaspace GC。(仅限个人理解)

总结

  上面还有很多的提到的参数没有进行测试,兴趣的读者可以参照笔者的代码对参数进行测试,这里有一点需要说明的是,在这个例子中,为了测试Metaspace的参数可以将 -Xmx、-Xms 等参数调小点,会看到不一样的结果哦!

JVM优化系列-详解JDK1.8 Metaspace 参数配置相关推荐

  1. JVM优化系列-详解JVM堆内存分析

    导语   了解过java虚拟机的读者都知道,在JVM的内存可以分为堆内存和非堆内存,在之前的博客中分享了关于JVM常见参数的配置.这次分享的内容主要是对堆和非堆内存参数的配置   在Java程序运行的 ...

  2. JVM优化系列-详解常用的虚拟机调优参数

    导语   需要对虚拟机进行诊断,首先需要了解如何进行虚拟机的配合和跟踪,这里就来说说有那些虚拟机配置参数,通过它们来对虚拟机进行跟踪和配置. 文章目录 虚拟机跟踪调试参数 如何读懂虚拟机日志 GC基本 ...

  3. JVM由浅入深系列——详解垃圾收集器与内存分配策略

    文章目录 一.内存分配策略 1.引用计数算法 2.可达性分析算法 3.标记清除算法 4.标记复制算法 5.标记整理算法 二.收集器 1.Serial收集器 2.ParNew收集器 3.Parallel ...

  4. JDK自带JVM分析工具详解

    JDK自带JVM分析工具详解 1. JVM分析工具概述 1.1 JVM分析工具简介 1.2 JVM分析工具分类 2. JVM分析工具详解 2.1 idea环境配置 2.2 jps 2.3 jinfo ...

  5. Ceph优化系列(二):Ceph主要配置参数详解

    转载:Ceph配置参数详解 概述 Ceph的配置参数很多,从网上也能搜索到一大批的调优参数,但这些参数为什么这么设置?设置为这样是否合理?解释的并不多 本文从当前我们的ceph.conf文件入手,解释 ...

  6. 【JAVA进阶】JVM第二篇- JVM 垃圾回收详解

    写在前面的话 脑子是个好东西,可惜的是一直没有搞懂脑子的内存删除机制是什么,所以啊,入行多年,零零散散的文章看了无数,却总是学习了很多也忘了很多. 痛定思痛的我决定从今天开始系统的梳理下知识架构,记录 ...

  7. 5W字高质量java并发系列详解教程(上)-附PDF下载

    文章目录 第一章 java.util.concurrent简介 主要的组件 Executor ExecutorService ScheduledExecutorService Future Count ...

  8. [java] 虚拟机(JVM)底层结构详解[转]

    [java] 虚拟机(JVM)底层结构详解[转] 本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 在以前的博客里面,我们介绍了在java领 ...

  9. Keras深度学习实战(3)——神经网络性能优化技术详解

    Keras深度学习实战(3)--神经网络性能优化技术详解 0. 前言 1. 缩放输入数据集 1.1 数据集缩放的合理性解释 1.2 使用缩放后的数据集训练模型 2. 输入值分布对模型性能的影响 3. ...

最新文章

  1. mac下 VisualBox 虚拟机转移到活动硬盘,出现 UUID 错误
  2. IOS开发基础之异步下载网络图片第1部分
  3. Android之elevation实现阴影效果
  4. centos下搭建Jenkins持续集成环境(安装jenkins)
  5. 【机器学习】监督学习--(分类)非线性逻辑回归
  6. Struts 配置文件
  7. 虚拟化qemu-img的简单用法。
  8. pthread库实现一个简单的任务池
  9. TFS2010用户解锁
  10. 【python】Torch not compiled with CUDA enabled
  11. kettle spoon 连接mysql数据库
  12. 两款程序员的好帮手——BitNami,Hoo WinTail
  13. 如何压缩图片?手把手教你三种图片缩小的办法
  14. fpga图像处理------常用算法(二)
  15. nose中的一段代码...
  16. 这样做数据可视化驾驶舱,高端大气,一目了然,领导不点赞都难
  17. 打造山寨手机中的App Store--斯凯MiniJ(mrp)诞生记
  18. 家用计算机的辐射,家用电脑辐射多大
  19. 外星人跑深度学习_P106真香?低成本深度学习平台搭建
  20. html5 报名页面,h5报名页性能优化总结

热门文章

  1. 迅雷游戏盒子下载|迅雷游戏盒子下载
  2. Elasticsearch集群监控工具bigdesk插件安装
  3. IIS OCIEnvCreate failed with return code -1
  4. Java中接口定义成员变量
  5. 更多核心、更大内存、更低成本 AMD皓龙6000欲成云计算基石
  6. 如何选择WEB报表工具(二)
  7. Vue项目部署遇到的问题及解决方案
  8. 一个失败的创意:GPGPU纹理化通用加速kD树的实现
  9. 美国国土安全部发布物联网安全最佳实践
  10. Apache Kafka – KIP 32,33 Time Index