《深入理解java虚拟机》学习笔记03

来源:互联网 发布:数据库工程师做什么 编辑:程序博客网 时间:2024/06/07 04:20
第三章 垃圾收集器与内存分配策略

1、对象已死吗

1.1 引用计数器算法
定义:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当应用失效时,计数器就减1;任何时刻计数器为0的对象就是不可能再被使用的对象。
缺点:循环引用。

1.2 可达性分析算法

通过一系列成为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径成为引用链(Reference Chain),当一个对象到GC Roots没有任何应用链项链时,则证明该对象不可用。
在java中 可作为GC Roots的对象包含以下几种:
(1)虚拟机栈(栈帧中的本地变量表)中引用的对象。
(2)方法区中类静态属性引用的对象。
(3)方法去中常量引用的对象。
(4)本地方法栈中JNI(即一般说的Native方法)引用的对象。


1.3再谈引用
jdk1.2以后,java对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)四种
(1)强引用就是指在程序代码中普遍存在的,new出来的对象,只要强引用存在,垃圾回收器就永远不会回收这部分引用。
(2)软引用就是用来描述一些还有用但是非必须的对象,在系统将要发生内存溢出时,将把这些对象列在二次回收的范围。如果这次回收后还没有足够的内存,才会抛异常。
(3)弱引用用来描述非必须的对象,强度比软引用更弱,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。
(4)虚引用也成为幽灵引用或者幻影引用,是最弱的一种引用。一个对象是否有虚引用的存在,完全不会对其生存时间构成引用,也无法通过虚引用来取得一个对象实例。
1.4 生存还是死亡
即使可达性分析算法中不可用的对象,也并非直接回收,还会经过两次标记过程。
第一次标记:第一次筛选的条件是此对象是否有必要执行finalize方法,如果该对象的finalize方法被覆盖过或者finalize方法已经被虚拟机调用过,当没有时,虚拟机认为没有必要,直接回收。
如果认为有必要执行finalize方法,那么这个对象将会放在一个叫做F-Queue的队列中,并在稍后由一个虚拟机自动建立、低优先级的Finalizer线程中执行,所谓执行,是指虚拟机会触发这个方法,但是虚拟机并不会等待该方法执行完毕。finalize方法是对象逃脱死亡的最后一次机会。如果在该方法中自救成功。那么在第二次标记时将被移除“即将回收”的集合。
第二次标记:第二次标记发生在F-Queue队列中。
1.5回收方法区
方法去(永久代)的回收包括两部分:废弃常量和无用类。
废弃常量的回收和java堆中对象的回收很相似,没有引用,常量就会被系统清理出常量池。
类需要同时满足下面三个条件才能判断为无用类:
(1)该类所有的实例已经被回收,也就是java堆中不存在该类的任何实例。
(2)加载该类的ClassLoader已经被回收。
(3)该类对应的java.lang.Class对象没有在任何地方被引用,无法再任何地方通过反射访问该类的方法。
在大量使用反射、动态代理、CGLib等的ByteCode框架频繁的自定义ClassLoader的场景都需要虚拟机设置类卸载的功能,以保证永久代不会溢出。
原创粉丝点击