| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 三天刷完《深入JVM虚拟机 第三版》是什么感觉 -> 正文阅读 |
|
[Java知识库]三天刷完《深入JVM虚拟机 第三版》是什么感觉 |
好久没有写过原创了,这篇是2021的第一篇原创,又开始自己的原创之路了,今天分享一个最近刷完的一本书《深入JVM虚拟机 第三版》,一共花了三天的时间刷完,我相信应该很多人还没看过,毕竟七百多页,坚持看完真不容易,在这里分享一下自己刷完的一些经验,以及怎么去刷这本书。 其实在刷这本书之前其实对于这本书的很多内容都已经学过了,所以再来刷这本书算是知识点的回顾吧,看的也比较快,更有目的性,在此之前对于JVM的学习,我还专门的做了自己的学习和总结了自己的思维导图: 这个思维导图也积累了非常久,大概一年多的时间吧,我还记得我第一看 《深入JVM虚拟机》 的时候,都是蒙蒙的,第一次也是没有看完。 后来因为工作需要零零散散的学了很多关于JVM的知识点,并且把它记录下来,这就成了我最后的这个思维导图,我感觉对于调优方面的话算是比较全的了。 下面我们开始我们的刷书之旅,先来看看这本书的总的目录,一共五大部分,首先第一大部门直接可以略过,是不是贼开心,一秒间就少了一大部分: 这部分内容其实可以不用看的,在《并发编程实战》这本书里面都会有,我下一本就是打算刷《并发编程实战》,大家也可以直接略过,这不又少了一部分。 还有就是第四部分,这部分应该是选看,我个人主要关注的是即时编译器,因为即时编译器还是挺重要的,有些面试也会被问到,其他部分我都是草草的看一下大致的内容,也并不是自己想要的,因为你去看,你也记不住,并且实际中也用不到,至少是现在阶段用不到,面试被问几乎为0。
接下来,我们来看第二部分就是JVM的内存管理,也就是内存模型、运行时数据区的内容,还有就是用于观察JVM内存的监控工具,其实这部分的内存模型应该是很多技术博主,都写过的博文,所以感觉大家看这部分内容应该算是只是的回顾了:
这里要掌握的就是这几个区域的含义,哪些是线程私有的,哪些是线程共有的,哪些会导致OOM异常出现,带着这几个问题去看基本没什么太大问题。 直接内存可能是有些人会比较陌生,直接内存并不是虚拟机的一部分,他是本地内存,按照常理来说他的大小和出现OOM问题之和本地内存有关,你也可以通过 -XX:MaxDirectMemorySize 参数来设置它的大小。 与这部分内存有关系的Java框架之一就是Netty,因为Netty的底层使用的是NIO,是给予通道和缓冲区的IO方式,它通过一个DirectByteBuffer 对象来对这块内存进行操作。
对象是怎么分配内存的?怎么避免多线程时内存资源的争抢?在哪里分配内存(堆、栈)?这块的内容基本就是围绕这几个问题讲解。 对象创建出来后并且分配内存后,对象在内存中又是怎么布局的,我相信大家可能之前看过一篇文章说:XX大厂XX面,面试官:你知道Java中对象有多大吗? 一个对象分为几部分(对象头(Header)、实例 最后就是对象的访问:句柄、直接指针。这两种方式有什么区别?分别有什么缺点和优点?搞懂这几个问题,就算是掌握了90%以上了。 以上的内容都是偏理论的,理论总是为实战服务的,后面的OOM异常就是偏实战的,前面介绍的几个运行时数据区除了程序计数器不会出现OOM,其他的部分都有可能会出现OOM。 而除了程序计数器不用考虑外(以下调优可以直接忽略程序计数器),在JVM中Java堆是调优的最重要也是最难的一部分,基本上JVM中的调优参数复杂的都是偏向于Java堆,对于除了Java堆其它的运行时数据期出现OOM的解决办法是啥?最有效的办法就是适当的增大内存。 而Java堆的调优就不是偏偏的增大内存那么简单,有时Java堆增大堆存,反而会适得其反,因为虽然内存大了,可能新生代的可分配的对象数量也增多了,但是单次GC的回收时间也变得长了,这样会导致系统卡顿时间增长。 对于那些用户交互时间频繁,要求响应时间短的应用,就不能接受了,可能老板就是找你:兔崽子,上次是不是你调优的JVM,现在卡顿的时间又更长了,用户每天投诉,你今晚必须搞定,不然明天别来了。 所以Java堆也是调优一块的重点和难点,首先在这部分先了解和熟悉分别各个区域出现OOM异常后,打印出来的堆栈信息一般都是怎么样的,比如堆OOM就如下所示:
在堆栈信息中都能看到“Java heap space”这个名称,还有就是那些场景会导致这几部分的内存溢出呢?这个也是比较重要的,比如递归深度过大、方法过长,程序中出现大对象,内存泄露,线程池数量设置不合理,过度使用代理、常量数量过多过大、Class信息过多等都会分别导致那些区域OOM呢? 其实对于调优之前还有要说清楚的就是,可能百分之七八十的问题,都可以通过代码优化来解决,比如方法过长,方法拆一下不就行了嘛,出现大对象,创建小一点的对象不就行了嘛。 但是,有时候有些问题你就有可能忽略调,比如大对象(有可能是同一时间内多对象),尽管你在开发中都非常的小心翼翼了,对象已经控制的非常小了,在生产中流量一上来的就出现OOM了,只有生产的流量才有可能验证你的某一些被忽略的功能。 举个例子,在PC端都有会有一个导出的功能,有当前页的导出以及全部的导出,特别是这个全部的导出,数据量小的时候就没啥问题,要是数据量一大,以及流量一上来,那同一时间内创建的Excell对象就非常的多,一不小心就出现OOM了。 再比如,面向用户的C端首页,一般C端首页为了提高用户的体验度都会进行缓存,那么当缓存的数量过大,同一时间从缓存里面获取的对象就会过多或者对象过大的问题。 对于这部分的内容,我之前的思维导图,也是做了非常详细的总结,以下只是其中的一部分,大家可以作为参看,对于大家思考也是非常重要的。 我们重点来关注一下垃圾收集器,随着jdk的不断发展,版本的不断升级,服务器由单核演变多核,内存的变大,垃圾收集器也变得越来越智能,每种垃圾收集器都有自己的适用场景。 这几种垃圾收集器比较常见的搭配如下图所示:
每种垃圾收集器都有自己的使用场景,优点和缺点,所以再看这部分的内容就带着这几个问题去看就行了:
把这几个问题搞懂基本也就摸透了,比如在适用于单核时代的Serial收集器它的主要问题一个就是造成了STW的问题,以及单线程的垃圾回收效率问题,但是对于单核的服务器,它无疑是最佳的选择。 以及后面发展到多线程时代PS和PO,由原来的的单线程收集,现在编程了多线程收集,肯定是比原来垃圾收集的时间效率提高了,但是对于多线程又有设置回收垃圾的线程数是多少,书中都有给出建议的。 后面比较经典的就是CMS,CMS有分为四个阶段初始标记、并发标记、重新标记、并发清理。 对于这些问题的答案相应的部分都说的明明白白的,大家可以仔细研究,后面一个就是G1,前面经典的垃圾收集器都是给予分代模型的。 但是,分代模型又是有自己存在的问题,比如经典的分代垃圾收集器相对应的都是整个堆大小的收集,随着服务器性能的提高,服务器的内存也会越来越大,现在动不动就好几个g或者10几个g的大小,那么这样就会导致单次的垃圾收集时间越来越长,停顿的时间也会相应变长,因为STW现在位置是没办法消除的,只能尽可能的减少。 这也就是后面出现了G1,G1弱化了分代理论模型的垃圾收集,改为真个堆划分为一个一个Region,每个Region都不是固定的哪一个代(新生代、老年代),在发生垃圾回收的时候,G1会对每一个Region的回收耗时做记录,这样就可以统计出要回收的成本,所以G1做到了在用户可接受的停顿时间(STW,一般100-300毫秒)的时间范围进行垃圾收集,不用针对整个堆。 以上就是G1来带来的优势,解决传统的垃圾收集器出现的问题,但是G1本身自己还存在问题,比如会产生浮动垃圾,这个是G1至今未解决的问题,还有G1在极端的情况下可能会造成系统假死的现象。 这也是为什么现在垃圾默认的垃圾收集器还不是G1的一些原因,这些问题都可以在文中找到,这部分的内容一定要细细的品,仔细的琢磨。 其中还有两款面向低延时的收集器是,我们现在阶段暂时用不到,你去看一下它使用的场景就知道了,以及适用于Java堆大小,所以大家可以忽略:
熟悉和精通上面集中垃圾收集的原理后,下面就是实战了,我这边我在我的思维导图里面总解决常用的JVM调优参数: 接下来就是实战部分包括一些场景和原则:对象内存的分配原则、大对象、长期存活的对象、对象年龄、空间的分配担保,这部分的内容也一定要细细的品,肯定是精华。
还有就是比较原始的排查方法,使用linux命令,例如jps、jstat、jinfo、jmap、jstack,这部分在书上有详细的讲解:
假如你都能够使用上面的原始命令和分析工具对以上问题能够自己独立分析,那你就是无敌了,调优高手啊,老板还不得花重金请你。 大家也可以参考一下我自己的思维导图,方式都差不多,大差不差,但还不完整,因为有些还没整理: 第五章部分,我感觉大家可以略过,可能是大佬的经历和我们不一样,实战的场景,很少遇见过,我是直接跳过的。 到这里要是以上的内容都吃透的话,后面的内容基本就是纯理论的东西,对你来说也不难: 第三部分就直接看虚拟机的加载机制,包括类加载过程、经典的三层加载器、自定义类加载器、双亲委派等,这些就是这部分的重点。 好了到这里基本我个人需要的内容已经吸收的差不多了,我就是带着调优的目的去看这本书的,这里澄清一下不是说不看的内容说写的不好,不是这样的,只是我们是带着目的去学习的,书里的内容很详细,但是并不是所有的东西都是我们需要的,至少是现阶段,我只是帮大家把我们需要的内容提取出来,然后分享自己刷这本书的目的以及经验。 限于篇幅,后面会继续分享自己对于JVM虚拟机的深入的学习和了解,有需要 《深入JVM虚拟机第三版》 电子书可以添加我微信:abc730500468,那本书重点的部分我都打上了标记,便于你们刷,以及刷的过程有技术可以相互讨论,好了我是黎杜,我们下一期见。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/17 20:23:24- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |