1.概述java与c 相比,在内存的分配与回收方面更加具备“自动化”,似乎我们并不需要了解虚拟机GC与内存分配。然而当需要排查各种内存溢出,内存泄露的问题时,当垃圾收集成为系统优化的瓶颈时,我们必须了解JVM的“自动化”技术,以实现对其的监控与调节。
2.确定哪些内存需要回收我们可以肯定的是,我们需要回收的对象是那些不再使用的对象,在c 中我们通过析构函数释放对象占用的内存空间。而在java中,这一步是虚拟机帮我们完成的。那么在回收对象的内存空间之前,虚拟机需要判断哪些对象是无用的。下面介绍两种算法: 2.1 引用计数算法
给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失效时,计数器就减1。当计数器的值为0时就认为这个对象是无用的。 这种算法简单易懂,判定效率也很高,不需要进行复杂的计算,但是其很难解决对象之间相互引用的问题。比如下图: objA引用B,objB引用A,这时就算我们不在使用A和B了,但由于A和B之间相互引用导致引用计数器的值不为0,通过引用计数算法无法将其回收。正是由于这种算法的弊端,所以主流的java虚拟机都没有选择这种算法来管理内存。 2.2 可达性分析算法
通过一系列的称为“GC ROOT”的对象作为起始点,从这些节点通过其指向其他对象的用用向下搜索,搜索走过的路径称为引用链,当一个对象到“GC ROOT”之间没有引用链就认为其是不可用的。也就是从root开始不可达的节点对象为无用对象 图中对象4,5,6不可达。
3.java的引用
在JDK1.2之后,java对引用的概念进行了扩充,将引用分为:强引用,软引用,弱引用,虚引用。
4.什么时候回收对象的回收至少要经历两次标记过程:如果对象在进行可达性分析后,发生没有与gc root相连的引用链,那它将会被标记并进行第一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖该方法或者已经执行过,虚拟机将这两中情况记为“不需要执行。要进行finalize()的对象放入F-Queue队列中,由一个finalize线程去执行”。GC稍后将会对F-Queue中的对象进行第二次小规模的标记。除非对象在finalize()方法中拯救自己(创建了到gc root的引用链),否则它就真的会被回收。
5.垃圾收集算法
不同虚拟机的垃圾收集算法的实现各不相同,这里只介绍几种算法的主要思想。 5.1标记-清除算法
该算法分为
5.2 复制算法它将可用的内存按容量划分为大小相等的两块,每次只使用一块,当这一块用完的时候,就将还存活的对象复制到另一块上面,然后再把已使用过的内存空间一次清理掉
5.3.标记-整理算法
标记过程与 5.4分代收集算法当前商业虚拟机的垃圾收集都采用“分代收集”(Grenerational Collection)算法.其将java堆分成新生代和老年代。新生代中选用复制算法,老年代中使用“标记-清除”或者“标记-整理”算法。
来源:http://www./content-1-121351.html |
|