JVM探索-6.JVM日志与G1简要参数

时间:2022-11-5 14:29     作者:林立     分类:


  如果启动JVM的时候我们没有指定参数,则可以通过设置Java -XX:+Print CommandLineFlags这个参数让JVM打印出那些已经被用户或者JVM设置过的详细的XX参数的名称和值。例如我们可以得到JVM使用的默认垃圾收集器,如下:

-XX:InitialHeapSize=266930688 -XX:MaxHeapSize=4270891008 
-XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation 
-XX:+UseParallelGC

  如果指定G1作为垃圾回收,但是没有指定堆空间的参数,当发生GC的时候,我们可以看到:

-Xmx256M -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions 
-XX:G1LogLevel=finest -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 
-XX:+UseAdaptiveSizePolicy
garbage-first heap   total 131072K, used 37569K [0x00000000f8000000, 
  0x00000000f8100400, 0x0000000100000000)
  region size 1024K, 24 young (24576K), 0 survivors (0K)

  Eden开始之前是24MB,主要来自于预测值,且24个分区,即每个分区都是1MB。
  第一次GC后的堆空间信息如下所示:

[Eden: 24.0M(24.0M)->0.0B(13.0M) Survivors: 0.0B->3072.0K Heap: 
  24.0M(128.0M)->12.9M(128.0M)]

  GC之后Eden设置为13M,来自于256M×5%=12.8MB,取整后就是13MB,并且满足预测时间。其中,256M是堆的大小,5%是G1 NewSizePercent指定的默认值。
  上面已经详细介绍了G1中堆大小和新生代大小的计算、分区设置、G1的停顿预测模型以及停顿预测模型中的几个参数。这里给出使用中的一些注意事项:
   - 参数G1HeapRegionSize指定堆分区大小。分区大小可以指定,也可以不指定;不指定时,由内存管理器启发式推断分区大小。
   - 参数xms/xmx指定堆空间的最小值/最大值。一定要正确设置xms/xmx,否则将使用默认配置,将影响分区大小推断。
   - 在以前的内存管理器中(非G1),为了防止新生代因为内存不断地重新分配导致性能变低,通常设置Xmn或者NewRatio。但是G1中不要设置MaxNewSize、NewSize、Xmn和NewRatio。原因有两个,第一G1对内存的管理不是连续的,所以即使重新分配一个堆分区代价也不高,第二也是最重要的,G1的目标满足垃圾收集停顿,这需要G1根据停顿时间动态调整收集的分区,如果设置了固定的分区数,即G1不能调整新生代的大小,那么G1可能不能满足停顿时间的要求。
   - 参数GCTimeRatio指的是GC与应用程序之间的时间占比,G1中默认值为9,表示GC与应用程序时间占比为10%。增大该值将减少GC占用的时间,带来的后果就是动态扩展内存更容易发生;在很多情况下10%已经很大,例如可以将该值设置为19,则表示GC时间不超过5%。
   - 根据业务请求变化的情况,设置合适的扩展G1ExpandByPercentOfAvailable速率,保持效率。
   - JVM在对新生代内存分配管理时,还有一个参数就是保留内存G1ReservePercent(默认值是10),即在初始化,或者内存扩展/收缩的时候会计算更新有多少个分区是保留的,在新生代分区初始化的时候,在空闲列表中保留一定比例的分区不使用,那么在对象晋升的时候就可以使用了,所以能有效地减小晋升失败的概率。这个值最大不超过50,即最多保留50%的空间,但是保留过多会导致新生代可用空间少,过少可能会增加新生代晋升失败,那将会导致更为复杂的串行回收。
   - G1NewSizePercent是一个实验参数,需要使用-XX:+UnlockExperimentalVMOptions才能改变选项。有实验表明G1在回收Eden分区的时候,大概每GB需要100ms,所以可以根据停顿时间,相应地调整。这个值在内存比较大的时候需要减少,例如32G可以设置-XX:G1NewSizePercent=3, 这样Eden至少保留大约1GB的空间,从而保证收集效率。
   - 参数MaxGCPauseMillis指期望停顿时间,可根据系统配置和业务动态调整。因为G1在垃圾收集的时候一定会收集新生代,所以需要配合新生代大小的设置来确定,如果该值太小,连新生代都不能收集完成,则没有任何意义,每次除了新生代之外只能多收集一个额外老生代分区。
   - 参数GCPauseIntervalMillisGC指GC间隔时间,默认值为0,GC启发式推断为MaxGCPauseMillis+1,设置该值必须要大于MaxGCPauseMillis。
   - 参数G1ConfidencePercent指GC预测置信度,该值越小说明基于过去历史数据的预测越准确,例如设置为0则表示收集的分区基本和过去的衰减均值相关,无波动,所以可以根据过去的衰减均值直接预测下一次预测的时间。反之该值越大,说明波动越大,越不准确,需要加上衰减方差来补偿。
   - JVM中提供了一个对象对齐的值ObjectAlignmentInBytes,默认值为8,需要明白该值对内存使用的影响,这个影响不仅仅是在JVM对对象的分配上面,正如上面看到的它也会影响对象在分配时的标记情况。注意这个值最少要和操作系统支持的位数一致才能提高对象分配的效率。所以32位系统最少是4,64位最少是8。一般不用修改该值。