文章目录
垃圾回收机制
自动垃圾收集
自动垃圾收集是查看堆内存,识别正在使用哪些对象以及哪些对象未被删除以及未使用对象的过程。
使用中的对象或引用的对象意味着程序的某些部分仍然维护指向该对象的指针。
程序的任何部分都不再引用未使用的对象或未引用的对象,因此可以回收未引用对象使用的内存。
像C这样的编程语言中,分配和释放内存是一个手动过程。
在java中,解除分配内存的过程由垃圾收集器自动处理。
如何确定内存需要被回收
该过程的第一步称为标记。这是垃圾收集器识别哪些内存正在使用而哪些不在使用的地方。
不同类型内存的判断方式:
- 对象回收 - 引用计数(解决不了循环引用的问题)
- 对象回收 - 可达性分析(重点研究)
- 方法区回收(类的卸载)
可达性分析算法
顺藤摸瓜…找到一个入口…
引用类型和可达性级别
引用类型:
- 强引用(StrongReference):最常见的普通对象引用,只要还有强引用指向一个对象,就不会回收。obj = new 。。。
- 软引用(SoftReference):JVM认为内存不足时,才会去试图回收软引用指向的对象。(缓存场景)
- 弱引用(WeakReference):虽然是引用,但随时可能被回收掉。
- 虚引用(PhantomReference):不能通过他访问对象。提供了对象被finalize以后,指向指定逻辑的机制(Cleaner堆外内存)
可达性级别:
- 强可达(Strongly Reachable):一个对象可以有一个或多个线程可以不通过各种引用访问到的情况。- 强引用
- 软可达(Softly Reachable):就是当我们只能通过软引用才能访问到对象的状态。- 软引用
- 弱可达(Weakly Reachable):只能通过弱引用被清除的时候,就符合销毁条件。- 弱引用
- 幻象可达(Phantom Reachable):不存在其他引用,并且finalize过了,只有幻象引用指向这个对象。- 虚引用
- 不可达(unreachable):意味着对象可以被清除了。
垃圾收集算法
标记-清除(Mark-Sweep)算法:首先标识出所有要回收的对象,然后进行清除。
标记、清除过程效率有限,有内存碎片化问题,不适合特别大的堆;收集算法基本基于标记-清除的思路进行改进。
复制(Copying)算法:划分两块同等大小的区域,收集时将活着的对象复制到另一块区域。
拷贝过程中将对象顺序放置,就可以避免内存碎片化。复制+预留内存,有一定的浪费。
标记-整理:类似于标记-清除,但为避免内存碎片化,它会在清理过程中将对象移动,以确保移动后的对象占用连续的内存空间。
分带收集
根据对象的存活周期,将内存划分为几个区域,不同区域采用合适的垃圾收集法。
新对象会分配到Eden,如果超过-XX:+PretenureSizeThreshold:设置大对象直接进入老年代的阈值。
新生代回收算法:复制算法
老年代标记整理算法:
minorGC:指新生代的GC
majorGC:指老年代的GC
fullGC:整个堆的GC
垃圾收集器
串行收集器-Serial GC -XX:UseSerialGC
新生代和老年代采用不同的参数进行配置
不适合多核处理器…
并行收集器-Parallel GC --XX:+UseParallelGC
新生代和老年代采用不同的参数进行配置
特点:将单线程变成了多线程
问题:串行收集器和并行收集器都会有一个stop-the-world,停止所有动作进行垃圾收集,有停顿时间。
并发收集器-CMS(Concurrent Mark Sweep) GC -XX:+UseConcMarkSweepGC
专用老年代,基于标记-清除(Mark-Sweep)算法,设计目标是尽量减少停顿时间。
采用的标记-清除算法,存在着内存碎片化问题,长时间运行等情况下发生full GC,导致恶劣的停顿。
CMS会占用更多的CPU资源,并和用户线程争抢。
减少了停顿时间,这一点对于互联网web等对时间敏感的系统非常重要,一直到今天,任然有很多系统使用CMSGC。
初始标记目的:找到GCroot
并行收集器-PraNew GC -XX:+UseParNewGC
新生代GC实现,它实际是Serial GC的多线程版本。
可以控制线程数量,参数: -XX:ParallelGCThreads
最常见的应用场景是配合老年代的CMS GC工作。参数: -XX:UseConcMarkSweepGC
在jdk中1.8中放弃维护了CMS GC