[jvm解析系列][三]Java的垃圾回收(一)如何鉴别垃圾,四种引用类型

垃圾回收就想垃圾车,每次天亮就会沿着街区开一圈,把垃圾都带走。

有的区域不需要这种垃圾车,也许它们不造垃圾吧,作为一个中级图钉我对这种地区很无奈,但是它们就是很少有垃圾甚至没有垃圾。首先应该是程序计数器,这玩意要什么垃圾回收,我都不用讲。下一个应该是虚拟机栈本地方法栈,栈帧的进出都受到控制,谁的垃圾谁带走,在进门的时候就算清楚了你要用多少内存,最后你再全部带走一点垃圾也不剩也不需要。(还有一个原因,是上述三个区域都是线程私有的,当线程撤退的时候把垃圾也都带走了)

那么根据第一章讲的,我们还剩几个区域?不记得就回去看吧^_^

还剩方法区(又称永久代)java堆。也就是说只剩这两个区需要垃圾回收了,垃圾佬表示很兴奋啊,终于有垃圾收了。(虽然叫永久代,但是现在永久代也是回收垃圾的,只是垃圾的回收率低,并且条件十分苛刻)

那么什么是垃圾呢?垃圾如何定义呢?

嗯,在我们的概念中,不要的东西就是垃圾。在程序中如何确定一个对象我们不用了呢?,引用计数法,也就是每当该对象被引用时+1,被去引用时-1,到引用为0的时候也就是该对象变垃圾的时候。嘿嘿嘿,我又瞎说了,没错是有这么个用法,但是主流jvm一个都没有使用这种方法定义垃圾的!

为什么呢?这个方法不是挺好的么?

我举个例子,如果我有

A a = new A();

 B b = new B();

a.b = b;

b.a = a;

这样的情况下是不相互调用了?如果看不懂没关系我画幅图给你

你蒙蔽了吗,是不是a和b对象直接就这样泄漏了,我的妈,你的android如果用这种方式定义垃圾你是不是半天就得重启一回防止累计下来的大量的内存泄漏呢?

所以我们的jvm没有选择引用计数算法,我们采用了可达性分析算法

在大多数商用的有垃圾回收的语言中多数都是采用这个算法的。简单的说来就是从某一个GC Roots开始往下找引用,没找到的就是垃圾。具体请看图:


图一帖上来打架都应该清楚了。1和2是垃圾,要回收。这个就是可达性分析算法。那么1说了:“凭什么root可以作为GC Roots”而我不行!“2跟着附和:”这中间肯定有不可告人的“某图钉:”py交易“。

其实并不是这样,GC roots是有要求的,我们来分析一下,我们说一个对象不是垃圾,肯定我们是能得到的,我们在写程序的时候什么类型是可以在任何地方都能得到的呢?

1、虚拟机栈中引用的对象(即我在写方法的时候A a =new A(),在方法没结束的时候就是a就是可以作为root使用的)

2、方法区中类静态属性(所以啊,我们应该少用类的静态属性,不然内存回收不了)

3、方法去中常量引用的对象

4、本地方法栈中JNI引用的对象

当一个类型是上述四个中的一个的时候,能跟他攀上关系的对象都不会被回收。

但是!后来改革了你知道吗?(四种引用强度)原本的时候攀上一个大佬就高枕无忧了,但是在jdk1.2之后这些对象引起了重视被改革了。

号外号外!一号文件规定以后引用不再是boolean类型了,不再是有或者没有的问题了~

它变成了四类引用

1、强引用

强引用是大家最常见的引用,他是jvm必不可少的,当强引用过多时宁愿oom也不回收内存,最常见的应该就是new出来的对象了。

2、软引用

软引用如果jvm不缺内存的话不会回收,一旦缺少内存就会回收软引用而不是报oom。SoftReference一般都是软引用

3、弱引用

弱引用更不用说了,只要被jvm扫描到了立即回收。WeakReference一般都是软引用

4、虚引用

虚引用。。。这玩意一不小心就没了,至于他为什么和弱引用分开是因为他有特殊的机制,在jvm回收内存的时候如果这个对象是虚引用,必须把这个虚引用放在引用队列里,如果引用队列里有一个虚引用说明这个对象要挂了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章