前言
共13题
JVM的主要组成部分有哪些?
- 类加载器:负责将字节码文件加载到内存中;
- 运行时数据区:用于保存
java程序运行过程中需要用到的数据和相关信息; - 执行引擎:特定的命令解析器执行引擎将字节码翻译成底层系统指令;
- 本地库接口:被执行引擎调用参与字节码的翻译。
运行时数据区的组成部分有哪些?
运行时数据区由五部分构成:堆、方法区、栈、本地方法栈、程序计数器。
- 堆:存放对象;
- 方法区:存储字节码文件、常量、静态变量、运行时常量池;
- 栈:是程序方法运行的主要区域,栈里面存的是栈帧;
- 本地方法栈:与栈功能相同,但他执行的是本地方法;
- 程序计数器:用于记录正在执行的字节码指令的地址,是线程的私有内存,不会产生内存溢出。
堆和栈的区别是什么?
- 栈内存一般会用来存储局部变量和方法调用,但堆内存是用来存储
Java对象和数组的; - 堆会
GC垃圾回收,而栈不会; - 栈内存是线程私有的,而堆内存是线程共有的。
JVM的类加载器有哪些?
类加载器的主要作用是将字节码文件加载到内存中,主要划分为四种类加载器:
- 启动类加载器(
BootStrap ClassLoader):负责加载JRE\lib目录中的类; - 扩展类加载器(
ExtClassLoader):负责加载JRE\lib\ext目录中的类; - 应用类加载器(
AppClassLoader):负责加载用户路径(ClassPath)上的类; - 自定义类加载器:自定义类继承
ClassLoader,实现自定义类加载规则。
什么是双亲委派模型?
双亲委派模型是Java中的一种类加载机制。类加载器之间形成了一种层次继承关系,加载时先交给其父类完成,完成不了再尝试执行。在实际执行过程中,会按照自定义类加载器-->应用类加载器-->扩展类加载器-->启动类加载器的顺序从后往前开始询问加载。
类加载器的双亲委派模型保障了jdk自带的类不会被覆盖,使用不同的类加载器最终得到的都是同一个对象。
说一下类加载器的执行过程?
类加载器的执行过程包括了5个阶段:加载、验证、准备、解析、初始化。
-
加载:获取字节码文件;
-
验证:验证字节码文件是否符合要求;
-
准备:为类变量分配内存并设置类变量的初始值;
-
解析:将符号引用替换为直接引用;
-
初始化:执行类构造器方法的过程,是类加载的最后一步。
怎么判断对象是否可以被回收?
- 引用计数法:两个对象相互引用始终无法释放
counter,则永远不能GC,现在已经不怎么用了; - 可达性分析算法:
GC Roots(List对象)为空时,下面创建的对象就将被回收。
JVM的垃圾回收算法有哪些?
有四个,分别是:标记清除算法、标记-整理算法、复制算法和分代收集算法。
- 复制算法:空间一分为
2,每次只用其中一半,第一块内存用完,把存货对象复制到另一块内存上,清除剩余可回收对象。简单高效但浪费了一半内存; - 分代收集算法:将堆区划分为新生代老年代(
1:2),新生代分为伊甸区和两个幸存区(8:1:1)。在伊甸区创建对象,回收对象直接删掉,未被回收的放入幸存区,当回收次数过多放入老年代中,在其中在进行清除。
JVM的垃圾回收器都有哪些?
-
整堆回收器:
G1; -
新生代垃圾回收器:一般采用的是复制算法,效率高但是内存利用率低;
-
老年代垃圾回收器:一般采用的是标记-整理的算法进行垃圾回收。
Minor GC(新生代)与Major GC(老年代)分别发生在何时?
- Minor GC:年轻代空间不足时,会触发老年代;
- Major GC:老年代空间不足时,会先尝试触发年轻代,若之后空间还不足,会触发老年代。
哪些情况会触发类加载机制?
- 在遇到
new、putstatic、getstatic、invokestatic字节码指令时,如果类尚未初始化,则需要先触发初始化; - 对类进行反射调用时,如果类还没有初始化,则需要先触发初始化;
- 初始化一个类时,如果其父类还没有初始化,则需要先初始化父类;
- 虚拟机启动时,需要指定一个包含
main()方法的主类,虚拟机会先初始化这个主类。
哪些变量可以作为GC Roots?
-
虚拟机栈中 (栈帧中的本地变量表) 引用的对象;
-
方法区中类静态属性引用的对象;
-
方法区中常量的引用对象;
-
本地方法栈中引用的对象。
介绍一下JVM的空间分配担保机制
JVM的空间分配担保机制是什么
JVM的空间分配担保机制确保了在Minor GC和Major/Full GC之间有足够空间处理对象晋升和分配,它的作用是避免在垃圾收集过程中出现内存不足的情况。
工作原理
- 估算新生代存活对象的大小:在每次
Minor GC前,JVM会估算新生代中存活对象的大小; - 判断老年代的剩余空间:根据估算的存活对象大小,
JVM会判断老年代是否有足够的空间来容纳这些晋升的对象; - 触发Full GC的条件:如果老年代空间不足以容纳新生代中晋升的对象,
JVM会触发一次Full GC。
JDK版本差异
JDK 6之前
担保失败处理:如果老年代最大可用连续空间小于新生代所有对象总空间,虚拟机会检查-XX:HandlePromotionFailure设置。
JDK 7及之后
策略调整:取消了-XX:HandlePromotionFailure选项,每次Minor GC前都会判断老年代剩余最大连续空间是否大于历次Minor GC晋升的平均大小或大于新生代所有对象的大小总和。