前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[我的面试宝典] 我是如何去看《深入理解Java虚拟机》这本书的

[我的面试宝典] 我是如何去看《深入理解Java虚拟机》这本书的

作者头像
乔戈里
发布2019-04-24 16:43:55
2.5K0
发布2019-04-24 16:43:55
举报
文章被收录于专栏:Java那些事Java那些事

01

听我唠唠嗑

最近公众号收到了很多留言,有的同学想知道我是如何看书,如何学习的,也有的同学想知道我的项目经验和一些技巧。其实,这都不是问题。微信公众号一天只能推送一次,我尽量每次每篇文章多写点。

讲下现在的文章排版风格。看过我之前公众号文章的同学可能还记得,我第一篇是讲CAP理论的,用的写小说的手法,但说实话,太累了,构思艰难,剧情无聊,我写了一篇就放弃了。到了第二篇文章,无意中找到一个对话模板,觉得对话的形式比较简洁省力,写了几篇,但说实话,都是绞尽脑汁的成果,写的并不顺畅。直到,我写了那篇我一个二本大学是如何拿到百度、网易大厂offer的!文章,并受到广泛阅读与转载后,我才觉得,这才是我的写作风格,舒服!

进入公众号领域没几天,有过探索也是正常。从那篇开始,我写了[我的面试宝典] 这些不会的话,就别去面试了文章,一是反响不错,二是我自己写的真舒服。不过缺点就是内容还是少,的确,面试这么大的事,怎么可能就被我小小一篇文章解决。

本篇是[我的面试宝典]系列第二篇,详细讲解java虚拟机那些事以及我的看书方法,并延续我一贯的写作风格,over。

02

Jvm内存结构

Jvm内存结构,一般是面试官对Java虚拟机这块考察的第一问。讲真,还没背会,自己罚自己面壁思过。

Java虚拟机的内存结构一般可以从线程共有和线程私有两部分起头作答,然后再详细说明各自的部分,类似树状结构的作答,好处就是思路清晰,面试官听着也舒服。

线程共有的包括Java堆和方法区,线程私有的包括虚拟机栈、本地方法栈和程序计数器。这些内容回答一遍后,就可以开始详细叙述每个点的详细部分。

Java堆是用于存放Java程序运行时所需的对象等数据,Java堆又分为新生代和老年代。我们平常所说的垃圾回收,主要回收的就是堆区。更细一点划分新生代又可划分为Eden区和2个Survivor区(From Survivor和To Survivor)。

方法区中最为重要的是类的类型信息、常量池、域信息、方法信息。总之,方法区保存的信息,大部分来自于 class 文件,是 Java 应用程序运行必不可少的重要数据。

程序计数器用于存放下一条运行的指令,这里是唯一无内存溢出的区域。如果当前程序正在执行一个Java方法,则程序计数器记录正在执行的Java字节码地址,如果当前线程正在执行一个Native方法,则程序计数器为空。

虚拟机栈和本地方法栈用于存放函数调用堆栈信息。虚拟机执行java程序的时候,每个方法都会创建一个栈帧,栈帧存放在java虚拟机栈中,通过压栈出栈的方式进行方法调用。

很多人分不清虚拟机栈和本地方法栈的区别,因为本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。

03

垃圾回收算法

当你回答Jvm内存结构,八九不离十,下一问就问你垃圾回收算法。

我简单说一下,垃圾回收算法你可以先回答引用计数法,回答完后说明一下此算法的缺点(无法解决互相引用问题),再引入标记-清除算法,再说一下它的缺点(空间碎片问题),然后说一下复制算法、标记-压缩算法如何解决空间碎片问题,最后说一下分代。到了这个时候,你完全可以举例新生代,老年代使用的是哪种算法,进行一个补充。一般回答到这,面试官就没得问了。如果还要继续深入,你可以了解垃圾回收器,CMS、G1、并行、串行等,已备不时之需。

下面分别说一下上面提到的算法。

引用计数法:引用计数法的实现很简单,对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减一。只要对象A的引用计数器的值为0,则对象A就不能再被使用。

标记-清除算法:标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。

复制算法:将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存中的角色,完成垃圾回收。

标记-压缩算法:首先从根节点开始,对所有可达的对象做一次标记,但之后,它并不是简单的清理未标记的对象,而是将所有的存活对象压缩到内存空间的一端。之后,清理边界外所有的空间。

分代:将内存区域根据对象的特点分成不同的内存区域,根据每块区域对象的特征不同使用不同的回收算法,以提高垃圾回收的效率。

说在这里,我非常想补充一个冷门的考点,也是面试官不一定问的问题。

哪些可以作为GC中root的对象?这个问题的标准回答如下:

1.被启动类加载的类和创建的对象

2.栈内存中引用的对象

3.方法区中静态和常量引用的对象

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

04

垃圾收集器

垃圾收集器有独占式的串行收集器,也有加了多线程的并行收集器。如何选择一个合适的垃圾收集器主要参考的就是GC策略的指标。包括以下几个部分:

吞吐量:指在应用程序的生命周期内,应用程序所花费的时间和系统总运行时间的比值。 举个例子,如果系统运行了 100min,GC 耗时 1min,那么系统的吞吐量就是(100-1)/100=99%。

垃圾回收器负载:和吞吐量正好相反,垃圾回收器负载指垃圾回收器耗时与系统运行总时间的比值。

停顿时间:指垃圾回收器正在运行时,应用程序的暂停时间。对于独占回收器而言,停顿时间可能会比较长。使用并发的回收器时,由于垃圾回收器和应用程序交替运行,程序的停顿时间会变短,但是,由于其效率很可能不如独占垃圾回收器,故系统的吞吐量可能会较低。

垃圾回收频率:指垃圾回收器多长时间会运行一次。一般来说,对于固定的应用而言,垃圾回收器的频率应该是越低越好。

反应时间:指当一个对象被称为垃圾后多长时间内,它所占据的内存空间会被释放。

堆分配:不同的垃圾回收器对堆内存的分配方式可能是不同的。一个良好的垃圾收集器应该有一个合理的堆内存区间划分。

科普完以上知识后,我简单说一下串行、并行、CMS、G1。

串行回收器主要有两个特点:第一:使用单线程进行垃圾回收;第二:独占式垃圾回收。并行回收器只是简单的把使用单线程进行垃圾回收改为多线程进行垃圾回收,它依旧是独占式垃圾回收。

CMS是Concurrent Mark Sweep的缩写,意为并发标记清除,从名称上可以得知,它使用的是标记-清除算法,同时它又是一个使用多线程并发回收的垃圾收集器。与CMS收集器相比,G1收集器是基于标记-压缩算法的。

那为什么CMS和G1不是独占式的垃圾回收器?

CMS工作时,主要步骤有:初始标记、并发标记、重新标记、并发清除和并发重置。其中初始标记和重新标记是独占系统资源的,而并发标记、并发清除和并发重置是可以和用户线程一起执行的。因此,从整体上来说,CMS收集不是独占式的,它可以在应用程序运行过程中进行垃圾回收。

05

说下阅读感悟

周志明的《深入理解Java虚拟机》很好很强大,但阅读起来颇有点费劲,尤其是当你跟随作者的思路一直探究下去,开始会让你弄不清方向,难免有些你说的啥子的感觉。但知识不得不学,于是天天看,反复看,就慢慢的理解了。

我其实不想说这种硬磨的方法有多好,我甚至不推荐,我建议大家阅读这本书时,由浅入深,有舍有得,先从宏观去理解去阅读,再慢慢深入,有条不紊的看下去。

具体来说,当你看书的某一部分时,先看这部分的章节名,了解这部分这一章在讲什么,然后再看某一章,我拿“类文件结构”这一章来说,我必须先知道类文件结构都有什么,然后看到有魔数、Class文件版本、常量池等,然后我再去看魔数是什么,Class文件版本在哪里,常量池是什么?再深入下去,常量池有字面量和符号引用,再深入下去,可能你看懂后还想深究,可能你到这里就已经看不下去了。这都没事,我想说的是,此时看不下去的知识,就不要看了,略过看下一节,我们先把最表面的那一层看完,了解,再去深入到某个点。

这本书的知识就像是一个多叉树,我们先把上面的那层看完再步步去深入到下一层,我觉得这样阅读起来比较轻松,不至于读到难处还要硬读下去。

最后文章结束,点个好看吧!你的每一个好看,赞赏都是对我写作的鼓励和动力。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员乔戈里 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档