1 了解 引用计数算法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值加1,当引用失效时,计数器的值就减1,任何时刻计数器为0的对象就是不可能再被使用的。
微软的COM Component Object Model技术就是用这个技术
但是至少现在主流的java虚拟机里面没有使用这个
因为它很难解决对象之间相互循环引用的问题
2 了解可达性分析算法
java C# Lisp都是用这个
通过一系列称为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连的时候,则证明此对象不可用。
在java语言中,可以作为GC Roots的对象包括
①java虚拟机栈中引用的对象
②方法中静态属性引用的对象
③常量引用的对象
④本地方法栈中JNI(即一般说的Native方法)引用的对象
3 再谈引用
判断对象是否存活都与引用有关,引用分为四种
① 强引用 Obejct obj = new Object()这类的引用,只要强引用还存在,永远不会被回收
② 软引用描述一些有用但并非必须的对象,对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。SoftReference
③弱引用 也是用来描述非必需对象的,被若引用关联的对象只能生存到下一次垃圾收集器之前,当垃圾收集器工作时,无论当前内存是否足够,都会回收掉被弱引用关联的对象。WeakReference
④虚引用,也称为幻影引用,幽灵引用,一个对象是否有虚引用完全对其生存时间构成影响,也无法通过虚引用来去的一个对象实例,为一个对象设置虚引用关联的唯一目的是能在这个对象被垃圾收集器手机时受到一个系统通知。
4 关于对象的生存问题
如果对象在进行可达性分析后没有与GC Roots相连接的引用连链,那么它将会被第一次标记并且进行一次筛选,这个筛选的条件就是是否有必要进行finalize方法,当对象没有覆盖finalize方法,或者finalize方法已经被虚拟机调用过,虚拟机将这两种情况视为没有必要执行。
如果被判定为有必要执行finalize方法,这个对象会被放入一个F-Queue的队列之中,并在稍后由一个虚拟机自动建立的,低优先级的finalizer线程去执行它。这里所谓的执行是虚拟机会触发这个方法,但并不承若会等待它运行结束,否则会被它耽误,整个内存回收系统奔溃,finalize逃脱对象死亡的最后一次机会。
任何一个对象的finalize方法只会被执行一次
5 判断一个类是否是无用的类
①该类所有的实例已经被回收
②加载该类的ClassLoader已经被回收
③该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
垃圾收集算法
一个效率,标记清除效率都不高,另一个空间问题,有大量不连续的内存碎片
② 复制算法
将内存按容量划分为大小相等的两块,每次只能使用其中的一块,当这一块的内存用完了,就将还存活着的对象复制到另一块上,然后把易经使用过的内存空间一次清理掉。
将内存缩小了原来的一般,代价太大。
现在的商业机器都用这种算法来回收新生代。
③ 标记--整理算法 Mark-Compact
标记过程一样,但是后续步骤不是对可回收对象进行清理,而是让存活的对象都向一端移动,然后直接清理到边界以外的内存。
分代收集算法
java分为新生代和老年代,一般把java分为新生代和老年代,这样可以根据各个年代的特点采用最适当的收集算法,
在新生代中,每次垃圾收集时都发现有大批对象死去,就用复制算法,只需要复制出少量的复制成本就可以收集,
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值加1,当引用失效时,计数器的值就减1,任何时刻计数器为0的对象就是不可能再被使用的。
微软的COM Component Object Model技术就是用这个技术
但是至少现在主流的java虚拟机里面没有使用这个
因为它很难解决对象之间相互循环引用的问题
2 了解可达性分析算法
java C# Lisp都是用这个
通过一系列称为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连的时候,则证明此对象不可用。
在java语言中,可以作为GC Roots的对象包括
①java虚拟机栈中引用的对象
②方法中静态属性引用的对象
③常量引用的对象
④本地方法栈中JNI(即一般说的Native方法)引用的对象
3 再谈引用
判断对象是否存活都与引用有关,引用分为四种
① 强引用 Obejct obj = new Object()这类的引用,只要强引用还存在,永远不会被回收
② 软引用描述一些有用但并非必须的对象,对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。SoftReference
③弱引用 也是用来描述非必需对象的,被若引用关联的对象只能生存到下一次垃圾收集器之前,当垃圾收集器工作时,无论当前内存是否足够,都会回收掉被弱引用关联的对象。WeakReference
④虚引用,也称为幻影引用,幽灵引用,一个对象是否有虚引用完全对其生存时间构成影响,也无法通过虚引用来去的一个对象实例,为一个对象设置虚引用关联的唯一目的是能在这个对象被垃圾收集器手机时受到一个系统通知。
4 关于对象的生存问题
如果对象在进行可达性分析后没有与GC Roots相连接的引用连链,那么它将会被第一次标记并且进行一次筛选,这个筛选的条件就是是否有必要进行finalize方法,当对象没有覆盖finalize方法,或者finalize方法已经被虚拟机调用过,虚拟机将这两种情况视为没有必要执行。
如果被判定为有必要执行finalize方法,这个对象会被放入一个F-Queue的队列之中,并在稍后由一个虚拟机自动建立的,低优先级的finalizer线程去执行它。这里所谓的执行是虚拟机会触发这个方法,但并不承若会等待它运行结束,否则会被它耽误,整个内存回收系统奔溃,finalize逃脱对象死亡的最后一次机会。
任何一个对象的finalize方法只会被执行一次
5 判断一个类是否是无用的类
①该类所有的实例已经被回收
②加载该类的ClassLoader已经被回收
③该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
垃圾收集算法
①标记—清除算法 Mark-Sweep
首先标记出需要回收的对象,在标记完成后统一回收所有被标记的对象
一个效率,标记清除效率都不高,另一个空间问题,有大量不连续的内存碎片
② 复制算法
将内存按容量划分为大小相等的两块,每次只能使用其中的一块,当这一块的内存用完了,就将还存活着的对象复制到另一块上,然后把易经使用过的内存空间一次清理掉。
将内存缩小了原来的一般,代价太大。
现在的商业机器都用这种算法来回收新生代。
③ 标记--整理算法 Mark-Compact
标记过程一样,但是后续步骤不是对可回收对象进行清理,而是让存活的对象都向一端移动,然后直接清理到边界以外的内存。
分代收集算法
java分为新生代和老年代,一般把java分为新生代和老年代,这样可以根据各个年代的特点采用最适当的收集算法,
在新生代中,每次垃圾收集时都发现有大批对象死去,就用复制算法,只需要复制出少量的复制成本就可以收集,
而老年代中对象存活率高,就用标记清除或者标记清理
参考文献:
《深入理解java虚拟机----JVM高级特性与最佳实践》