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 |
使用全并行后比全串行的吞吐量增加 |