jvm
Posted XiaoMaPro
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jvm相关的知识,希望对你有一定的参考价值。
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
Loaded | Bytes | Unloaded | Bytes | Time |
---|
加载class的数量 | 所占用空间大小 | 未加载数量 | 未加载占用空间 | 时间 |
编译统计
jstat -compiler pid(进程号)
Compiled | Failed | Invalid | Time | FailedType | FailedMethod |
---|
编译数量 | 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 |
---|
最近编译方法的数量 | 最近编译方法的字节码数量 | 最近编译方法的编译类型 | 方法名标识 |
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 |
---|
最近编译方法的数量 | 最近编译方法的字节码数量 | 最近编译方法的编译类型 | 方法名标识 |
以上是关于jvm的主要内容,如果未能解决你的问题,请参考以下文章
JVM类加载续
JVM调优参数整理
JVM参数说明
JVM 类的加载
JVM 类的加载
类的加载连接和初始化