java内存回收

    xiaoxiao2021-03-25  164

    1 垃圾对象的判定

    1.1 引用计数法

    引用计数法判定一个对象是否为垃圾对象的方式是为每一个对象设置一个引用计数器,每当一个对象引用它时,这个引用计数器就加1,引用失效时,则其减1,当引用计数器为0时则为垃圾对象.这种方式不能处理循环引用

    1.2 可达性分析算法

    通过一系列的GCRoots开始向下搜索,对于没有GCRoots能够达到的对象则判定为垃圾对象。java语言中GCRoots包括有以下几种:

    虚拟机栈,本地方法栈中引用的对象(正在用的对象)方法区中静态属性引用的对象。常量区中引用的对象

    1.3 引用类型

    强引用:诸如Object obj = new Object()这种引用软引用:在系统将要发生内存溢出异常之前,会把这些对象列进回收范围进行二次回收。软引用可以用来做高速缓存,其可以用SoftReference来实现软引用。弱引用:弱引用在下一次垃圾回收时一定会被回收。当想引用一个已有自己生命周期对象,并且不想介入这个对象的生命周期时,这时可以使用弱引用。可以用WeakReference来实现虚引用:为对象设置虚拟引用关联的唯一目的就是在这个对象被收集器回收时收到一个 系统通知.可以用PhantomReference来实现

    方法区的垃圾对象判断

    方法区中的垃圾对象主要为"废弃常量""无用的类"。 "废弃常量"的判定是当前系统中没有任何对象引用了这个常量 "无用的类"的判断标准为:

    该类的所有实例都已经被回收加载该类的classloder已经被回收改类对应的Class对象没有在任何地方被引用

    2 垃圾收集算法

    2.1 标记-清除算法

    首先标记出所有需要回收的对象,在标记后统一回收所有的被标记的对象

    2.2 复制算法

    复制算法是指将内存化分为相等的两块,每一次只使用其中一块,每次垃圾回收时将还存活的对象移到另一块中。实际上虚拟机上的实现是将内存分为新生代和老年代,新生代中又分为Eden区和两个survivor区,每次使用的是Eden区和其中一个survivor区,hotspot默认的eden和survivor区的比值为8:1,因此每次只浪费10% 。

    2.3 标记-整理算法

    标记整理算法先标记出所有需要回收的对象,然后将所有存活的对象向一端移动,然后直接清理掉边界以外的内存。

    3 hotspot算法实现

    hotspot通过OopMap来直接得知那些地方存放着对象引用。 在进行GCRoots时可能会由于程序在运行而导致引用关系的变化,并且hotspot不能为每条指令生成对象的OopMap。而在HotSpot实现时采用的是"安全点",只需要将正在执行的线程"跑到"安全点,就可以执行gc对应的操作,安全区域,当线程执行到安全区域时,首先标定自己为Safe Region状态的线程,在这段时间JVM执行gc操作时,就不需要将已经在安全区域的线程运行到对应的安全点去。

    4 垃圾回收器

    4.1 Serial收集器

    Serial收集器是一个单线程的收集器,在它进行垃圾回收时,需要停止所有工作线程,直至其收集结束

    4.2 ParNew收集器

    ParNew收集器是Serial收集器的多线程版本.

    4.3 Parallel Scavenge收集器

    Parallel Scavenge收集器主要目标是达到一个可控制的吞吐量。可以用-XX:SurvivorRatio设置吞吐量,-XX:PretenureSizeThreshold设置晋升老年代的年龄,-XX:MAXGCPauseMillis设置最大垃圾回收停顿时间。主要适合在后台运算而不需要太多交互的任务。

    4.4 Serial Old收集器

    Serial Old收集器是Serial收集器的老年代版本,这个收集器的主要意义是在于给Client模式下的虚拟机使用,在server模式下作为CMS的后备方案,如果CMS出错则采用Serial Old收集器。

    4.5 Parallel Old收集器是

    Parallel Old收集器是Parallel Scavenge收集器的老年代版本。

    4.6 CMS收集器

    算法实现主要是有4个步骤:

    初始标记并发标记重新标记并发清除

    初始标记标记的是GC Roots能直接关联到的对象。并发标记则是进行 GC Roots tracing的过程.重新标记是修正并发标记期间标记产生变动的那一部分对象的标记记录。并发清除则采用标记-清除算法对标记好的对象清除。

    内存分配策略

    对象优先在Eden分配大对象直接进入老年代长期存活的对象进行老年代(-XX:MaxTenuringThreshold=1)Surivor区同年的对象大于Survivor区的一半,这些对象直接进入老年代对于发生Minor GC之前,虚拟机会检查老年代的最大可用连续空间是否大于新生代所有对象总空间,如果不大,则通过HandlePromotionFailure看是否允许空间分配担保,如果允许,则判断老年代最大连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,则进行Minor GC。
    转载请注明原文地址: https://ju.6miu.com/read-935.html

    最新回复(0)