JVM 常见参数:
新生代常用参数:
-Xms 20M starting 表示堆的起始大小
-Xmx max 表示堆的最大大小
-Xmn new 表示堆的新生代大小
-XX:SurvivorRatio = 8 新生带大小 8 : 1 :1
jmap -heap pid 查看当前jvm 进程占用大小
对象空间分配
多线程进行对象分配时,使用cas算法保证不同的线程可以将对象分到堆里。线程多了就会有指针碰撞的情况,消耗性能。所以竞争激烈的时候就会进行栈上分配。
补充:栈上分配(TLAB: Thread Local Allaction Buffer ) ,在eden 区每个线程都有自己的buffer,这个buffer 的大小是可以定的,在自己的空间去分配就不存在并发了。避免过多的锁消耗性能。栈上分配与ThreadLocal 的思想是一样的。
FreeList 带压缩的 收集器 (内存不规整)空闲列表
补充 新生代分配:分配的是对象 ,引用是栈中。eden区放不下了,就会minor GC。设计成8:1:1 而不是9:1 就可以是对象的年龄增加。Minor GC 只会清理Eden 区。其他的就都会被干掉。old 区去GC 交major GC 会比我们的minor GC 慢十倍 。若果设置成9:1 当一个对象在第二次GC 的时候他只能进入老年代。没地方可去了。分代的目标就是让对象不要进入老年代 在新生代就回收掉。最理想的的状态下是所有的对象都不要进入老年代。
对象进入老年代的方式:
对象很大
-XX:PretenureSizeThreshold = 31145728 即 3M 直接进入老年代
长期存活的对象:
-XX : MaxTenuringThreshold = 15 控制进入老年代的条件 默认是15。
动态对象年龄判定:
相同年龄所有对象的大小总和>Survivor空间的一半。
minorGC 的时候也不是只要有存活对象就往老年代丢,而是他有一个判断条件,在每次 minor GC 的时候都会有担保机制。
分配担保:
每次minor GC 之前 检查,老年代最大可用连续空间是否>新生代所有对象的总空间,如果满足就直接minor GC ,如果不满足就要去判断,是否大于历代晋升老年代的平均大小,判断之后进行确定是进行minorGC 还是full GC 。
Minor GC : 新生代的一个回收算法
Major GC: old 区的回收算法
Full GC: minor GC + Major GC
做垃圾回收器的目的就是减少full GC
什么样的对象需要回收?
引用:
强 :Object obj = new Object(); (判断算法 GC Root 判断可达)
软 :做大的缓存的时候使用软引用 ,会在做GC 时内存不足时被干掉
弱 只要GC 就会被回收,不管空间够不够都会回收,被弱引用关联的对象只能生存到下一次垃圾回收之前。
虚 虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
用虚引用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知
回收
方法论:
标记-清除算法(cms使用的垃圾收集算法)
效率低,造成空间碎片
复制回收算法(新生代使用的收集算法)
有点:高效,无碎片 缺点:空间利用率低
标记- 整理算法(老年代使用的算法)
标记--整理--清除
优势:没有碎片
垃圾回收器(实现)与垃圾回收算法(理论)有什么关系:
垃圾回收器就是算法的实现,
实现机制
垃圾回收器
六种垃圾回收器,是分代的,上面三个是yong区域,下面三个是old 区, G1 既有young区也有old区
Parallel Scavenge(全局)
吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)
-XX:MaxGCPauseMillis = n 控制GC 的停顿时间
-XX:GCTimeRatio = n
-XX:UseAdaptiveSizePolicy 使用适合的策略 ,
只有减少垃圾回收时间吞吐量才会大 GC Ergonomics
Serial Old 标记-整理 是 CMS 的备用方案 ,在current Model Failure 时 去执行
Parallel Old 标记-整理算法
CMS (current Mark Sweep) 标记-清除算法
减少回收停顿时间
1、初始标记(标记GC Root 的对象) stop the word
2、并发标记(标记能找到GC Root的对象,业务线程在跑)过程比较长
3、重新标记(标记处并发标记时变化的GC Root) stop the word 过程比较短
4、并发清楚(并发的清楚掉可以回收的对象),并发清楚的时候,GC Root 可能会变化,产生新的可回收对象,在本次收集过程中无法回收产生浮动垃圾,等到下次才可以回收。
缺点:current cpu 敏感,更多的线程去GC 会耗费CPU ,是吞吐量下降。
标记清楚一定 会产生碎片 :-XXCMSInitiationgOccupancyFraction
Concurrent Mode Failure 启用 Serial Old
G1(garbage First)收集器
G1最大可以有两千个块,每个块的大小都是1M----32M . 分块压缩基本上不会产生浮动垃圾。优先选择第一块,垃圾最大的一块进行回收。
回收的时间节点:
在GC 的时候线程是如何停下来的,安全点(运行线程可以停下来的节点,让GC 线程去执行)。安全点的选择就是相对来说执行比较久的过程之前,或者之后来做一个停顿。
安全点有:方法调用(之前之后)
循环跳转(之前之后)
异常跳转(之前之后)
每一条指令在cpu中运行都比较快的,把他们作为安全点是不合适的,要在流程切换的时候找到安全点。是一个相对来说时间周期比较长的点。
stop the word 时 应用线程与GC 线程的协调方式:
1、潜在式的,应用线程在执行的时候会检查一下他在不在安全点,如果在就停下来。stop the world,如果不在就继续跑,跑到安全点在进行Stop the word.
2、主动式中断,GC 线程 会有一个flag,运行线程走到安全点时回去检测flag标识,如果看到flag标识是GC 在跑,那么就会停下来。如果GC 线程不再跑,运行线程就不会停下来。
安全区域
如果线程挂起了,线程不在运行状态了,无法进入安全点(safe point )呢。安全区域是指一段代码片中,引用关系不会发生变化,在这个区域任何地方GC都是安全的,安全区域可以看做是安全点的一个扩展。线程执行到安全区域的代码时,首先标识自己进入了安全区域,在full GC 时运行时线程与GC 线程就不用再做交互了。可以直接进行GC.