概要:jvm运行时数据区如下图(JVM内存区域)
一。垃圾回收主要发生在堆,极少量发生在方法区(回收静态变量、常量池等)。因此GC可以说成是堆的回收
GC回收啥样的对象?=什么对象被认为是不在存活状态
这里得谈谈对象的几种引用:
对象引用被设计的原因:
1.能够主动的去决定对象的生命周期
2.利于JVM垃圾回收
强引用,比如A a = new A("111"),像这种就不会被回收,不管是否被使用,但是可以人为的令a=null让在GC时回收。如果不null(null的作用是中断强引用与对象关联)就永不回收。
软引用,一般通过SoftReference r = new SoftReference (a)修饰, 像这样内存紧张时会回收,一般不回收,不过使用时需要注意判断是否为null,有可能已经被回收了。
弱引用,一般通过WeakReference r = new WeakReference(a)修饰, GC回收时一定被回收。若a同时又关联强引用则也不会被回收。
虚引用,PhantomReference,和其他引用不同,并不会影响对象的生命周期,必须要跟引用队列ReferenceQueue联合使用,当垃圾回收期准备回收带有虚引用对象时,会将虚引用加入到已关联的引用队列中, 通过判断虚引用在队列存在就知道对象即将要被回收,所以此时可以提前做一些操作了。
常见应用场景:比如解决OOM,通过软引用跟弱引用。
解决对象何时回收:
1.通过引用计数算法
当A对象被B对象引用时(每个对象都自带一个引用计数器),则记录A被引用的次数(假设记录的变量为n,则n)+1,若B被回收了则n-1,若n=0则说明该对象不再可用需被回收。
该种算法存在问题:当对象间循环相互引用则会发生永不被回收
2.可达分析算法
从GC root对象向下搜索的所有路径中的对象都视为活的(这一连串可以称为可达的引用链),无法达到的其他的对象都随时可被回收。
流程图如下:此时对象Object5、Object6、Object7到GC Roots就没有引用链,所以是可回收对象
该算法是jvm默认的,天然的解决了循环引用问题。
在Object类下有个finalize()方法,JVM规范之所以不提倡使用这个方法在于它会影响GC可达性分析,造成对象起死回生从而不被回收。
因为篇幅问题,其他问题只能下篇,右边传送门,java之GC垃圾回收二