文章目录
我们在接触这一专题时,应该是从之前所描述的学习思维方式展开探索与研究,我们先以这个技术点是什么到怎么使用、优化等,接下来就对这一个专题以下面四个方面进行总体的总结
一、JVM类加载机制
由上图可知:在加载一个类时,首先是先加载资源到内存中,其次就对加载的资源进行文件格式和内容的校验与验证,接下来就对静态变量进行默认值的赋值,之后就到解析阶段,这个阶段会将符号引用转变为直接引用,直接引用中分为静态连接和动态连接,最后就是初始化,对静态变量进行赋值,以及执行静态代码块
二、JVM内存模型(图解)
三、JVM对象创建与内存分配剖析(图解)
四、垃圾回收算法与垃圾回收器(图解)
五、常见面试题
5.1、GC如何判断对象可以被回收
参考答案:GC判断对象是否为垃圾主要是同个两种方式,分别为:引用计数法、可达性分析,引用计数=>内部会维护一个对象被引用的次数,凡被引用后,这个值会+1,取消引用-1,直到这个数为0时,说明这个对象没有被引用了,属于垃圾对象,可达性分析=>以GC Roots为起始扫描点,依次往下扫描,凡是没有被GC Roots标记还被引用的,说明这些对象属于垃圾对象,可以被回收
5.2、Java类加载
参考答案:Java的类加载主要分为以下几步:首先是先从磁盘中加载对象资源到内存中,其次是对加载的资源进行校验,验证其文件格式与内容的正确性,如果没问题就会到达准备阶段,这个阶段会对类中的静态变量进行默认值赋值,完成之后,会进入解析阶段,这个阶段会将符号引用转换为直接引用,最后就是对相关静态变量进行初始化操作,对象加载完成,如下图:
5.3、Java类加载器
参考答案:Java中的类加载器主要分为四种,分别是:BootStrapClassLoader、ExtClassLoader、AppClassLoader和自定义加载类,在类加载时,会以双亲委派机制进行类资源加载(可自定义类加载器打破双亲委派),各个类加载的职责我们可以看下图:
5.4、JVM内存模型
参考答案:JVM内存中主要分为三个区域,分别为:类装载子系统、运行时数据区、字节码执行引擎,类装载子系统=>其实就是对类资源进行加载的,字节码执行引擎=>对编译后的字节码文件进行运行;而运行时数据区主要分为:堆、栈、本地方法栈、方法区和程序计数器,堆主要是存放创建出来的对象信息,栈会存放局部变量、方法出口、动态连接、操作数栈,本地方法栈是用来存放被Native修饰的资源信息,方法区,会存在一些常量池、类元信息、静态变量信息,而程序计数器则是配合字节码执行引擎协同操作,会记录每次字节码文件运行到的位置信息,这样子做主要是更好的支持并发,具体如下图:
5.5、JVM垃圾回收器
参考答案:JVM的垃圾回收器,常用的主要有以下几种:Serial回收器、Parallel回收器、ParNew回收器、CMS回收器以及G1回收器,之所以有这么多的版本的垃圾回收器,主要是站在原垃圾回收器缺陷基础之上做的改善,例如:Serial回收器是一种单线程且STW进行回收垃圾的一种机制,而Parallel回收器就是基于Serial做了改善,改善点在于提高了吞吐量,利用多线程进行垃圾回收,但也会STW,CMS和G1则是站在用户体验的角度进行改善的,具体过程和模型图我们可以看上面第一个章节的垃圾回收器图
5.6、垃圾回收算法
参考答案:垃圾回收算法,主要包含了:标记—复制、标记—清除、标记—整理,具体的模型图我们可以看上面第一个章节的垃圾回收算法图
5.7、JVM中那些可以作为GC Root
参考答案:线程栈中本地变量、静态变量、本地方法栈的变量都可以作为GC Roots
5.8、JVM中那些是线程共享区
参考答案:JVM中主要有两个区域是线程共享区,分别是:堆、方法区
5.9、对象在JVM中历经的过程
参考答案:我们从new 一个对象开始:首先,我们会先判断当前类是否被加载过,如果被加载国,就进行内存分配,如果没被加载过,就需要先加载对象,再进行内存分配;内存分配=>先分析当前创建的对象是否是逃逸对象,不是逃逸对象,对象分配在栈中,是逃逸对象=>大对象判断,如果是大对象,直接进到老年代,反之就以TLAB或CAS方式获取内存Eden区存放对象,在GC过程中,如果当前对象代年龄到达设定/默认15进入老年代的值后,对象移动到老年代
5.10、说说双亲委派模型
参考答案:在java中,类加载主要分为:自定义类加载器、AppClassLoader、ExtClassLoader、BootStrapClassLoader 在加载类资源到JVM时,当前类加载器会先判断在已加载过的列表中是否存在,如果不存在,当前的类加载器会委派自己的parent类加载器进行加载,如果父加载类都没有加载到当前类资源,就由当前的类加载器进行加载 设置这个机制一方面是因为考虑到沙箱安全机制,例如java中的一些核心内库中的类,是不允许被随意撰改的,另一方面是为了让类不被重复性加载,父类以及有的类,当前类加载器都不用再加载一次了
5.11、你们项目中如何排查JVM问题
参考答案:我们可以使用JVM参数(Jmap、Jstack、Jstat等)命令进行排查,当然,我们会结合业务场景分析出对象的创建频率,结合分配的内存,评估出YoungGC的频率,进入老年代的对象频率与大小,full GC频率次数等,再结合分配的JVM内存占比做调整,或者结合命令进行分析是否为代码原因,除此之外,我们可以借助第三方分析工具,例:阿里巴巴开源的Arthas工具以及JVM自带的JvisualVM等工具