玉林社区   吃喝玩乐购   说说:面试时候总喜欢问的 JVM 要点在哪
返回列表
查看: 347|回复: 0

说说:面试时候总喜欢问的 JVM 要点在哪

[复制链接]

1590

主题

1590

帖子

5790

积分

论坛元老

Rank: 8Rank: 8

积分
5790
发表于 2022-2-22 12:00:31 | 显示全部楼层 |阅读模式

马上注册玉林红豆网会员,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

什么是新生代?主要是用来存放新生的对象。一般占据堆空间的1,由于频繁创建对象,所以新生代会频繁触发MGC进行垃圾回收。[url=http:///www.wangsu.com/]视频加速[/url]的具体问题可以到我们网站了解一下,也有业内领域专业的客服为您解答问题,为成功合作打下一个良好的开端![align=center]

                               
登录/注册后可看大图
[/align]


本文转载自微信「J极客技术」,作者鸭血粉丝T。转载本文请联系J极客技术。


面试的时候,很多面试官问JVM的时候,我们作为一个开发者,很多时候很难G到面试官提问的要点,因为JVM确太多了,从程序计数器开始,然后堆,然后栈,但是面试的时候却总是回答不好这个问题,很多情况就是没有系统的去看过所以回答面试题的时候,会出现语伦次,这一块内容,那边一块内容,总是回答不好,几天阿粉就来分享给大家一个JVM的面试教程,对你有用的话,点赞关注和收藏一波。


你对JVM了解么?
首先,问这个问题的,一般都是问完了一些基础了,这时候需要你自己从头开始说JVM了,很多人际上想到就是垃圾回收机制,确,没错,但是,如果你直接就开始说是不是垃圾回收机制的时候,就已经有点答非所问了。


为什么这么说,因为JVM的垃圾回收机制,都是发生在堆内存的,但是,JVM的划分可不是只要堆内存的,这时候回答应该怎么回答?


**JVM的内部结构,最主要的内部结构是什么!**


JVM分成了两个部分


1线程共享区域


2线程私有区域


线程共享区域包含:堆(H)、方法区


线程私有区域包含:程序计数器、虚拟机栈(S)、本地方法栈


因为JVM,那可是不单单只有堆(H)的存在呀,其他的存在也是不可缺少的,为什么阿粉要这么说呢?


因为有些面试官会问JVM的类加载机制你了解么?


如果你只是了解了垃圾回收机制的话,那你这个问题,是不是有点麻了,有点懵了,这不就芭比Q了么?


那么JVM的类加载机制是个什么呢?


回答:


首先通过类加载器(CL)会把字节码文件加载到内存中运行时数据区(RDA),而字节码文件只是JVM的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(EE),将字节码翻译成底层系统指令,再交由CPU去执行,而这个过程中需要调用其他语言的本地库接口(NI)来现整个程序的功能。


跑偏了,我们继续回答上一个问题,既然你说你了解了,你也回答了都有哪些内部结构了,是不是就该说说这些内容是干啥的了,对,没错,就是这么回答。



程序计数器:记录线程执行的位置,方便线程切换后再次执行
虚拟机栈(S):每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(SF),对应着一次次的J方法调用
本地方法栈:是为了执行方法所服务的

说完这个,没啥事别停顿,如果你停顿了,这时候面试官很有可能接着去问你栈的一些特性,你本身是想说垃圾回收机制的,总不能被带跑偏吧,所以,继续往下说。



方法区:线程共享,存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等等

最后我们再说堆(H)


堆是JVM中最主要的区域了,因为堆(H)是J虚拟机所管理的内存中最大的一块。


唯一目的就是储存对象例和数组(JDK7已把字符串常量池和类静态变量移动到J堆),几乎所有的对象例都会存储在堆中分配。


但是呢,随着JIT编译器发展,逃逸分析、栈配、标量替换等优化技术导致并不是所有对象都会在堆配。


这时候,一般面试官都会开始提问了,就会让你具体的说说堆内存。


JH堆
J堆是垃圾收集器管理的主要区域。堆内存分为新生代(Y)和老年代(O)


什么是新生代?


主要是用来存放新生的对象。一般占据堆空间的1,由于频繁创建对象,所以新生代会频繁触发MGC进行垃圾回收。


什么是老年代?


老年代的对象比较稳定,所以MGC不会频繁执行。


那么我们在分别来介绍一下JVM的新生代和老年代,就这两个,足够你和面试官聊上十几分钟的内容了。


JVM的新生代(垃圾回收机制)
新生代分为E区、SF、ST个区。



E区J新对象的出生地(如果新创建的对象占用内存很大则直接分配给老年代)。当E区内存不够的时候就会触发一次MG,对新生代区进行一次垃圾回收。
SF区上一次GC的幸存者,作为这一次GC的被扫描者。当JVM法为新建对象分配内存空间的时候(E区满的时候),JVM触发MG
ST区

保留了一次MG过程中的幸存者。


那么新生代会使用什么样子的垃圾回收机制呢?


我们每次对象的时候都会先在新生代的E区放着也就是最开始是这样子的





然后在E用完的时候里面会出现待回收的





然后就来了把存活的对象复制放到S1()中,待回收的等待给他回收掉就是这样的





然后把E区清空回收掉





这样的话第一次GC就完成了,下面再往下走


当E充满的时候就会再次GC


先是这个样子的





然后会把E和S1中的内容复制到S中,





然后就会把E和S进行回收





然后从E中过去的就相当于次数少的,而从S1中过去的就相当于移动了2次





这样新生代的GC就执行了2次了,


当E再次被使用完成的时候,就会从S2复制到S1中,


接下来是连图





经过回收之后S1就变了,1对象是从E直接复制过来的,2对象是E--S2--S1,对象则是从E--S1--S2--S1复制过来的,这样一步一步的执行下去的时候,就是新生代的GC。


这就是新生代采用的GC,如果你需要给面试官解释,那么你就得熟练的记住这个图,为什么这么说,因为只有你掌握了这个图,那么你绝对会把这个复制算法给面试官讲述的明明白白。


既然我们都知道了这个复制算法了,那么他到底有什么缺点呢?



堆利用效率低这是最明显的,空间都被劈成两半了,一次永远只能用一半就得搬家
递归调用在对子对象进行复制时,使用了递归方法,可能导致栈溢出

但是我们也得吹一下复制算法的牛逼的地方呀。


吞吐量高所谓吞吐量就是搜索活动对象的时间比上搜索堆时间,越高说明你的有效搜索占比越高,不难看出,我们都是从根开始,搜索的全部是活动对象,并没有浪费时间去搜索垃圾对象。这个优势在堆越大的场景下越明显。


没有碎片


在将活动对象复制到T空间时,他们都是紧挨着的,然后清空F时全部清空,完全没有碎片的可能。


这也是新生代使用的垃圾回收的算法。


JVM的老年代(垃圾回收机制)


老年代的垃圾回收机制,采用的则是和新生代不一样的方式,有些人称之为FGC,而FGC出现的原因则是:在新生代如果说存在的对象或者说新创建出来的对象由于某些原因需要移动到老年代中,但是老年代中压根就没有这么大的内存空间去容纳这个对象,那么就会引发一次FGC,如果在执行完FGC之后,还是没有办法给这些对象分配内存,那么凉了,该抛出异常了,异常类型就是OOME。


而FGC使用的是和MGC不一样的算法,它使用的是标记清除算法,听字,挺好理解的,来波图示解析一波。深入了解JVM一书中的图示是这个样子的,





图示是不是看着也挺明确,先标记,然后在删除。



标记(M)过程:找到所有的可以访问的对象,做个指定的标记。
清除(S)过程:遍历堆内存,把未标记的对象进行一个回收。

在了解了这个之后,我们还得说一个概念,那就是GCR,R我们可以理解成一个根节点就像这个样子





上图中的,,,,就是活着的对象,如果说存在这引用,比如说引用的,那么他就是属于活着的对象。当我们老年代内存区中的有效的内存空间不够的时候,那么这时候整个世界都要安静下来了(),这时候就要开始准备进行垃圾回收了。



标记:遍历所有的GCR,然后将所有GCR可达的对象标记为存活的对象。就是我们图中所标记的,,,?清除:清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。也就是说,如果内存不够,GC线程就会被触发然后将程序暂停,随后将依旧存活的对象标记一遍,最后再将堆中所有没被标记的对象全部清除掉,接下来便让程序继续恢复运行。

流程图就像这个样子的初始下的老年代中的对象状态





这时候都是没有被标记的状态,接下来内存不够,GC线程停止,开始进行标记了





按照根节点开始遍历标记的都是存活的对象,接下来开始标记。





接下来就是清除数据了





清楚完成之后还有就是把标记去除掉,可以下次进行标记清除的时候继续清除





其这个阿粉的老读者肯定看过,因为很早之前阿粉就画出过这个图。


这样标记清除就执行完毕了。


这时候不吹不黑,肯定会有优缺点,不然为啥不采用其他的方法呢?毕竟JVM肯定是会选择最适合自己的方式来进行GC的。


缺点清除后的堆内存由于空间不连续,即内存碎片化,若下一次需要分配对象的内存大于碎片空间,这样会提前触发GC,当提前触发的GC回收后,空间还是不足就会出现OOM等错误。


时间问题:由于分为两个过程(标记、清除),当堆内可回收对象较多时,该算法需要进行大量的标记与清除,这里就产生一个问题,随着可回收对象的的增多,标记和清除的效率就会下降;再者由于空间不连续导致每次再次分配都要遍历空闲列表。


有点


现简单,与保守式GC算法兼容这阿粉真的说不上他其他的优点了,除了能够解决引用计数算法带来的不能清除循环引用的问题外,阿粉在不知道了。


关于JVM的知识要点,你学会了么?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

收藏:1 | 帖子:8万



侵权举报:本页面所涉内容均为用户发表并上传,岭南都会网仅提供存储服务,岭南都会网不承担相应的法律责任;如存在侵权问题,请权利人与岭南都会网联系删除!