常见参数
java启动参数
参数说明
-所有jvm实现都必须实现这些参数的功能,向后兼容-X默认jvm实现这些参数的功能,不保证所有jvm实现都满足,不保证向后兼容-XX各个jvm实现有所不同,可能会随时取消
输出jvm的信息参数
参数说明
-verbose:gc输出每次GC的相关信息-XX:+PrintGCDetails获取的信息比上面更多
更多信息
参数说明
-XX:PrintGCTimeStamps显示jvm启动到执行GC时流逝的时间,单位是秒-XX:PrintDateTimeStamps显示执行GC时的本地时间(Java 6 update 4才开始支持)-Xloggc:/Users/cc/Desktop/log.txtgc信息重定向到文件
解读log信息
CommandLine flags: -XX:InitialHeapSize=
134217728 -XX:MaxHeapSize=
2147483648 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
0.465: [GC (System.gc()) [PSYoungGen:
5341K->
851K(
38400K)]
5341K->
859K(
125952K),
0.0020406 secs] [
Times: user=
0.00 sys=
0.00, real=
0.00 secs]
0.467: [
Full GC (System.gc()) [PSYoungGen:
851K->
0K(
38400K)] [ParOldGen:
8K->
778K(
87552K)]
859K->
778K(
125952K), [Metaspace:
3653K->
3653K(
1056768K)],
0.0064182 secs] [
Times: user=
0.01 sys=
0.00, real=
0.01 secs]
Heap
PSYoungGen total
38400K, used
1553K [
0x0000000795580000,
0x0000000798000000,
0x00000007c0000000)
eden space
33280K,
4% used [
0x0000000795580000,
0x00000007957045f8,
0x0000000797600000)
from space
5120K,
0% used [
0x0000000797600000,
0x0000000797600000,
0x0000000797b00000)
to space
5120K,
0% used [
0x0000000797b00000,
0x0000000797b00000,
0x0000000798000000)
ParOldGen total
87552K, used
778K [
0x0000000740000000,
0x0000000745580000,
0x0000000795580000)
object space
87552K,
0% used [
0x0000000740000000,
0x00000007400c2ab8,
0x0000000745580000)
Metaspace used
3775K, capacity
4888K, committed
5120K, reserved
1056768K
class space used
419K, capacity
456K, committed
512K, reserved
1048576K
System.out.println(Runtime.getRuntime().maxMemory()); System.out.println(Runtime.getRuntime().freeMemory()); System.out.println(Runtime.getRuntime().totalMemory());
JVM内存结构
JVM的内存由栈寄存器和堆构成,堆里面有新生代、老年代和持久代。
Young(年轻代)
分为Eden(伊甸)区,两个survivor(存活)区。大部分对象(刚new出的对象)在Eden区,当Eden区满时,还存货的对象被复制到survivor区中的一个,当这个survivor区满时,此区的存活对象将被复制到另外一个survivor区,当这个survivor区满时,从第一个survivor区复制过来的并且此时还存活的对象,被复制到“老年代”。survivor总有一个是空的。
Tenured(老年代)
老年代存放从年轻代存活的对象,一般来说老年代存放的都是生命周期较长的对象
Perm(持久代)
用于存放静态文件,如java类,方法。持久代对垃圾回收没有显著影响.final修饰的常量,classLoader加载的信息。
GC的两种类型
ScavengeGC(Minor GC)Full GC
一般情况下,当新对象生成并且在Eden申请空间失败时,触发scavengeGC,堆Eden区域进行GC,清楚非存活对象,并将尚且存活的对象移动到survivor区,然后整理survivor的两个区对整个堆进行真理,包括young tenured和perm。触发:Eden区满触发full gc的三种原因:tenured被写满;perm被写满;System.gc()被显式调用新生代发生的垃圾回收操作,因为java对象大多具有朝生夕灭的特性,所以minorGC非常频繁,一般回收速度也比较快,通常在百毫秒级老年代GC(FullGC/MajorGC)发生在老年代的GC,出现了MajorGC经常会伴随至少一次的MinorGC(非绝对,在parallelscavenge收集器的手机策略里就有直接进行majorGC的策略选择过程)。majorGC的速度一般会比MinorGC慢10倍以上,1.4G的Old Gen进行一次回收通常需要20-40秒首次YGC:对Eden区进行垃圾回收,回收后Eden区中依然存活的对象被移入S0 第二次YGC:将s0中的对象复制到s1,并对Eden区和s1进行垃圾回收,回收后Eden区依然存活的对象被移入s1,并将s0中所有的对象清楚,以此类推,在S0/S1中存活次数超过N次(默认15次)的对象移入OldGen,如果S0/S1空间不足,则直接移入Old Gen对young gen,old gen,perm gen进行一次完整的垃圾回收,old gen不在被引用的对象直接销毁,young gen的回收算法同youngGC,perm GEM回收方式为,如果堆中不存在某个类的任何势力,且该类的Class对象没有在任何地方被引用,则该类被回收
虚拟机给每个对象定义了一个对象年龄(Age)计数器,如果对象在Eden出生并经过第一次MinorGC后仍然存活,并且能被survivor容纳的话,将被移动到survivor空间中,并将对象年龄设为1.对象在survivor区中每熬过一次MinorGC,年龄就增加一岁,当它的年龄增加到一定程度(默认为15岁)时,就会被晋升到老年代中。对象晋升老年代的年龄阈值 通过-XX:MaxTenuringThreshhold来设置
jstat -gcutil <pid> <timediff>
用jstat查看jvm内存使用情况
s0s1EOPYGCYGCTFGCFGCTGCT
S0区占用的空间比s1Eden区Old区Perm区YGC的次数YGCtime从程序启动到采用ygc所有的时间/sFGC次数FGC时间/s用于垃圾回收的总时间/s
xiejiangqiongdeMacBook-Pro:~ cc$ jstat -gcutil
5061 1000
Warning: Unresolved Symbol: sun
.gc.generation.2.space.0.capacity substituted NaN
Warning: Unresolved Symbol: sun
.gc.generation.2.space.0.used substituted NaN
Warning: Unresolved Symbol: sun
.gc.generation.2.space.0.capacity substituted NaN
S0 S1 E O P YGC YGCT FGC FGCT GCT
75.66 0.00 0.00 99.76 �
18 2.212 5 2.398 4.610
73.66 0.00 20.00 65.58 �
18 2.212 5 4.433 6.645
73.66 0.00 44.00 65.58 �
18 2.212 5 4.433 6.645
73.66 0.00 64.00 65.58 �
18 2.212 5 4.433 6.645
73.66 0.00 84.00 65.58 �
18 2.212 5 4.433 6.645
73.66 0.00 100.00 65.58 �
18 2.212 5 4.433 6.645
0.00 100.00 8.00 68.23 �
19 2.613 5 4.433 7.046
0.00 100.00 32.00 68.23 �
19 2.613 5 4.433 7.046
0.00 100.00 50.00 68.23 �
19 2.613 5 4.433 7.046
0.00 100.00 68.00 68.23 �
19 2.613 5 4.433 7.046
0.00 100.00 86.00 68.23 �
19 2.613 5 4.433 7.046
2.72 100.00 100.00 81.55 �
20 2.613 5 4.433 7.046
51.81 0.00 0.00 88.70 �
20 3.010 6 4.433 7.443
5.87 0.00 2.00 69.16 �
20 3.010 6 6.121 9.130
5.87 0.00 30.00 69.16 �
20 3.010 6 6.121 9.130
5.87 0.00 54.00 69.16 �
20 3.010 6 6.121 9.130
用ps -ef | grep java 查看待检测进程的id
uidpidppidcstimettycmd
用户ID进程ID父进程ID开始时间登录方式命令
从我的毕设中大量的FullGC看内存
内存泄露时会发生什么
某些对象会占用大量的JVM内存,且长时间无法被回收掉。这些长时间无法被回收的对象通常都会在Old Gen中由于Old Gen中存在大量无法被回收的对象,每次FullGC只能释放出极少的Old Gen空间,回收处的这少部分Old Gen空间又会很快被占满,这就会导致JVM在频繁地进行FullGCFullGC很慢,而JVM在做GC时会stop-the-world,在GC时终止JVM的一切工作。所以假设在内存泄露发生时,JVM被迫每40秒做一次FullFC,每次FullGC需要30秒,这就代表JVM只有1/4的时间在正常工作,此时的性能一定是非常慢的而随着泄露对象的不断增加,OldGen的可用空间会越来越少,最终JVM会回收不出足够的可用内容以支撑程序的运行,从而导致服务的彻底不可用
通过jstat观察Old Gen内存占用的增长速度,以及GC的频次
如果jstat命令输出的信息表示JVM正在频繁进行FullGC,那么基本而已肯定性能故障的原因是内存泄露 [Full GC (Ergonomics) 3344336K->3068858K(3749376K), 3.7187515 secs] [Full GC (Ergonomics) 3344336K->3091406K(3749376K), 3.2715931 secs] [Full GC (Ergonomics) 3344336K->3112195K(3749376K), 3.9227456 secs] [Full GC (Ergonomics) 3344336K->3139728K(3749376K), 3.5998555 secs]
参考博客
日志信息解读 IDEA JVM运行参数 JVM参数原理和性能调优 jvm调优总结+jstat分析 很好的总结 java gc的工作原理 minor gc full gc的原理 关于tomcat上的性能