JVM故障诊断与性能优化-垃圾收集器与内存分配(四)

1.垃圾收集器

相关概念见:深入理解jvm--垃圾收集器与内存分配策略(二)

垃圾收集器的开关

参数

新生代使用的GC

老年代使用的GC

-XX:+UseSerialGC

serialGC

serialOldGC

-XX:+UseParNewGC

ParNewGC

serialOldGC

-XX:+UseParallelGC

ParallelGC

serialOldGC

-XX:+UseParallelOldGC

ParallelGC

ParallelOldGC

-XX:+UseConcMarkSweepGC

ParNewGC

CMS

-XX:+UseG1GC

G1

G1


CMS收集器的相关参数:

-XX:ConcGCThreads/-XX:ParallelCMSThreads

设置并发线程数量

-XX:CMSInitiatingOccupancyFraction 

设置回收阈值,默认空间使用率为68%时进行回收。

 -XX:+UseCMSCompactAtFullCollection    

 进行碎片整理

 -XX:CMSFullGCsBeforeCompaction

 进行制定次数的CMS回收后进行内存压缩

 -XX:+CMSClassUnloadingEnabled

 回收Perm区的class数据

G1收集器相关的参数:

-XX:MaxGCPauseMillis

制定目标的最大停顿时间

-XX:ParallelGCThreads

设置工作线程的数量

-XX:InitiatingHeapOccupancyPercent

达到指定的堆使用率时进行并发标记周期的执行

示例1--垃圾回收日志的阅读

package chapter5;

public class GCtools {
	private final static int _1MB = 1024 * 1024;

	public static void allocation() {
		byte[] allocation1, allocation2, allocation3, allocation4, allocation5;
		allocation1 = new byte[6 * _1MB];
		allocation2 = new byte[6 * _1MB];
		allocation3 = new byte[1 * _1MB];
		allocation3 = null;
		allocation4 = new byte[1 * _1MB];
		allocation4 = null;
		allocation5 = new byte[1 * _1MB];
	}

	public static void main(String[] args) {
		allocation();
	}
}

输出结果列表

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+UseG1GC -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

0.087: [GC pause (young) (initial-mark), 0.0016104 secs] //发生了一次新生代GC,在0.087秒开始,耗时0.0016秒

   [Parallel Time: 1.4 ms, GC Workers: 4]//所有GC线程总的花费时间

      [GC Worker Start (ms): Min: 87.3, Avg: 87.4, Max: 87.4, Diff: 0.1]//给出每一个线程的执行情况。

      [Ext Root Scanning (ms): Min: 0.5, Avg: 0.7, Max: 1.2, Diff: 0.6, Sum: 3.0]//根扫描的耗时

      [Code Root Marking (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]

      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]//更新记忆集耗时(Remembered Set耗时)

         [Processed Buffers: Min: 0, Avg: 2.3, Max: 5, Diff: 5, Sum: 9]

      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]//扫描RS时间

      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]

      [Object Copy (ms): Min: 0.1, Avg: 0.6, Max: 0.7, Diff: 0.6, Sum: 2.2]//在正式回收时,G1会对被回收的对象进行疏散,即将存活的对象放置在其他区域,所以要复制对象。

      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]//GC工作线程的终止信息

      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.0, Sum: 0.1]//GC线程在其它任务中的耗时

      [GC Worker Total (ms): Min: 1.3, Avg: 1.4, Max: 1.4, Diff: 0.0, Sum: 5.5]

      [GC Worker End (ms): Min: 88.7, Avg: 88.7, Max: 88.7, Diff: 0.0]//显示GC工作线程完成的时间

   [Code Root Fixup: 0.0 ms]

   [Code Root Migration: 0.0 ms]

   [Clear CT: 0.0 ms]//清空cartTable的时间,RS就是依靠CardTable来记录存活对象。

   [Other: 0.2 ms]//显示其它几个任务的耗时

      [Choose CSet: 0.0 ms]

      [Ref Proc: 0.1 ms]

      [Ref Enq: 0.0 ms]

      [Free CSet: 0.0 ms]

   [Eden: 1024.0K(10.0M)->0.0B(9216.0K) Survivors: 0.0B->1024.0K Heap: 6784.0K(20.0M)->6696.0K(20.0M)]//GC回收的整体情况

 [Times: user=0.00 sys=0.00, real=0.00 secs]

0.089: [GC concurrent-root-region-scan-start]

0.090: [GC concurrent-root-region-scan-end, 0.0003651 secs]

0.090: [GC concurrent-mark-start]

0.090: [GC concurrent-mark-end, 0.0000936 secs]

0.092: [GC remark 0.092: [GC ref-proc, 0.0001257 secs], 0.0004546 secs]

 [Times: user=0.00 sys=0.00, real=0.00 secs]

0.093: [GC cleanup 13M->7740K(20M), 0.0002530 secs]

 [Times: user=0.00 sys=0.00, real=0.00 secs]

0.093: [GC concurrent-cleanup-start]

0.093: [GC concurrent-cleanup-end, 0.0000181 secs]

Heap

 garbage-first heap   total 20480K, used 9768K [0x00000000f9a00000, 0x00000000fae00000, 0x00000000fae00000)

  region size 1024K, 2 young (2048K), 1 survivors (1024K)

 compacting perm gen  total 20480K, used 2569K [0x00000000fae00000, 0x00000000fc200000, 0x0000000100000000)

   the space 20480K,  12% used [0x00000000fae00000, 0x00000000fb0826d8, 0x00000000fb082800, 0x00000000fc200000)

No shared spaces configured.

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

0.079: [GC0.079: [ParNew: 6980K->484K(9216K), 0.0040167 secs] 6980K->6630K(19456K), 0.0041330 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.084: [GC0.084: [ParNew: 7826K->7826K(9216K), 0.0000200 secs]0.084: [CMS: 6146K->6144K(10240K), 0.0063789 secs] 13972K->12751K(19456K), [CMS Perm : 2563K->2562K(21248K)], 0.0064763 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

0.091: [GC [1 CMS-initial-mark: 6144K(10240K)] 13775K(19456K), 0.0002722 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.091: [CMS-concurrent-mark-start]

0.091: [GC0.091: [ParNew (promotion failed): 7631K->8298K(9216K), 0.0017036 secs]0.093: [CMS0.094: [CMS-concurrent-mark: 0.002/0.003 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

 (concurrent mode failure): 6146K->6144K(10240K), 0.0052340 secs] 13775K->12751K(19456K), [CMS Perm : 2562K->2562K(21248K)], 0.0070064 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

晋升失败的原因:晋升对象大于平均晋升对象的大小,或者发生异常。

并发模式失败的原因:一个是在年老代被用完之前不能完成对无引用对象的回收;一个是当新空间分配请求在年老代的剩余空间中得到满足

2.内存分配和回收的细节问题

1.禁用System.gc()

使用参数-XX:+DisableExplicitGC可禁止手工触发GC。

2.System.gc()使用并发回收

显示GC默认使用串行方式进行回收,使用“+ExplicitGCInvokesConcurrent”会采用并发方式进行回收。

3.并行GC前额外触发新生代的GC

示例2--并发收集器FullGC前的新生代GC

package chapter5;

public class ScavengeBeforeFullGC {
	public static void main(String[] args) {
		System.gc();
	}
}

使用串行收集器并打印GC日志:

[Full GC[Tenured: 0K->464K(86400K), 0.0038260 secs] 1382K->464K(125248K), [Perm : 2562K->2562K(21248K)], 0.0038951 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

使用并行收集器并打印GC日志:(-XX:+PrintGCDetails -XX:+UseParallelGC)

[GC [PSYoungGen: 1331K->600K(38400K)] 1331K->600K(124416K), 0.0015175 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC [PSYoungGen: 600K->0K(38400K)] [ParOldGen: 0K->464K(86016K)] 600K->464K(124416K) [PSPermGen: 2562K->2561K(21504K)], 0.0109997 secs] [Times: user=0.05 sys=0.00, real=0.01 secs] 

禁用新生代GC,(-XX:+PrintGCDetails -XX:+UseParallelGC -XX:-ScavengeBeforeFullGC)

[Full GC [PSYoungGen: 1331K->0K(38400K)] [ParOldGen: 0K->464K(86016K)] 1331K->464K(124416K) [PSPermGen: 2562K->2561K(21504K)], 0.0106025 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

可见,显示GC实际上出发了两次GC。尽可能地缩短一次GC所用的时间。

4.对象何时进入老年代

示例3--初创的对象在eden区

package chapter5;
//jvm参数:-Xmx64M -Xms64M -XX:+PrintGCDetails
public class AllocEden {
	public static final int _1k = 1024;
	public static void main(String[] args) {
		for (int i = 0; i < 5*_1k; i++) {
			byte[] b= new byte[_1k];
		}
	}
}

输出结果:

Heap
 PSYoungGen      total 19456K, used 6774K [0x00000000fea80000, 0x0000000100000000, 0x0000000100000000)
  eden space 16896K, 40% used [0x00000000fea80000,0x00000000ff11dbd0,0x00000000ffb00000)
  from space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
  to   space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
 ParOldGen       total 44032K, used 0K [0x00000000fbf80000, 0x00000000fea80000, 0x00000000fea80000)
  object space 44032K, 0% used [0x00000000fbf80000,0x00000000fbf80000,0x00000000fea80000)
 PSPermGen       total 21504K, used 2569K [0x00000000f6d80000, 0x00000000f8280000, 0x00000000fbf80000)
  object space 21504K, 11% used [0x00000000f6d80000,0x00000000f7002650,0x00000000f8280000)

示例4--老年对象进入老年代

package chapter5;

import java.util.HashMap;
import java.util.Map;

public class MaxTenuringThreshold {
	public static final int _1M = 1024*1024;
	public static final int _1k = 1024;
	public static void main(String[] args) {
		Map<Integer, byte[]> map = new HashMap<Integer, byte[]>();
		for(int i=0;i<5*_1k;i++){
			byte[] b = new byte[_1k];
			map.put(i, b);
		}
		for (int k = 0; k < 17; k++) {
			for(int i=0;i<270;i++){
				byte[] g = new byte[_1M];
			}
		}
	}
}

输出结果表:

-Xmx1024M -Xms1024M -XX:+PrintGCDetails -XX:+UseSerialGC -XX:MaxTenuringThreshold=15 -XX:+PrintHeapAtGC

{Heap before GC invocations=0 (full 0):

 def new generation   total 314560K, used 278926K [0x00000000bae00000, 0x00000000d0350000, 0x00000000d0350000)

  eden space 279616K,  99% used [0x00000000bae00000, 0x00000000cbe638c8, 0x00000000cbf10000)

  from space 34944K,   0% used [0x00000000cbf10000, 0x00000000cbf10000, 0x00000000ce130000)

  to   space 34944K,   0% used [0x00000000ce130000, 0x00000000ce130000, 0x00000000d0350000)

 tenured generation   total 699072K, used 0K [0x00000000d0350000, 0x00000000fae00000, 0x00000000fae00000)

   the space 699072K,   0% used [0x00000000d0350000, 0x00000000d0350000, 0x00000000d0350200, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2570K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb0828a0, 0x00000000fb082a00, 0x00000000fc2c0000)

No shared spaces configured.

[GC[DefNew: 278926K->5941K(314560K), 0.0053639 secs] 278926K->5941K(1013632K), 0.0054100 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Heap after GC invocations=1 (full 0):

 def new generation   total 314560K, used 5941K [0x00000000bae00000, 0x00000000d0350000, 0x00000000d0350000)

  eden space 279616K,   0% used [0x00000000bae00000, 0x00000000bae00000, 0x00000000cbf10000)

  from space 34944K,  17% used [0x00000000ce130000, 0x00000000ce6fd748, 0x00000000d0350000)

  to   space 34944K,   0% used [0x00000000cbf10000, 0x00000000cbf10000, 0x00000000ce130000)

 tenured generation   total 699072K, used 0K [0x00000000d0350000, 0x00000000fae00000, 0x00000000fae00000)

   the space 699072K,   0% used [0x00000000d0350000, 0x00000000d0350000, 0x00000000d0350200, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2570K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb0828a0, 0x00000000fb082a00, 0x00000000fc2c0000)

No shared spaces configured.

}

... ...

{Heap before GC invocations=15 (full 0):

 def new generation   total 314560K, used 285513K [0x00000000bae00000, 0x00000000d0350000, 0x00000000d0350000)

  eden space 279616K,  99% used [0x00000000bae00000, 0x00000000cbf05200, 0x00000000cbf10000)

  from space 34944K,  17% used [0x00000000ce130000, 0x00000000ce6fd5c0, 0x00000000d0350000)

  to   space 34944K,   0% used [0x00000000cbf10000, 0x00000000cbf10000, 0x00000000ce130000)

 tenured generation   total 699072K, used 0K [0x00000000d0350000, 0x00000000fae00000, 0x00000000fae00000)

   the space 699072K,   0% used [0x00000000d0350000, 0x00000000d0350000, 0x00000000d0350200, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2570K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb0828a0, 0x00000000fb082a00, 0x00000000fc2c0000)

No shared spaces configured.

[GC[DefNew: 285513K->0K(314560K), 0.0046427 secs] 285513K->5941K(1013632K), 0.0046635 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

Heap after GC invocations=16 (full 0):

 def new generation   total 314560K, used 0K [0x00000000bae00000, 0x00000000d0350000, 0x00000000d0350000)

  eden space 279616K,   0% used [0x00000000bae00000, 0x00000000bae00000, 0x00000000cbf10000)

  from space 34944K,   0% used [0x00000000cbf10000, 0x00000000cbf10088, 0x00000000ce130000)

  to   space 34944K,   0% used [0x00000000ce130000, 0x00000000ce130000, 0x00000000d0350000)

 tenured generation   total 699072K, used 5941K [0x00000000d0350000, 0x00000000fae00000, 0x00000000fae00000)

   the space 699072K,   0% used [0x00000000d0350000, 0x00000000d091d538, 0x00000000d091d600, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2570K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb0828a0, 0x00000000fb082a00, 0x00000000fc2c0000)

No shared spaces configured.

}

可以看到对象的年龄按照GC的次数逐渐增加,当达到设置的最大年龄时进入老年代

-Xmx1024M -Xms1024M -XX:+PrintGCDetails -XX:MaxTenuringThreshold=15 -XX:+UseSerialGC -XX:+PrintHeapAtGC -XX:TargetSurvivorRatio=15

... ...

{Heap before GC invocations=1 (full 0):

 def new generation   total 314560K, used 285114K [0x00000000bae00000, 0x00000000d0350000, 0x00000000d0350000)

  eden space 279616K,  99% used [0x00000000bae00000, 0x00000000cbea1308, 0x00000000cbf10000)

  from space 34944K,  17% used [0x00000000ce130000, 0x00000000ce6fd748, 0x00000000d0350000)

  to   space 34944K,   0% used [0x00000000cbf10000, 0x00000000cbf10000, 0x00000000ce130000)

 tenured generation   total 699072K, used 0K [0x00000000d0350000, 0x00000000fae00000, 0x00000000fae00000)

   the space 699072K,   0% used [0x00000000d0350000, 0x00000000d0350000, 0x00000000d0350200, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2570K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb0828a0, 0x00000000fb082a00, 0x00000000fc2c0000)

No shared spaces configured.

[GC[DefNew: 285114K->0K(314560K), 0.0059892 secs] 285114K->5941K(1013632K), 0.0060118 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

Heap after GC invocations=2 (full 0):

 def new generation   total 314560K, used 0K [0x00000000bae00000, 0x00000000d0350000, 0x00000000d0350000)

  eden space 279616K,   0% used [0x00000000bae00000, 0x00000000bae00000, 0x00000000cbf10000)

  from space 34944K,   0% used [0x00000000cbf10000, 0x00000000cbf10088, 0x00000000ce130000)

  to   space 34944K,   0% used [0x00000000ce130000, 0x00000000ce130000, 0x00000000d0350000)

 tenured generation   total 699072K, used 5941K [0x00000000d0350000, 0x00000000fae00000, 0x00000000fae00000)

   the space 699072K,   0% used [0x00000000d0350000, 0x00000000d091d538, 0x00000000d091d600, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2570K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb0828a0, 0x00000000fb082a00, 0x00000000fc2c0000)

No shared spaces configured.

}

{Heap before GC invocations=2 (full 0):

 def new generation   total 314560K, used 279419K [0x00000000bae00000, 0x00000000d0350000, 0x00000000d0350000)

  eden space 279616K,  99% used [0x00000000bae00000, 0x00000000cbedec00, 0x00000000cbf10000)

  from space 34944K,   0% used [0x00000000cbf10000, 0x00000000cbf10088, 0x00000000ce130000)

  to   space 34944K,   0% used [0x00000000ce130000, 0x00000000ce130000, 0x00000000d0350000)

 tenured generation   total 699072K, used 5941K [0x00000000d0350000, 0x00000000fae00000, 0x00000000fae00000)

   the space 699072K,   0% used [0x00000000d0350000, 0x00000000d091d538, 0x00000000d091d600, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2570K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb0828a0, 0x00000000fb082a00, 0x00000000fc2c0000)

No shared spaces configured.

}

可见,当from区达到目标使用率时,对象会提前进入老年代

示例4--大对象直接进入老年代

package chapter5;

import java.util.HashMap;
import java.util.Map;

public class PreTenureSizeThreshold {
	public static final int _1K = 1024;
	public static void main(String[] args) {
		Map<Integer, byte[]> map = new HashMap<Integer, byte[]>();
		for(int i=0;i<5*_1K;i++){
			byte[] b = new byte[_1K];
			map.put(i, b);
		}
	}
}

输出结果表:

-Xmx32M -Xms32M -XX:+UseSerialGC -XX:+PrintGCDetails

Heap

 def new generation   total 9792K, used 6647K [0x00000000f8e00000, 0x00000000f98a0000, 0x00000000f98a0000)

  eden space 8704K,  76% used [0x00000000f8e00000, 0x00000000f947dfb8, 0x00000000f9680000)

  from space 1088K,   0% used [0x00000000f9680000, 0x00000000f9680000, 0x00000000f9790000)

  to   space 1088K,   0% used [0x00000000f9790000, 0x00000000f9790000, 0x00000000f98a0000)

 tenured generation   total 21888K, used 0K [0x00000000f98a0000, 0x00000000fae00000, 0x00000000fae00000)

   the space 21888K,   0% used [0x00000000f98a0000, 0x00000000f98a0000, 0x00000000f98a0200, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2576K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb084318, 0x00000000fb084400, 0x00000000fc2c0000)

No shared spaces configured.

可以看到,所有对象都分配在新生代

-Xmx32M -Xms32M -XX:+UseSerialGC -XX:+PrintGCDetails -XX:PretenureSizeThreshold=1000

Heap

 def new generation   total 9792K, used 6648K [0x00000000f8e00000, 0x00000000f98a0000, 0x00000000f98a0000)

  eden space 8704K,  76% used [0x00000000f8e00000, 0x00000000f947e1b0, 0x00000000f9680000)

  from space 1088K,   0% used [0x00000000f9680000, 0x00000000f9680000, 0x00000000f9790000)

  to   space 1088K,   0% used [0x00000000f9790000, 0x00000000f9790000, 0x00000000f98a0000)

 tenured generation   total 21888K, used 0K [0x00000000f98a0000, 0x00000000fae00000, 0x00000000fae00000)

   the space 21888K,   0% used [0x00000000f98a0000, 0x00000000f98a0000, 0x00000000f98a0200, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2576K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb084318, 0x00000000fb084400, 0x00000000fc2c0000)

No shared spaces configured.

当设置对象晋升老年代的大小后,对象并没有进入老年代。

-Xmx32M -Xms32M -XX:+UseSerialGC -XX:+PrintGCDetails -XX:PretenureSizeThreshold=1000 -XX:-UseTLAB

Heap

 def new generation   total 9792K, used 704K [0x00000000f8e00000, 0x00000000f98a0000, 0x00000000f98a0000)

  eden space 8704K,   8% used [0x00000000f8e00000, 0x00000000f8eb0230, 0x00000000f9680000)

  from space 1088K,   0% used [0x00000000f9680000, 0x00000000f9680000, 0x00000000f9790000)

  to   space 1088K,   0% used [0x00000000f9790000, 0x00000000f9790000, 0x00000000f98a0000)

 tenured generation   total 21888K, used 5413K [0x00000000f98a0000, 0x00000000fae00000, 0x00000000fae00000)

   the space 21888K,  24% used [0x00000000f98a0000, 0x00000000f9de9590, 0x00000000f9de9600, 0x00000000fae00000)

 compacting perm gen  total 21248K, used 2576K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)

   the space 21248K,  12% used [0x00000000fae00000, 0x00000000fb084318, 0x00000000fb084400, 0x00000000fc2c0000)

No shared spaces configured.

 当禁用对象在TLAB上分配后,可以看到大对象进入了老年代。

示例5--TLAB上分配对象

package chapter5;

public class UseTLAB {
	public static void alloc(){
		byte[] b = new byte[2];
		b[0] = 1;
	}
	public static void main(String[] args) {
		long b = System.currentTimeMillis();
		for(int i=0;i<10000000;i++){
			alloc();
		}
		long e = System.currentTimeMillis();
		System.out.println(e-b);
	}
}

输出结果表:

-XX:+UseTLAB -Xcomp -XX:-BackgroundCompilation -XX:-DoEscapeAnalysis -server

-XX:-UseTLAB -Xcomp -XX:-BackgroundCompilation -XX:-DoEscapeAnalysis -server

由于TLAB空间不会太大,大对象直接分配在堆上,TLAB空间较小因此有两种选择,一种是废弃当前的TLAB,另一种是直接分配到堆上。

-XX:+UseTLAB -XX:+PrintTLAB -XX:+PrintGC -XX:TLABSize=102400 -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=100 -XX:-DoEscapeAnalysis -server

TLAB: gc thread: 0x000000000b25e800 [id: 9912] desired_size: 100KB(TLAB的大小) slow allocs: 0(慢分配次数)  refill waste: 1024B alloc: 0.15024     5000KB refills: 1 waste 99.7% gc: 102080B slow: 0B fast: 0B

TLAB: gc thread: 0x0000000002e90800 [id: 104] desired_size: 100KB slow allocs: 1  refill waste: 1024B alloc: 0.15024     5000KB refills: 332 waste  0.0% gc: 0B slow: 5920B fast: 0B

TLAB totals: thrds: 2  refills: 333 max: 332 slow allocs: 1 max 1 waste:  0.3% gc: 102080B max: 102080B slow: 5920B max: 5920B fast: 0B max: 0B

[GC 33280K->568K(124416K), 0.0013079 secs]

... ...

296

当设置TLAB阈值后,大于TLAB空间*(1/阈值)的对象会直接在堆上分配


5.对象的分配流程


6.finalize方法对垃圾回收的影响

1.会导致对象复活。

2.执行时间没有保障,若不发生GC,则没有机会执行

3.耗时的finalize方法影响GC性能

示例5--finalize影响GC效率

package chapter5;
//-Xmx64M -Xms64M -XX:+PrintGCDetails
public class LongFinalize {
	public static  class LF{
		private byte[] content = new byte[512];
		@Override
		protected void finalize() throws Throwable {
			try{
				System.out.println(Thread.currentThread().getId());
				Thread.sleep(1000);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		long b = System.currentTimeMillis();
		for(int i=0;i<50000;i++){
			LF f = new LF();
		}
		long e = System.currentTimeMillis();
		System.out.println(e-b);
	}
}

查看快照:


3.垃圾回收器对tomcat性能影响实验

1.配置JMeter

添加线程组


添加采样器,输入服务器地址



配置监听器


2.配置tomcat的jvm参数

有两种方式,一种是在Catalina.bat中直接添加,另一种是新建批处理程序setenv.bat进行添加:



CATALINA_OPTS用于控制tomcat本身的虚拟机参数,而JAVA_OPTS用于控制tomcat的全部进程使用。

参数不同时的报告:

set CATALINA_OPTS=-Xloggc:gc.log -XX:+PrintGCDetails -Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:+UseSerialGC -XX:PermSize=32M

set CATALINA_OPTS=-Xloggc:gc.log -XX:+PrintGCDetails -Xmx512M -XX:MaxPermSize=32M -XX:+HeapDumpOnOutOfMemoryError -XX:+UseSerialGC

当最大堆扩大后,系统的吞吐量显著提升

set CATALINA_OPTS=-Xloggc:gc.log -XX:+PrintGCDetails -Xmx512M -Xms64M -XX:MaxPermSize=32M -XX:+UseSerialGC

修改初始堆大小后,系统GC次数减少,吞吐量无明显变化

set CATALINA_OPTS=-Xloggc:gc.log -XX:+PrintGCDetails -Xmx512M -Xms64M -XX:MaxPermSize=32M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:ParallelGCThreads=4

在使用并发垃圾回收器后,由于GC压力不大,吞吐量并无明显变化

set CATALINA_OPTS=-Xloggc:gc.log -XX:+PrintGCDetails -Xmx40M -Xms40M -XX:MaxPermSize=32M -XX:+UseSerialGC

减小堆的大小后,GC压力变大,吞吐量增加。

set CATALINA_OPTS=-Xloggc:gc.log -XX:+PrintGCDetails -Xmx40M -Xms40M -XX:MaxPermSize=32M -XX:+UseParallelOldGC -XX:ParallelGCThreads=4

在有一定的GC压力后,使用并发收集器吞吐量有明显的增加

set CATALINA_OPTS=-Xloggc:gc.log -XX:+PrintGCDetails -Xmx40M -Xms40M -XX:MaxPermSize=32M -XX:+UseParNewGC

使用全并行后比全串行的吞吐量增加




猜你喜欢

转载自blog.csdn.net/yinweicheng/article/details/80678653