JVM学习之垃圾回收
在我们除学习Java的时候,就知道Java的内存回收机制,虚拟机可以将我们不用的变量进行回收掉,从而使我们的系统不至于因为垃圾太多而终止运行,在阅读完《深入理解Java虚拟机》关于内存回收的描述之后,在此将自己的理解做一些总结,
在我们将要进行垃圾回收之前,首先要确定哪些是垃圾,基本上所有的对象实例都分配在堆内存。那么第一件事就是要判断,哪些对象还存活着(也就是还在使用),可以被引用到,哪些对象已经死亡(也就是说不可能在被引用了)。在进行判定的时候,我们可以用以下方法来判断:
引用计数算法:每个对象都添加一个计数器,当他被引用一次的时候就+1,引用失效的时候就-1,当计数器为0的时候,也就是说不可能在被使用了,这样做的优点很明显,实现起来简单,而且判定也比较准确,但是它有个明显的问题就是不能解决循环引用的问题。
可达性分析算法:这是另一种判定的方法,通过一系列的作为GCroot的对象,虚拟机会从GCroot沿着对象传递引用的链来寻找,如果找不到,就表明这个对象是不可达的,也就是该对象可已被回收,可以作为GC root的对象有:虚拟机栈(即局部变量表里边引用的对象),方法区类静态属性引用的对象,方法区中常量引用的对象,本地方法栈中引用的对象。
Java将引用按强度分类分为4种,强引用,当强引用存在时,其引用的对象不会被回收;软引用,如果内存溢出(也就是内存不够用的时候),其引用的对象会在下一次垃圾回收时进行回收,否则就不回收;弱引用,其引用的对象在下一次GC发生时被回收到,无论是否发生内存溢出;虚引用:对其所引用的对象生存时间没有实质的引用,其存在的作用就是在其引用的对象被回收得到通知,并且无法通过虚引用来引用一个对象的实例。
在垃圾收集器对对象回收之前首先对GCroot不可达的对象进行第一次标记,然后进行筛选(判断该对象是否有必要执行finalize()方法,finalize()方法只能被调用一次。),如果有必要执行时,就会放在一个处理队列里等待虚拟机处理,虚拟机会触发该对象的finalize(),但是不承诺会等待它结束,防止他进入死循环而阻塞后边的进程,然后在finalize()执行完之后,在对那些仍旧没有被引用的对象进行第二次标记,然后开始进行回收,换而言之,该对象可以在自己的finalize()方法里让别人引用自己,这样自己就不会被回收了,从而拯救自己。
一般来说,垃圾回收主要指的是Java堆的垃圾回收,但是方法区也是可以进行回收,只不过性价比比较低,在这里回收的主要为废弃的常量和无用的类:废弃的常量,即就是在没有人引用的时候,当发生垃圾回收的时候进行回收,而判断一个类是否为无用的类有以下3个条件,该类的所有实例是否已全部被回收,该类的ClassLoader是否已经被回收,该类的Class对象有没有被引用。只有满足以上三个条件时,该类变可以被回收,但并不是,一定要被回收。
垃圾收集算法一般可以分为标记-清除算法,缺点是效率不高,而且清除完之后会产生不连续的内存碎片,导致以后再分配较大对象时,会提前出发下一次GC;复制算法,将空间分为两部分,这里用A和B表示,当A的快用完时,将A上存活的对象复制到B上,然后回收A,这样就可以进行使用了。一般来说将Java堆的新生代分为一个Eden区域和两个Survivor区域,比例为8:1:1;每次可以使用90%,当往剩下的10%的Survivor上复制对象时如果空间不够时就要像老年代进行分配担保;标记-整理算法:这个是在标记-清楚算法的基础上,让回收完还存活的对象往一侧移动,这样剩下的空间就是连续的了。
一般来说对于Java堆,使用分代收集,新生代采用复制算法,老年代使用,标记-清理或者标记-整理算法进行清理。
在我们除学习Java的时候,就知道Java的内存回收机制,虚拟机可以将我们不用的变量进行回收掉,从而使我们的系统不至于因为垃圾太多而终止运行,在阅读完《深入理解Java虚拟机》关于内存回收的描述之后,在此将自己的理解做一些总结,
在我们将要进行垃圾回收之前,首先要确定哪些是垃圾,基本上所有的对象实例都分配在堆内存。那么第一件事就是要判断,哪些对象还存活着(也就是还在使用),可以被引用到,哪些对象已经死亡(也就是说不可能在被引用了)。在进行判定的时候,我们可以用以下方法来判断:
引用计数算法:每个对象都添加一个计数器,当他被引用一次的时候就+1,引用失效的时候就-1,当计数器为0的时候,也就是说不可能在被使用了,这样做的优点很明显,实现起来简单,而且判定也比较准确,但是它有个明显的问题就是不能解决循环引用的问题。
可达性分析算法:这是另一种判定的方法,通过一系列的作为GCroot的对象,虚拟机会从GCroot沿着对象传递引用的链来寻找,如果找不到,就表明这个对象是不可达的,也就是该对象可已被回收,可以作为GC root的对象有:虚拟机栈(即局部变量表里边引用的对象),方法区类静态属性引用的对象,方法区中常量引用的对象,本地方法栈中引用的对象。
Java将引用按强度分类分为4种,强引用,当强引用存在时,其引用的对象不会被回收;软引用,如果内存溢出(也就是内存不够用的时候),其引用的对象会在下一次垃圾回收时进行回收,否则就不回收;弱引用,其引用的对象在下一次GC发生时被回收到,无论是否发生内存溢出;虚引用:对其所引用的对象生存时间没有实质的引用,其存在的作用就是在其引用的对象被回收得到通知,并且无法通过虚引用来引用一个对象的实例。
在垃圾收集器对对象回收之前首先对GCroot不可达的对象进行第一次标记,然后进行筛选(判断该对象是否有必要执行finalize()方法,finalize()方法只能被调用一次。),如果有必要执行时,就会放在一个处理队列里等待虚拟机处理,虚拟机会触发该对象的finalize(),但是不承诺会等待它结束,防止他进入死循环而阻塞后边的进程,然后在finalize()执行完之后,在对那些仍旧没有被引用的对象进行第二次标记,然后开始进行回收,换而言之,该对象可以在自己的finalize()方法里让别人引用自己,这样自己就不会被回收了,从而拯救自己。

浙公网安备 33010602011771号