什么是JVM垃圾回收?
在jvm运行过程中,由于对象的引入,不断开辟新的内存;在使用之后所占内存没有被释放掉,造成内存资源紧张。jvm提供了垃圾回收器,能够及时释放这些内存。jvm在识别定位垃圾、垃圾回收时机、垃圾回收方式等许多环节给出了一些可调节项,供用户自定义调整优化。
如何判断垃圾?
jvm采用可达性分析算法,接下来介绍与之相关的概念
根对象
System Class:由启动类加载器加载,运行期间一定会用到,不会被垃圾回收
Native Stack:os在执行时引用的java对象,本地方法栈
Thread:活动线程
Busy Monitor:正在加锁的对象
引用类型
强引用:被gc root对象强引用的对象不会被垃圾回收,所有强引用断开,下一次gc会被回收
软引用:在没有被强引用直接引用时,当发生垃圾回收时,内存仍不足时再次垃圾回收,回收软引用对象
配合引用队列来释放软引用自身
弱引用:在没有被强引用直接引用时,当发生垃圾回收时,不管内存是否充足都回收弱引用
配合引用队列来释放弱引用自身
虚引用:必须配合引用队列,配合ByteBuffer,被引用对象回收时,虚引用入队,由Reference Handler 线程调用Cleaner的clean方法,将直接内存地址Unsafe.freeMemory()
终结器引用:所有对象继承自Object,终结方法finalize()
垃圾回收时,终结器引用进入引用队列,被引用对象暂未回收,由Finalizer线程通过终结器引用找到被引用对象,调用finalize()方法,第二次gc时才被回收
总结:可以根据对象是否为根对象以及对象的引用类型来确定这个对象是否是垃圾
垃圾回收算法
确定了要清除的对象之后,接下来要学习jvm对垃圾回收的手段,接下来是三种基本的垃圾回收算法,jvm根据这些算法的组合,寻找最适合的垃圾处理方式。
标记清除 Mark Sweep
标记——>清除对象,释放内存
速度快、但有内存碎片
标记整理 Mark Compact
标记——>移动整理对象
无内存碎片,但速度较慢
复制 Copy
标记——>复制到新的内存分区
无内存碎片,速度较快,但占用双倍内存空间
分代垃圾回收
新生代
Eden
幸存区 From/To
老年代
1、对象首先分配在Eden区
2、新生代空间不足时触发minor gc
3、minor gc会引发stop the world(STW),即暂停用户线程直到垃圾回收线程结束
4、对象寿命超过阈值时,晋升至老年代,最大15次(4bit 二进制四位最大值 1111B);超过新生代的大对象不触发minor gc直接晋升老年代
5、当老年代空间不足,先触发minor gc,若空间仍不足,则触发full gc,也会触发STW,相较于minor gc的时间更长(标记整理)
6、空间仍不足,触发OOM(OutOfMemoryError)
7、一个线程内OOM不会导致其他线程结束
垃圾回收器
串行 Serial GC
单线程回收,其他线程阻塞;堆内存较小,适合个人电脑。
吞吐量优先 Parallel GC
多线程回收,与CPU核数相关,堆内存较大,垃圾回收时间越短,吞吐量越高。
响应时间优先 CMS Concurrent Mark Sweep
多线程回收,与CPU核数相关,堆内存较大,尽可能让stw时间缩短,回收时间响应迅速。老年代回收器。
G1 Garbage First
简介:
同时注重吞吐量Throughput和低延迟Low latency,默认暂停目标200ms;超大堆内存,会将堆内存划分为多个大小相等的region;整体时使用标记整理算法,两个区域间时使用复制算法。
回收阶段:
新生代 Young Collection:有STW
新生代+CM Concurrent Mark:Young GC时会进行GC Root初始标记,老年代占用堆空间比例达阈值时,进行并发标记(不会STW)
-XX:InitiatingHeapOccupancyFraction=percent 阈值默认45%
混合回收 Mixed Collection:对Eden、Survivor、Old全面回收,最终标记 Remark 会STW,拷贝存活 Evacuation 会STW
-XX:MaxGCPauseMillis=ms
垃圾回收调优
调优领域
内存、锁竞争、cpu占用、io
调优目标
运算:追求高吞吐量
互联网项目:追求快速响应时间、低延迟