jvm简介什么的不详细介绍了,只介绍有重点性,需要理解和记忆以及常用的核心参数的介绍。
对象的年龄:每垃圾回收一次,如果一个对象没被回收掉,他的年龄就会增加1
对象的分配:
- 对象优先分配在新生代
- 新生代如果对象满了,会触发Minor GC回收掉没有引用的垃圾对象
- 如果有对象躲过了十多次垃圾回收,就会放入老年代里
- 如果老年代也满了,那么也会触发垃圾回收,把老年代里没人引用的垃圾对象清理掉
对象进入老年代的方法:
1、新生代垃圾回收之后,因为存活对象太多,会导致大量对象直接进入老年代
2、特别大的超大对象直接不经过新生代就进入老年代
3、动态对象年龄判断机制:假如说当前放对象的Survivor区域里,一批对象的总大小大于了这块Survivor区域的内存大小的50%,那么此时大于等于这批对象年龄的对象,就可以直接进入老年代了。
4、空间担保机制:执行任何一次Minor GC之前,JVM会先检查一下老年代最大的可用连续空间,是否大于新生代所有对象的总大小
jvm内存分配的核心参数:
-Xms:Java堆内存的大小
-Xmx:Java堆内存的最大大小
-Xmn:Java堆内存中的新生代大小,扣除新生代剩下的就是老年代的内存大小了
-XX:PermSize:永久代大小
-XX:MaxPermSize:永久代最大大小
-Xss:每个线程的栈内存大小
如:
java -Xms512M -Xmx512M -Xmn256M -Xss1M -XX:PermSize=128M -XX:MaxPermSize=128M -jar App.jar
-Xms3072M -Xmx3072M -Xmn1536M -Xss1M -XX:PermSize=256M -XX:MaxPermSize=256M -XX:HandlePromotionFailure
其他参数:
-XX:MaxTenuringThreshold 多少岁进入老年代 默认15岁 。在JVM中用4个bit存储(放在对象头中),所以其最大值是15
其他进入老年代的方法:
如果gc之后eden区剩余的对象内存大于Survivor区,则将对象直接转移到老年代中
-XX:PretenureSizeThreshold 默认值是0,超过多大的对象直接进入分配在老年代。设置为字节数,比如“1048576”字节,就是1MB,如:-XX:PretenureSizeThreshold=1M
-XX:-HandlePromotionFailure 老年代最大可用连续空间是否大于之前到晋级老年代对象的平均大小。参数在JDK 1.6以后就被废弃
-XX:+UseParNewGC 使用ParNew垃圾回收器(多线程来进行垃圾回收),运行在Windows上的客户端程序,建议采用Serial垃圾回收器
-XX:+UseG1GC 使用G1垃圾回收器
-XX:+UseParallelGC: 新生代使用ParllelGC回收器
-XX:ParallelGCThreads 控制ParNew的垃圾回收线程数量
-XX:CMSInitiatingOccupancyFaction 参数可以设置老年代中对象占多少比例的时候,触发 CMS 垃圾回收器的回收机制,默认92%如:-XX:CMSInitiatingOccupancyFaction=92
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
G1中,大对象的判定规则就是一个大对象超过了一个Region大小的50%,大对象可以横跨多个region进行存放
-XX:MaxGCPauseMills G1执行GC的时候最多可以让系统停顿多长时间。默认值是200ms
-XX:InitiatingHeapOccupancyPercent 默认值是45% 如果老年代占据了堆内存的45%的Region的时候,此时就会尝试触发一个新生代+老年代一起回收的混合回收阶段
-XX:G1MixedGCCountTarget 在一次混合回收的过程中,最后一个阶段执行几次混合回收,默认值是8次
-XX:G1MixedGCLiveThresholdPercent,他的默认值是85%,意思就是确定要回收的Region的时候,必须是存活对象低于85%的Region才可以进行回收
-XX:+HeapDumpOnOutOfMemoryError OOM的时候自动dump内存快照
-XX:HeapDumpPath=/usr/local/app/oom 内存快照放到哪儿去
MinorGC触发条件图:
调优步骤:
1、估计系统每秒会产生多少新的对象,占用多少内存 访问压力以及核心对象的内存占据,需要多少时间才会让新生代触发Minor GC以及多久之后触发FullGC。
2、突发巨大的流量压力,突发的性能抖动,最后导致很多对象长期在新生代被人引用,无法被回收,最后持续进入老年代,最后触发老年代内存都频繁占满,然后老年代都频繁被垃圾回收。
Tomcat jvm调优在bin目录下的catalina.sh中可以加入JVM参数
CMS垃圾收集算法:
初始标记(CMS-initial-mark) -> 并发标记(CMS-concurrent-mark) -> 重新标记(CMS-remark) -> 并发清除(CMS-concurrent-sweep) ->并发重设状态等待下次CMS的触发(CMS-concurrent-reset)
可能会出现的异常:Concurrent mode failed的产生是由于CMS回收老年代的速度太慢,导致年老代在CMS完成前就被占满,引起full gc(需要时间较长),发现此异常后会使用Serial Old来进行垃圾回收,如果Serial Old也顶不住,会发生OOM。
有GC Roots引用的对象不能回收,没有GC Roots引用的对象可以回收,如果有GC Roots引用,但是如果是软引用或者弱引用的,也有可能被回收掉。静态变量也可以看做是一种GC Roots。
Object中的finalize()方法,垃圾回收时会调用的方法,如果不想被回收,可以重写这个方法。
对于 XX:SurvivorRatio 网上很多人说是占百分比:
官网原话:
The SurvivorRatio parameter controls the size of the two survivor spaces. For example, -XX:SurvivorRatio=6 sets the ratio between each survivor space and eden to be 1:6, each survivor space will be one eighth of the young generation. The default for Solaris is 32. If survivor spaces are too small, copying collection overflows directly into the old generation. If survivor spaces are too large, they will be empty. At each GC, the JVM determines the number of times an object can be copied before it is tenured, called the tenure threshold. This threshold is chosen to keep the survivor space half full.
链接:https://docs.oracle.com/cd/E19159-01/819-3681/abeil/index.html
G1 内存模型:
G1(Garbage First):将Java堆内存拆分为多个大小相等的Region,每个分区内部又被分成了若干个大小为512 Byte卡片(Card)。每个Region可能是老年代,也可以新生代。G1仍然存在有Eden和Survivor(逻辑概念),各自占据不同的Region。这样就和之前的调优步骤一致。
G1可以设置一个垃圾回收的预期停顿时间,如果设置0.5s,G1会计算这个时间可以回收多少个Region,从来只回收部分region已达到控制时间的作用。
G1适用于堆内存比较大(一般4G以上)
题目:
-Xms:1G , 就是说初始堆大小为1G
-Xmx:2G , 就是说最大堆大小为2G
-Xmn:500M ,就是说新生代大小是500M(包括一个Eden和两个Survivor)
-XX:MaxPermSize:64M , 就是说设置持久代最大值为64M
-XX:+UseConcMarkSweepGC , 就是说使用使用CMS内存收集算法
-XX:SurvivorRatio=3 , Eden区比例30% 就是说Eden区与Survivor区的大小比值为3:1:1
题目中所问的Eden区的大小是指年轻代的大小,直接根据-Xmn:500M和-XX:SurvivorRatio=3可以直接计算得出
500M*(3/(3+1+1)) =500M*(3/5) =300M
因此Eden区域的大小为300M
总结:
分析系统的压力点在哪里,如果在现有内存资源的情况下,尽量减少GC回收的次数。根据每秒的产生在新生代的内存,根据jvm运行原理分析出,什么时候对象将在老年代中,什么时候进行minor GC会通过担保机制直接进入老年代等。
附:
比较齐全的一份jvm参数设置:
-Xms4096M -Xmx4096M -Xmn3072M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFaction=92 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSParallelInitialMarkEnabled -XX:+CMSScavengeBeforeRemark -XX:+DisableExplicitGC -XX:+PrintGCDetails -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/app/oom