1、JVM空间说明
- JDK 1.7及以前,java类的信息、常量池、静态变量都存在Permanent中,类的元数据和静态变量在类加载的时候分配到permanent中,只有当类被销毁的时候垃圾收集GC会从permanent中处理掉
- JDK 1.8 的对 JVM 架构的改造将类元数据放到本地内存中,将常量池和静态变量放到 Java 堆里。HotSoptVM 将会为类的元数据明确分配和释放本地内存。在这种架构下,类元信息就突破了原来 -XX:MaxPermSize 的限制,所以PermSize的配置也是无效的,现在可以使用更多的本地内存。这样就从一定程度上解决了原来在运行时生成大量类的造成经常 Full GC 问题,如运行时使用反射、代理等.
- 可以发现最明显的一个变化是元空间从虚拟机转移到本地内存;默认情况下,元空间的大小仅受本地内存的限制。这意味着以后不会因为永久代空间不够而抛出OOM异常了。jdk1.8以前版本的class和jar包数据存储在permGen下面 ,permGen大小是固定的,而且项目之间无法共用公有的class,所以很容易碰到OOM异常。
改成metaSpaces后,各个项目会共享同样的class内存空间,比如多个项目都引用了common包,在metaSpaces中只会存储common的class,提高了内存的利用率,垃圾回收更有效率。
2、JVM参数配置
1.在jdk1.8以前,生产环境一般有如下配置
-XX:PermSize=512M -XX:MaxPermSize=1024M
表示在JVM里存储Java类信息,常量池和静态变量的永久代区域初始大小为512M,最大为1024M。在项目启动后,这个值是固定的,如果项目class过多,很可能遇到OutOfMemoryError: PermGen异常。
2.升级JDK1.8之后,上面的perm配置已经变成
-XX:MetaspaceSize=512M XX:MaxMetaspaceSize=1024M
MetaspaceSize如果不做配置,通过jinfo查看默认MetaspaceSize大小(约21M),MaxMetaspaceSize很大很大,前面说过MetaSpace只受本地内存大小限制。MetaspaceSize为出发FullGC的阈值,默认约为21M,如做了配置,最小阈值为自定义配置大小。空间使用达到阈值,触发FullGC,同时对该值扩大。当然如果元空间实际使用小于阈值,在GC的时候也会对该值缩小。MaxMetaspaceSize为元空间的最大值,如果设置太小,可能会导致频繁FullGC,甚至OOM。
3、GarbageCollection过程
1、新new的对象都放在Eden区
2、Eden区满或者快满的时候进行一次清理(MinorGc),不被引用的对象直接被清理掉;还有引用的对象,但是年龄比较大的,挪到S0区
3、下次Eden区快满的时候,会进行上一步的操作,并且将Eden和S0区的年纪大的对象放到S1区,原理上随时保持S0和S1有一个是空的,用来存下一次的对象
4、下下次,Eden区快满的时候,会进行上一步操作,并且将Eden和S1区的年纪大的对象放到S0区,此时S1区就是空的
5、直到Eden区快满,S0或者S1也快满的时候,这时候就把这两个区的年纪大的对象放到Old区
6、依次循环,直到Old区也快满的时候,Eden区也快满的时候,会对整个这一块内存区域进行一次大清洗(FullGC),腾出内存,为之后的对象创建,程序运行腾地方。
清理Eden区和Survivor区叫Minor GC;清理Old区叫Major GC;清理整个堆空间—包括年轻代和老年代叫Full GC。
4、jvm建议配置
-XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -Xms256m -Xmx256m
设置元空间的初始值和最大值,设置堆空间的初始值和最大值。
MetaspaceSize要设置为128M?堆内存初始值Xms设置为256M而不是512M?
根据jdk官网的建议
Java堆大小设置,Xms 和 Xmx设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍
永久代 PermSize和MaxPermSize(元空间)设置为老年代存活对象的1.2-1.5倍。(1.8以后彻底抛弃了)
年轻代Xmn的设置为老年代存活对象的1-1.5倍。
老年代的内存大小设置为老年代存活对象的2-3倍
类加载统计:
jstat -class pid(进程号)
Loaded |
Bytes |
Unloaded |
Bytes |
Time |
9881 |
17877.5 |
0 |
0.0 |
43.05 |
加载class的数量 |
所占用空间大小 |
未加载数量 |
未加载占用空间 |
时间 |
编译统计
jstat -compiler pid(进程号)
Compiled |
Failed |
Invalid |
Time |
FailedType |
FailedMethod |
1735 |
0 |
0 |
14.09 |
0 |
编译数量 |
Failed:失败数量 |
Invalid:不可用数量 |
Time:时间 |
FailedType:失败类型 |
FailedMethod:失败的方法 |
垃圾回收统计
jstat -gc pid(进程号)
S0C |
S1C |
S0U |
S1U |
EC |
EU |
OC |
OU |
MC |
MU |
CCSC |
CCSU |
YGC |
YGCT |
FGC |
FGCT |
GCT |
第一个幸存区的大小 |
第二个幸存区的大小 |
第一个幸存区的使用大小 |
第二个幸存区的使用大小 |
伊甸园区的大小 |
伊甸园区的使用大小 |
老年代大小 |
老年代使用大小 |
方法区大小 |
方法区使用大小 |
压缩类空间大小 |
压缩类空间使用大小 |
年轻代垃圾回收次数 |
年轻代垃圾回收消耗时间 |
老年代垃圾回收次数 |
老年代垃圾回收消耗时间 |
垃圾回收消耗总时间 |
堆内存统计
jstat -gccapacity pid(进程号)
NGCMN |
NGCMX |
NGC |
S0C |
S1C |
EC |
OGCMN |
OGCMX |
OGC |
OC |
MCMN |
MCMX |
MC |
CCSMN |
CCSMX |
CCSC |
YGC |
FGC |
新生代最小容量 |
新生代最大容量 |
当前新生代容量 |
第一个幸存区大小 |
第二个幸存区的大小 |
伊甸园区的大小 |
老年代最小容量 |
老年代最大容量 |
当前老年代大小 |
当前老年代大小 |
最小元数据容量 |
最大元数据容量 |
当前元数据空间大小 |
最小压缩类空间大小 |
最大压缩类空间大小 |
当前压缩类空间大小 |
年轻代gc次数 |
老年代GC次数 |
新生代垃圾回收统计
jstat -gcnew pid(进程号)
S0C |
S1C |
S0U |
S1U |
TT |
MTT |
DSS |
EC |
EU |
YGC |
YGCT |
第一个幸存区大小 |
第二个幸存区的大小 |
第一个幸存区的使用大小 |
第二个幸存区的使用大小 |
对象在新生代存活的次数 |
对象在新生代存活的最大次数 |
期望的幸存区大小 |
伊甸园区的大小 |
伊甸园区的使用大小 |
年轻代垃圾回收次数 |
年轻代垃圾回收消耗时间 |
新生代内存统计
jstat -gcnewcapacity pid(进程号)
NGCMN |
NGCMX |
NGC |
S0CMX |
S0C |
S1CMX |
S1C |
ECMX |
EC |
YGC |
FGC |
新生代最小容量 |
新生代最大容量 |
当前新生代容量 |
最大幸存1区大小 |
当前幸存1区大小 |
最大幸存2区大小 |
当前幸存2区大小 |
最大伊甸园区大小 |
当前伊甸园区大小 |
年轻代垃圾回收次数 |
老年代回收次数 |
老年代垃圾回收统计
jstat -gcold pid(进程号)
MC |
MU |
CCSC |
CCSU |
OC |
OU |
YGC |
FGC |
FGCT |
GCT |
方法区大小 |
方法区使用大小 |
压缩类空间大小 |
压缩类空间使用大小 |
老年代大小 |
老年代使用大小 |
年轻代垃圾回收次数 |
老年代垃圾回收次数 |
老年代垃圾回收消耗时间 |
垃圾回收消耗总时间 |
老年代内存统计
jstat -gcoldcapacity pid(进程号)
OGCMN |
OGCMX |
OGC |
OC |
YGC |
FGC |
FGCT |
GCT |
老年代最小容量 |
老年代最大容量 |
当前老年代大小 |
老年代大小 |
年轻代垃圾回收次数 |
老年代垃圾回收次数 |
老年代垃圾回收消耗时间 |
垃圾回收消耗总时间 |
元数据空间统计
jstat -gcmetacapacity pid(进程号)
MCMN | MCMX | MC |CCSMN|CCSMX|CCSC|YGC|FGC|FGCT|GCT
--- |--- |--- |--- |--- |---|---|---|---|---|---
最小元数据容量 | 最大元数据容量|最大元数据容量|最小压缩类空间大小|最大压缩类空间大小|最大压缩类空间大小|年轻代垃圾回收次数|老年代垃圾回收次数|老年代垃圾回收消耗时间|垃圾回收消耗总时间
总结垃圾回收统计
jstat -gcutil pid(进程号)
S0 |
S1 |
E |
O |
M |
CCS |
YGC |
FGC |
FGCT |
GCT |
幸存1区当前使用比例 |
幸存2区当前使用比例 |
伊甸园区使用比例 |
老年代使用比例 |
元数据区使用比例 |
压缩使用比例 |
年轻代垃圾回收次数 |
老年代垃圾回收次数 |
老年代垃圾回收消耗时间 |
垃圾回收消耗总时间 |
JVM编译方法统计
jstat -printcompilation pid(进程号)
Compiled |Size|Type|Method
---| ---|---| ---|---
最近编译方法的数量|最近编译方法的字节码数量|最近编译方法的编译类型|方法名标识