判断对象是否存活算法
引用计数法(Reference Counting)
在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值+1,当引用失效的时候,引用计数器的值-1。
缺点:单纯的引用计数器很难解决对象之间相互循环引用的问题。
可达性分析法(Reachability Analysis)
GC Roots
1.虚拟机栈(栈帧中的本地变量表)中引用的对象(各个线程被调用的方法堆栈中使用到的参数,局部变量,临时变量等)。
2.方法区中类静态属性引用的对象(java类的引用类型静态变量)。
3.方法区中常量引用的对象(字符串常量池(String Table)里的应用)
4.本地方法栈(JNI)引用的对象。
5.Java虚拟机内部的引用(基本数据类型对象的Class对象,一些常驻的异常对象(NullPointException、OutOfMemoryError),类加载器)。
6.被同步锁(synchronized)持有的对象。
7.反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。
8.分代收集和局部回收(Partial GC)。
引用链(Reference Chain):GC Roots的跟对象作为起始节点集,根据引用关系向下搜索,搜索过程所走过的路径。
引用
强引用(Strongly Reference):
Object obj = new Object()。
主要强引用关系存在,垃圾收集器就不会回收掉被引用的对象。
软引用(Soft Reference):
还有用,但非必须的对象。
被软引用关联的对象,在系统将要发生内存溢出前,会将软应用的对象列进回收范围进行第二次回收。
弱引用(Weak Reference):
非必须对象,强度比软引用弱一些。
被弱引用关联的对象,只能生存到下一次垃圾收集为止。
虚引用(Phantom Reference):
“幽灵引用”或“幻影引用”,是最弱的一种引用关系
为对象设置虚引用关联唯一的目的是为了能在整个对象被收集器回收时收到一个系统通知。
方法区回收
回收内容:1、废弃的常量;2、不在使用的类型
判断一个常量是否废弃
1.该类所有实例都已经被回收(Java堆中不存在该类及其任何派生子类的实例)
2.加载该类的类加载器已经被回收(OSGi、JSP的重加载)
3.该类对应的java.lang.Class对象没有任在任何地方被引用,无法在任何地方通过反射访问该类的方法。
垃圾回收算法
分代收集理论
弱分代假说(Weak Generational Hypothesis):绝大多数对象都会被回收。
新生代(Young Generation):Minor GC / Major GC
强分代假说(Strong Generational Hypothesis):经过越多次垃圾收收集的对象越难以回收。
老年代(Old Generation):Full GC
Full GC:收集整个Java堆和方法区
跨代引用假说(Intergenerational Reference Hypothesis)
新生代上建立一个全局的数据结构(记忆集(Remembered Set))
划分老年代若干内存,标识出老年代哪块内存存在跨代引用。
当发生Minor GC时,将包含跨代引用内存中的对象加入到GC Roots进行扫描
标记-清除
缺点:
执行效率不稳定:执行效率会随着回收对象数量的增长而降低。
内存空间碎片化:产生大量不连续的内存碎片,当需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
通过分区空间分配链表解决内存分配问题
标记-复制
为了解决标记-清除算法面对大量可回收对象时执行效率低
划分为两块大小相同的区域,只使用其中的一块,当这一块内存使用完之后,就进行回收,把存活的对象放到另一块区域,当前的这块区域全部清除。
注意:
在分代收集中的from Survivor、to Survivor 区,to区一直是保留区域,from、to的名字是相互替换的
Eden、from Survivor、to Survivor默认比例:8:1:1
缺点:空间浪费,只使用了一半的内存空间
标记-整理
先标记-清除,在对存活的对象向空间一端移动,直接清理掉边界以外的内存。
对象移动必须全程暂停用户应用线程。
领取专属 10元无门槛券
私享最新 技术干货