标签:log 通知 自己的 设置 入栈 soft 程序 垃圾收集器 问题
前一章介绍了Java内存运行时区域的各个部分,其中程序计数器、虚拟机栈和本地方法栈3个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊的执行着出栈和入栈操作。每一帧分配多少内存基本在类结构确定下来时就已知了,因此这几个区域的内存分配和回收具有确定性,线程结束时,内存就跟着回收了,不需要太多考虑回收问题。而Java堆和方法区则不一样,一个接口的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期时才知道会创建哪些对象,这部分内存的分配是动态的,垃圾收集器所关注的是这部分内存。
在堆里存放着java中几乎所有的对象,垃圾收集器在对堆回收之前,首先确定这些对象中哪些活着,哪些已死。
给对象添加一个引用计数器,每当一个地方引用它时,计数器加1,当引用失效时,计数器减1。任何计数器为0的对象就是不再被使用的对象。
缺点:两个对象相互引用时,计数器永远不能减为0,即循环引用问题。
通过一系列称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则该对象是不可用的。
在Java中可以作为GC Roots的对象包括以下几种:
1)虚拟机栈中引用的对象
2)方法区中类静态属性引用的对象
3)方法区中常量引用的对象
4)本地方法栈中JNI引用的方法。
JDK1.2之后,Java对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用、虚引用。
1)强引用,指在程序代码中普遍存在的,类似“O o=new O()”这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉这类对象。
2)软引用,用来描述一些还有用但并非必须的对象。对于软引用关联的对象,内存溢出之前对其回收,如果内存还不够才会抛异常。可以通过SoftReference类实现软引用。
3)弱引用,用来描述非必须的对象。弱引用的对象只能生存到下一次垃圾收集发生之前。WeakReference类实现弱引用。
4)虚引用,为一个对象设置虚引用的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。PhantomReference类实现虚引用。
即使在可达性分析算法中不可达的对象,也并非非死不可,这时候他们只是处于缓刑阶段。要宣告对象的死亡需要两次标记过程:如果对象在进行可达性分析时发现该对象没有与GC Roots相连的引用链,那么第一次标记该对象并且进行一次筛选。筛选条件是对此对象是否有必要执行finalize()方法。但对象没有覆盖finalize()方法或者finalize()方法已被虚拟机调用过,虚拟机把这两个情况视为“没有必要执行”。
如果对象判定为有必要执行finalize()方法,那这个对象放在F-Queue队列,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去执行。finalize()方法是对象拯救自己的最后一次机会。如果在finalize()方法中重新与引用链的对象发生关联,那么第二次标记时将他移除“即将回收”的集合。
方法区在HotSpot中是永久代,对方法区进行垃圾回收性价比较低。
永久代的垃圾回收包括两个部分:废弃常量和无用的类
标签:log 通知 自己的 设置 入栈 soft 程序 垃圾收集器 问题
原文地址:http://www.cnblogs.com/wuchaodzxx/p/6721937.html