JVM面试题

img

内存模型:各个部分的作用,保存哪儿些数据

类加载:双亲委派加载机制,常用加载器分别加载哪儿种类型的类

GC:分带回收的思想依据

性能调优:JVM工具,性能分析工具

执行模式:解释模式,编译模式,混合模式等

编译器优化:javac的变异过程

JVM内存模型

Java 运行时数据区域(JDK1.8 )

线程私有:栈,本地方法栈,程序计数器

1
2
3
4
5
6
7
8
9
10
11
12

又称方法栈,线程私有的,线程执行方法是都会创建一个栈帧,
用来存储局部变量表、操作栈、动态链接、方法出口等信息。
调用方法时执行入栈,方法返回时执行出栈

本地方法栈
与栈类似,也是用来保存执行方法的信息,
执行Java方法是使用占,执行Native方法时是使用本地方法栈

程序计数器
保存当前线程执行的字节码位置,每个线程工作时都有独立的计数器,
值为执行Java方法服务,执行Native方法时,程序计数器为空

线程共享:堆,方法区

1
2
3
4
5
6
7
8
9
10
11

JVM内存管理最大的一块,堆被线程共享,目的是存放对象的实例,几乎所有对象的实例都会放在这里。
当堆没有可用空间时,会抛出OOM异常(Out of Menory内存溢出),根据对象的存活周期不同,
JVM把对象进行分代管理,由垃圾回收器进行垃圾的回收管理
新生代内存(Young Generation)
老生代(Old Generation)
永久代(Permanent Generation)、1.8版本:元空间

方法区
又称非堆区,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器优化后的代码等数据
1.7的永久代和1.8的源空间都是方法区的一种实现

类的加载和卸载

image-20240606101850630
1
2
3
4
5
6
7
8
9
加载:通过类的全限定名,查找此类的字节码文件,利用字节码文件创建Class对象

链接:分为三个阶段
验证:确保Class文件符合当前虚拟机的要求,不会危害到虚拟机自身安全
准备:进行内存分配,为static修饰的类变量分配内存,并设置初始值(0或null),
不包含final修饰的静态变量,因为final变量在编译时就分配好了
解析:将常量池中的符号引用替换为直接引用的过程,直接引用为直接指向目标的指针或者相对偏移量等
初始化:主要完成静态块执行以及静态变量的复制,先初始化父类,再初始化当前类。
初始化是懒惰的,只有对类主动使用的时候才会初始化

加载机制:双亲委派机制

1
2
3
4
加载机制:双亲委派模式
当一个类加载器收到类加载请求时,它首先会将这个请求委托给父类加载器去处理。
如果父类加载器无法加载该类,则该类加载器才会自己去加载这个类。
优点:避免类的重复加载,避免Java的核心API被篡改

卸载过程

1
2
类卸载的实现依赖于JVM的垃圾回收机制。当一个类不再被引用时
JVM可能会通过垃圾回收机制将该类的实例回收

对象的创建过程

1
2
3
4
5
6
7
8
9
Java对象的创建过程可以概括为以下几个步骤

类加载:JVM会先检查类是否已经被加载了,如果没有则通过类加载器加载类的class文件,并将类的信息存储到方法区中
内存分配:当类被加载后,JVM会为该类的对象分配内存,根据Java对象的特点,
内存大小是在编译时就已经确定的,因此内存分配可以通过一些简单的算法来实现,例如指针碰撞和空闲列表等
初始化:内存分配完成后,JVM会对对象进行默认初始化,即将对象的成员变量赋上默认值。
基本类型的默认值是0或false,引用类型的默认值是null
构造函数:默认初始化后,JVM会调用该对象的构造函数,进行对象的属性初始化和一些其他操作
返回地址:构造函数执行完毕后,JVM会将对象的引用返回给调用者,此时对象创建过程完毕

JVM中的垃圾回收机制,大致说一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GC是JVM的垃圾回收机制
首先GC有多种算法:
标记清除:遍历整个堆,清除所有未标记的对象,将其内存空间释放。
标记压缩:将所有存活的对象压缩到堆的一端,保持连续的内存空间,清除端释放未使用的空间。
复制算法:将堆内存分成两部分,活动对象从一个区域复制到另一个区域,不活动的对象直接丢弃
(新生代)
堆内存区域划分:
新生代,老年代,元空间
GC的过程:
minor GC:年轻代满的时候发生,主要复制算法
Full GC:老年代空间不够用的时候

垃圾收集器
JVM 提供了多种垃圾收集器,不同收集器适用于不同的应用场景:

Serial 收集器:适用于单线程环境,简单高效。
Parallel 收集器:适用于多线程环境,采用并行的方式进行垃圾回收。
CMS(Concurrent Mark-Sweep)收集器:适用于低停顿时间的应用,主要用于老年代的垃圾回收。
G1(Garbage First)收集器:适用于大内存和高吞吐量的应用,采用分区算法,能够并发和并行回收内存。

有看过GC日志吗

1
2
3
4
5
没看过
调用System.gc()方法后
在IDEA中的application配置那里
输入一个什么命令去查看
-Xlog:gc*:file=<path-to-log-file>:time,uptime:filecount=10,filesize=10M

如何判断一个对象是垃圾

1
2
3
1.没有被引用的指向时候
2,无法通过引用链到达的时候
3,没有重写finalize方法