Android菜鸟的提升之路---java面试学习及深入探究(四)

今天说一下Java的GC:

首先,在面试的时候,我们android程序猿会被问到很多java方面的知识,GC基本上都是会问那么太浅显回答肯定得不到面试官的青睐。那么我来谈谈我自以为深入的理解:

java的对象都是放在java堆里面的,也就是你new出来的东西(这里解释一下,java是面向对象的语言,那要知道什么是对象,在学习C语言的时候我们接触了 int short long char double float boolen byte等等,这些是变量,一般你不是去new一下,当然你开心new也没事。  那么其它的很多都是对象了,也就是由类new来的)这里补充一下变量是放在java栈里面的。

下面我模拟一下java堆来详细讲一下GC的原理:

首先堆被分为三代 新生代 老年代 持久代(想想也知道是递进的关系了)


Android菜鸟的提升之路---java面试学习及深入探究(四)

盗了一波图,自己画丑

首先分析新生代,这里记住了在新生代里面 执行的是minorGC(根据英文直接翻译:次要的GC)

你开始new了,当你一次次new,把这些对象放在了Eden(英语翻译:伊甸园)只要Eden没有满那么你不需要担心,GC不会执行,

但是慢慢地,Eden满了,好,minorGC出来把不用的消亡的对象清理了,然后把Eden没有被清理的对象放到From里面,

那么这个时候Eden空了,你之后new的对象又可以进来了,然后又满了,minorGC出来控场,把消亡的清理,同时把上次From的里面消亡的也清理掉,然后把这些打包起来给To,

这个时候 To 改一下名字叫“From”,From改名叫“To”(就像小时候没有冰箱,要喝冷水需要两个杯子,左手倒到右手,右手倒到左手,一样的道理,那么每次倒完总有一个杯子是空的,空的那个永远叫"To",有水的永远叫“From”)

但是总有一个时候发现被你“倒满了”那么这个时候剩下的对象就全部到了老年带了,

当然你不可能一次次minorGC,每次minorGC一次,对每一个活的对象标记一下,如果标记到了15以后还或者,恭喜你,去“老年代”养老去吧,

老年带相对安稳一点,当老年代满了一个就要进行一次FullGC(完全的GC)或者叫MajorGC(主要的GC)速度慢,比minorGC慢10倍。

最后就是持久代,JDK8把它给去掉了,直接保存在本地了,为什么呢?因为一个对象(数据)经历了新生带,被minorGC了15次还活着,然后在老年代还活的好好的,那么可以认为它长生不老了,之前是把这些长生不老的放到持久代(永久带)但是这些东西越来越多会造成最终的OOM,所以把这些当主程序运行时永远在的对象放到了本地内存。

那么既然讲到了GC,顺便把java四类引用讲一下,个人理解,可能不是很全面:

首先四类引用是:强引用 软引用 弱引用 虚引用

强引用:你平时最普通的操作 A a = new A();  当a没有被赋值为null或者没有超出作用域时,即使OOM也不会被GC(地位最高)

软引用:没有快要发生OOM前和强引用一样,但是马上要OOM,对不起,a被GC(地位第二)

弱引用:只活一次,只要当GC的线程来了,发现有你,不管什么情况,对不起,直接GC(地位第三)

虚引用:没什么存在感,和没有引用一样(你去获取值,永远是null)一般用于监控对象的创建和销毁(这个一般用于。。。是网上看来的,没有试过,感觉大家都这么说,很社会,学一波,哈哈哈)

好了,还是回归GC:

下面是自己社会的总结:

首先 拿3个对象(a,b,c)举例,开始a,b,c都在(Eden)伊甸园愉快的生活,但是慢慢的(Eden)伊甸园满了,minorGC来清理了,a因为消亡被清除出去了,b,c活了下来,和其它活的伙伴被放到From里面(这个时候他们身上多了一个标记是1),他们走了,Eden慢慢多了很多新来的,满了,minorGC清理,b,c也被扫描一下,还活着,把b,c放到“To”,然后把“To”改名“From”,From改成“To”(b,c身上标记变成2)(为什么改名字,为了让他们自以为永远活在From里面,其实早就改来改去了,很社会)然后一次次这样,b,c标记到了15,b,c合格了,可以去老年带享福了,当他们开始享福的时候,老年代的人越来越多了,然后没办法,没地方了,开始全面检查FullGC(MajorGC)(用了标记—清理算法),把老年代消亡的也清除出去,这个时候b走了,c还在,c经受了考验,慢慢的c越来越重要,把c放到了本地内存了,好了,c圆满了。


都是字,网上总结而来,希望对大家有帮助!好好看完应该会有一个相对全面的了解,但有一些细节可能存在问题,发现了可以修改,慢慢进步1