java-gc

GC: Garbage Collection, 垃圾收集

java堆内存分: 新生代(1个Eden区, 2个Survivor区,比例:8:1:1)、老年代

GC要做的事情: 针对有限内存,将不用的对象清除,达到内存释放目的

GC机制递进理解: GC的区域在哪里, GC的对象是什么,GC的时机是什么? GC做哪些事情

 

 

 

GC的区域
jvm中 程序计数器、虚拟机栈、本地方法栈随线程而生随线程而灭,实现自动的内存清理; gc 主要针对java堆和方法区,这部分内存的分配和使用都是动态的
运行时数据区域:(程序计数器、本地方法栈、虚拟机栈;方法区、堆),主要回收区域(方法区、堆):无用堆对象实例回收、常量池回收、类型的卸载

GC对象
已经没有存活的对象,判定方法:
引用计数(新增引用计数加1,引用释放计数减1,计数为0即可回收,无法解决对象相互引用问题);
可达分析(Roots向下搜索,搜索走过的路径成为引用链,若Roots没有任何引用链相连,则该对象为不可用、不可达对象)
(GC Roots: 虚拟机引用的对象;本地方法JNI引用的对象;方法区类静态属性引用的对象;方法区中常量应用的对象)

GC时机
程序调用System.gc时触发;系统自身决定GC触发的时机(根据Eden区和Survivor的From space 区内存大小来决定,当内存大小不足时,启动GC线程并停止应用线程)
GC共分两种:
minorGC: Eden区满时,触发minorGC;
fullGC(Major GC): 调用System.gc时,系统建议执行full GC;老年代空间不足;方法区空间不足;通过Minor GC进入老年代的大小大于老年代的可用内存;由Eden区、From Space区向To Space区复制时,对象大小大于To Space的大小;

GC做哪些事情
清理对象,整理内存

 

 

GC常用算法

标记清除算法
每个对象一个存储位,记录对象状态;分两个阶段,标记阶段:检查是否死亡;清除阶段:对死亡对象进行清除优点:活着对象只需要找到一个即可,并且不需要移动对象;缺点:效率较低(递归、遍历),所有活着对象都要在标记阶段遍历一遍;所有对象都需要在清除阶段扫描一遍;没有移动对象,产生较多碎片;

标记压缩算法
标记清除改进版,标记阶段将所有对象标记为存活、死亡两种状态;第二阶段将所有活着的对象放到另外一处空间,然后把剩余的所有对象全部清除
优点:不会产生大量碎片;缺点;如果存活的对象过多,整理阶段会执行较多复制操作;

复制算法
将内存分为两部分,只使用其中一部分,该部分内存满后,将所有存活对象复制到另一个内存中,将之前内存清空,只使用这部分内存,循环下去
(与标记整理区别为不是再同一区域复制,而是复制到另一个区域)

优点:不产生内存碎片;缺点:每次运行,总有一半内存是空的

分代收集算法(主流)
根据对象生成周期分为新生代、老年代:
新生代:对象生成期短,每次回收都有大量的对象死去,采用复制算法;

老年代:对象存活率较高,没有额外的空间进行分配担保,可使用标记整理、标记清除;
新生代分Eden区,From区、To区 -> Eden区满,触发YoungGC,也是年轻代的垃圾回收,将能用的对象复制到From区;Eden区被清理干净后,继续创建新对象,再次用完后,再触发YoungGC,这次触发YoungGC后,会将Eden区和From区还被使用的对象复制到To区;再下一次YoungGC,将Eden区和To区复制到From区;经过多次游荡,From区或To区满后,一起复制到老年代; 老年代满了后,进行FullGC,即全量回收。

 

 

垃圾收集器(可设置收集器)


1. Serial 收集器
串行收集器是最古老,最稳定以及效率高的收集器,可能会产生较长的停顿,只使用一个线程去回收
新生代串行-复制算法和老年代串行-标记压缩算法


2. 并行收集器

2.1 ParNew
新生代并行-复制算法,老年代串行

2.2 Parallel收集器
新生代-复制算法, 老年代-标记压缩(可设置串行或并行)

3. CMS收集器
应用程序线程和GC线程交替执行
标记清除算法(不能改变对象的内存位置,所有不是标记整理):a)初始标记(全局卡顿),根直接关联的对象;b)并发标记,和用户线程一起,标记全部对象; c)重新标记(全局卡顿),为刚才并发标记做修正;d)并发清除;

影响系统整体吞吐量和性能;清理不彻底;由于并行操作,需要提前清理,否则易导致内存不足;清理失败,使用串行收集器为后备; 并行减少GC时间,但是没有处理碎片,还需要花时间清理碎片,本质上没有改善时间

4. G1收集器
G1使用标记整理算法,不会产生内存碎片(分配大对象不会因为无法找到连续空间而提前触发下一次GC);可预测停顿时间,即指定垃圾回收时间
将java堆划分为多个独立区域(region),仅保留新生代和老年代的概念,不在物理隔离,都是Region的集合

初始标记阶段, 触发 youngGC; 并发标记;再标记;并发整理、清除;

 

finalize

Object 的projected方法, 子类可覆盖该方法实现资源清理,GC在回收对象前调用该方法
调用具有不确定性,不建议用该方法完成非内存资源的清理,但建议:清理本地对象,某些非内存资源释放的一个补充(Socket,文件)

java不会保证finalize会被执行

finalize流程:对象roots不可达,判断有无finalize方法,若无直接回收;若有并且未执行,防止低优先级队列执行该方法;执行完后再判断该对象是否可达,仍不可达回收,否则复活

 


GC总结
1. 尽早释放无用对象的引用,尤其比较复杂的对象图
2. 尽量少用finalize,提供一个释放对象和资源的机会, 但会加大GC的工作量

 

参考: https://blog.csdn.net/laomo_bible/article/details/83112622

posted on 2021-03-16 20:49  wangsong412  阅读(58)  评论(0编辑  收藏  举报