可能大家都知道,JVM中有一个相当重要的环节,就是性能调优,那么你是否也清楚JVM是如何进行调优的呢?下面有兴趣的朋友可以跟小编一起来看看哦。
在JDK 1.7及以前呢,Java类的信息、常量池、静态变量都是存储在 Perm(永久代)里的。类的元数据,和静态变量都会在类加载的时候分配到Perm中,当类被卸载的时候垃圾收集器从Perm会处理掉。
那么JDK 1.8对JVM架构的改造是将类元数据放到本地内存中的,另外呢,将常量池和静态变量放到Java堆里。HotSopt VM就将会为类的元数据明确分配和释放本地内存。在这种架构下呢,类元信息就突破了原来 -XX:MaxPermSize的限制了,所以PermSize的配置也是无效的,现在可以使用更多的本地内存。这样就是从一定程度上解决了原来在运行时生成大量类的造成经常Full GC问题,如运行时使用反射、代理等等。
jvm内存
可以发现比较明显的一个变化就是元空间从虚拟机转移到本地内存;在默认情况下,元空间的大小仅仅受本地内存的限制。这就意味着以后也不会因为永久代空间不够而抛出OOM异常了。
在jdk1.8以前版本的class和jar包数据都存储在permGen下面,permGen大小是固定的,而且项目之间无法共用公有的class,所以就很容易碰到OOM异常。
改成metaSpaces后,各个项目会共享同样的class内存空间,例如多个项目都引用了apache-common包,在metaSpaces中只会存储一份apache-common的class,提高了内存的利用率,使得垃圾回收更有效率。
JVM参数配置
在jdk1.8以前,生产环境一般会有如下的配置:
-XX:PermSize=512M
-XX:MaxPermSize=1024M
是表示在JVM里存储Java类信息,常量池和静态变量的永久代区域初始大小为512M,最大为1024M。而在项目启动后,这个值是固定的,如果项目class过多,很可能遇到OutOfMemoryError: PermGen的异常了。
在升级JDK1.8之后,上面的perm配置已经变成了:
-XX:MetaspaceSize=512M
XX:MaxMetaspaceSize=1024M
如果MetaspaceSize不做配置,那么通过jinfo查看默认MetaspaceSize大小(约21M),MaxMetaspaceSize很大很大,前面说过MetaSpace只受本地内存大小限制。
jinfo -flag MetaspaceSize 1234 #结果为:-XX:MetaspaceSize=21807104
jinfo -flag MaxMetaspaceSize 1234 #结果为:-XX:MaxMetaspaceSize=18446744073709547520
MetaspaceSize为出发FullGC的阈值,默认约为21M,如果做了配置,最小阈值为自定义配置大小。空间使用达到阈值,触发FullGC,同时对该值扩大。当然如果元空间实际使用小于阈值,在GC的时候也会对该值缩小。
MaxMetaspaceSize为元空间的最大值,如果设置太小,可能会导致频繁FullGC,甚至OOM。
GC(GarbageCollection)过程
新new的对象都放在Eden区(伊甸园嘛,创造的地方)
Eden区满或者快满的时候进行一次清理(Minor Gc),不被引用的对象直接被干掉;还有引用的对象,但是年龄比较大的,挪到S0区
下次Eden区快满的时候,会进行上一步的操作,并且将Eden和S0区的年纪大的对象放到S1区【原理上随时保持S0和S1有一个是空的,用来存下一次的对象。
下下次,Eden区快满的时候,会进行上一步操作,并且将Eden和S1区的年纪大的对象放到S0区【此时S1区就是空的】
直到Eden区快满,S0或者S1也快满的时候,这时候就把这两个区的年纪大的对象放到Old区
依次循环,直到Old区也快满的时候,Eden区也快满的时候,会对整个这一块内存区域进行一次大清洗(FullGC),腾出内存,为之后的对象创建,程序运行腾地方。
清理Eden区和Survivor区叫Minor GC;清理Old区叫Major GC;清理整个堆空间—包括年轻代和老年代叫Full GC。
JVM参数配置指南
前面三个部分对JVM进行了整体的了解,接下来是本文的重点。
-XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -Xms256m -Xmx256m
Java堆大小设置,Xms 和 Xmx设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍
永久代 PermSize和MaxPermSize(元空间)设置为老年代存活对象的1.2-1.5倍。
年轻代Xmn的设置为老年代存活对象的1-1.5倍。
老年代的内存大小设置为老年代存活对象的2-3倍。
可以让系统运行一段时间后查看系统的各个指标,然后在进行配置。
好了,以上就是本篇文章的所有内容了,还想了解更多java常见问答知识,欢迎来关注本站最新消息,更多精彩内容等你来解锁。
推荐阅读: