hi,大家好,我是”吹毛”,本人现在新出了一个系列叫做”吹毛光”系列,全称”吹毛光速讲解”
相信大家用头条看这篇知识文章也是喜欢利用零碎的时间来学习把,
各位勤勉的同胞相信可能都在地铁,公交,排队,或者空余时间才看到头条的这篇文章吧.
如果是零碎的时间,长篇大论谁会看?谁能看得完?
所以,”吹毛光”系列来了!”吹毛”本人会吧一些复杂难懂,高深糊涂的概念和长篇大论的文章进行总结归纳,
再用生动形象的例子来为大家献上干货,短小却不失内涵,精简而不失要领.
喜欢本人的作品请点击关注呦.
废话不多说,下面开始简单粗暴.
这篇文章也是我准备很久才敢去写的,因为这涉及的东西非常多,怎么才能在有限的篇幅里讲清楚gc垃圾回收那么复杂而且多的事情是非常有挑战的.
所以呢,我,接受挑战!
接受挑战
这里所需要一些java运行时数据区和内存模型有关的基础知识,不知道的没关系,关注然后看看我前几篇
关于JVM的全方位剖析.
都非常生动形象,广受好评,欢迎品尝!
大伙们是不是经常面试被问到,
“来说一下gc垃圾回收机制”
“gc是在什么情况下收集对象的?”
“怎么判断对象死没死?”
我日,我就知道java垃圾回收是自动的,甚至连gc垃圾回收是啥都不清楚,还问我那么多?
不是自动的嘛?还问那么多干啥,
自动的多省事,你想知道gc什么时候收集对象?想知道怎么判断对象死没死?
自己去问jvm去啊!问我干啥!
四不四,四不四!是不是大家都和我有一样的想法????
对,”吹毛”我在经过无数的探讨和深入的调查后,终于开始明白为啥问这个问题了
-
面试官想知道你这个人基础怎么样
-
他想看看你这个人是否是一个善于钻研的人
-
看你有没有好奇心,能不能对本公司使用的东西感兴趣
-
你能不能解决jvm偶尔出现的这方面的问题
看到了吧,这就是面试官问你问题的原因.这个知识点能很好的反映出你这个人的精神状态
另一个方面,内存溢出这个问题也确实经常出现,它虽然是自动的,但是不够聪明不够智能啊,总会出现问题,而面对这种不经常出现问题,一旦出现了,因为是自动的,你还不了解原理,那真是两眼一抹黑,没有了java虚拟机,你还拿什么去写代码?
还有最重要的一点,学会这个技术,不仅可以装b,而且可以涨工资!
似乎看到了满手的钱…….
行了,动力十足了吧!所以别再说它没用.
弄明白了为什么学,下面”吹毛”开始教大家 怎么学.
相信大家都对第一个程序 “Hello World”印象深刻把?对!这是你对这个世界的第一声呐喊!
那咱们今天学的是什么呢?
“stop the world!”
没错,咱们要学习的就是停止这个世界,将世界暂停!然后用gc垃圾回收器将垃圾回收,最后再让世界继续!
当 stop the world 发生的时候,除了GC所需要的线程外,所有线程都处于等待状态.直到GC的任务完成.
大家知道java虚拟机运行时数据区都分为哪些把(之前文章有):程序计数器,java虚拟机栈,本地方法栈,方法区和堆.
而根据之前所说,栈中不存有数据只存有逻辑,而堆和方法区中会存放很多大量的实例与数据.
所以呢,垃圾回收垃圾回收,肯定是要对垃圾的数据进行回收,所以回收都集中在方法区和堆中,而堆又是存放大量实例的地方,而新new的实例据IBM公司的专门研究表明,对象98%是“朝生夕死”的,基本都是短命鬼,所以在堆中会产生大量的垃圾数据.
好,数据的概念讲好了,那就可能会有人问了,垃圾是个什么概念?什么样的被定义为垃圾而被回收了呢?
勤劳的GC
举一个最简单的例子,
A a = New A();
a=null;
好,上面的代码做了两件事,第一件事,new了一个对象A,也就是第一行等号后面的
(
想知道new对象的具体细节麻烦关注”吹毛”本人查看
“吹毛光”系列:面试常考!java单身狗到底是如何new对象的呢?
,有超生动讲解
)
第二件事,定义了一个小a 也就是第一行等号前面的,这个小a其实就是一个小小的指针(类似于一个专门指向数据的箭头)
第三件事,将第一行的左和右连接起来,让小a指针指向了 大A()这个实例
到这里为止,如果你想调用这个大A()实例,直接写一个小a,就代表了这个大A()实例了,
也就是说这个大A()实例在堆里现在是可以被找到的.有一个小a一直指着它
然而,在执行第二行的时候,小a不指这个大A()实例了,而是改向了一个null,
这代表着 现在小a指向了另一个地方,另求新欢
那,,,原来的大A(),此时就变成了孤家寡人,静静的躺在堆里面,再也没人知道他的存在了.
这个A(),就是咱们最后要清理的垃圾数据,gc需要在堆里来回寻找这样的无人问津的老人,然后让他们入土为安.
那我们现在需要来看一下,具体gc是如何来巡逻的?他们又有什么标准来判定谁是被人抛弃的,谁是有用的呢?
gc巡逻兵
在jvm区域中的堆里分为:Eden Space(伊甸园)、Survivor Space(幸存者 区)、Tenured Gen(老年代)
前两个区统称为新生代.
在新生代中,有一个Eden Space和两个Survivor Space,按8:1:1分配
大多数情况下,,新生对象主要分配在eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB(这个概念后面讲)上分配。对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC(也就是新生代的gc垃圾回收,动作非常频繁,回收速度较快)。
而大对象,就是需要连续空间的那种java对象则直接分配进了老年代中.
下面我将着重讲解一下,gc是如何垃圾回收的!
嗯..用一种生动的方式吧,方便于大家理解.
当一个对象刚刚诞生的时候,它会出生在”伊甸幼儿园”(Eden Space),我们给他命名叫”ChuiMao”,当然还有很多其他的对象也同时诞生在这里,但是呢,大部分对象基本上都是出生就夭折了,我们的”ChuiMao”坚强的活了下来.在这个地方有一个叫GC的清理员,当这个”伊甸幼儿园”(Eden Space)人满了的时候,它就会出动,来搜寻幸存者,把它们转移到一个叫”幸存者一区”(Survivor Space)的地方,”ChuiMao”也就跟着转移到了这个”幸存者一区”(Survivor Space),当GC清理员确定所有幸存人员全部转移后,它放了一个核弹,把这个”伊甸幼儿园”(Eden Space)里还剩余的所有对象全部干掉了,干掉以后的空间用来留着给其它新诞生的对象们.
宝宝们
我们的”ChuiMao”于是就在这个叫”幸存者一区”(Survivor Space)的地方幸福的长大,不过随着时间的推移,这里也依旧会有死掉的对象,当达到一定程度的时候,我们的GC清理员又来在”幸存者一区”(Survivor Space)里把所有幸存的对象转移到另一个”幸存者二区”(Survivor Space),同样的,又经过一段时间,在幸存者二区也有对象死亡,于是GC清理员又会把我们的幸存者转移回”幸存者一区”(Survivor Space),也就是来回折腾(话说GC好累哦),当我们的”ChuiMao”15岁的时候,也就是折腾了15回之后(系统默认),因为如果折腾这么多回你还存在的话,说明你经受住了考验,它被认定为是一个长寿对象,那么恭喜你,你升级了,你终于不用再像之前一样被弄来弄去了.这个长寿对象会被转移到”老年代”(Tenured Gen)中,
15岁就老了…
在”老年代”(Tenured Gen)中,他们就会安安稳稳的度过晚年,基本只有在空间彻底满了,在新生代中来回小幅度折腾已经不足以腾出足够的空间的时候,才会运行Full GC(老年代的GC),此时jvm gc停止所有在堆中运行的线程并执行清除动作。
于是,一个对象就此走完了他的一生..而GC依旧在勤劳的工作,供养一批又一批的对象们…..
这满满的都是无私的爱
以上就是gc垃圾回收的机制讲解.
最后我再强调一点,
在java中,我们对于垃圾回收是普通百姓,没有强大的控制权,在Java程序中不能显式地分配和注销内存。有些人把相关的对象设置为null或者调用System.gc()来试图显式地清理内存。设置为null至少没什么坏处,但是调用System.gc()会显著地影响系统性能,必须彻底杜绝!请各位记住!
讲解结束。
怎么样,听完我这篇对GC垃圾回收的讲解文章是不是对你有所帮助?
我希望对你是有所帮助的,哪怕是一点点,
当然啦,这次的垃圾回收我是从概念与运行逻辑上下手的,下一次我会从gc垃圾回收的算法入手.
如果你面试能答出gc回收过程,面试官会觉得还可以.
如果你面试能说出具体的gc垃圾回收算法并且实现,那面试官绝对会对你刮目相看的!
理解的同时更需要掌握,jvm一直是所有初学者头疼的问题,那我来替你头疼,你只需要………
赶快关注“吹毛”的头条号哦,不要错过精彩!
最后感谢大家,再次手动比心。
依旧爱你们
声明:本站部分文章内容及图片转载于互联 、内容不代表本站观点,如有内容涉及侵权,请您立即联系本站处理,非常感谢!