1. 什么是JVM?它的作用是什么?
答案 :
JVM(Java Virtual Machine)是Java虚拟机的缩写,它是Java程序运行的执行环境。JVM的作用包括:
- 加载.class文件
- 验证字节码
- 执行字节码
- 提供运行时环境
- 内存管理(垃圾回收)
- 平台无关性("一次编写,到处运行")
2. JVM内存区域如何划分?
答案 :
JVM内存主要分为以下几个区域:
- 程序计数器:线程私有,记录当前线程执行的字节码行号
- 虚拟机栈:线程私有,存储局部变量表、操作数栈、动态链接、方法出口等
- 本地方法栈:为Native方法服务
- 堆:线程共享,存放对象实例和数组,是GC主要区域
- 方法区:线程共享,存储类信息、常量、静态变量、即时编译器编译后的代码等
(JDK8后,方法区的实现从永久代改为元空间)
3. 什么是Java垃圾回收机制?常见的垃圾回收算法有哪些?
答案 :
垃圾回收是JVM自动管理内存的机制,用于回收不再使用的对象所占用的内存空间。
常见垃圾回收算法:
- 标记-清除算法:标记所有需要回收的对象,然后统一回收
- 复制算法:将内存分为两块,每次使用一块,存活对象复制到另一块
- 标记-整理算法:标记后让所有存活对象向一端移动,然后清理边界外内存
- 分代收集算法:根据对象存活周期将堆分为新生代和老年代,分别采用不同算法
4. 什么是类加载机制?类加载的过程是什么?
答案 :
类加载机制是JVM将.class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被JVM直接使用的Java类型的过程。
类加载过程分为5个阶段:
- 加载:查找并加载类的二进制数据
- 验证:确保被加载的类的正确性
- 准备:为类的静态变量分配内存并设置初始值
- 解析:将符号引用转换为直接引用
- 初始化:执行类构造器<clinit>()方法的过程
5. 什么是双亲委派模型?有什么好处?
答案 :
双亲委派模型是JVM类加载的一种工作机制,要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。
工作流程:
- 当前类加载器首先检查是否已加载过该类
- 如果没有,则委托父类加载器加载
- 父类加载器无法完成加载时,子类加载器才会尝试加载
好处:
- 避免类的重复加载
- 防止核心API被篡改(安全考虑)
- 保证Java核心库的类型安全
6. JVM有哪些常见的性能调优参数?
答案 :
常见JVM调优参数:
-
堆内存设置 :
- -Xms:初始堆大小
- -Xmx:最大堆大小
-
新生代设置 :
- -Xmn:新生代大小
- -XX:SurvivorRatio:Eden和Survivor区比例
-
垃圾回收器选择 :
-
其他 :
- -XX:MaxPermSize:永久代大小(JDK7及之前)
- -XX:MetaspaceSize:元空间初始大小(JDK8+)
- -XX:MaxMetaspaceSize:元空间最大大小(JDK8+)
7. 什么是Java内存模型(JMM)?
答案 :
Java内存模型(Java Memory Model)定义了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取变量的底层细节。
JMM主要特性:
- 原子性:基本数据类型的访问读写是原子性的
- 可见性:一个线程修改了共享变量的值,其他线程能够立即得知
- 有序性:禁止指令重排序优化
JMM通过volatile、synchronized、final等关键字和happens-before原则来保证多线程环境下的正确性。
8. 什么是OOM?常见的OOM有哪些类型?
答案 :
OOM(OutOfMemoryError)是Java中的内存溢出错误,常见类型包括:
- Java堆空间溢出(OutOfMemoryError: Java heap space):对象数量达到堆容量限制
- 永久代/元空间溢出(OutOfMemoryError: PermGen space/Metaspace):类信息过多
- GC开销限制超出(OutOfMemoryError: GC overhead limit exceeded):GC时间过长
- 无法创建新线程(OutOfMemoryError: unable to create new native thread):线程数过多
- 直接内存溢出(OutOfMemoryError: Direct buffer memory):NIO直接内存不足
9. 解释强引用、软引用、弱引用和虚引用的区别
答案:
- 强引用:最常见的引用,只要强引用存在,垃圾回收器永远不会回收被引用的对象
- 软引用(SoftReference):内存不足时会被回收,适合做缓存
- 弱引用(WeakReference):无论内存是否足够,只要GC就会被回收
- 虚引用(PhantomReference):最弱的引用,无法通过它获取对象实例,主要用于跟踪对象被回收的活动
10. 什么是逃逸分析?有什么作用?
答案 :
逃逸分析是一种分析对象作用域的技术,用于分析对象的动态作用域,判断对象是否会被外部方法或线程访问。
作用:
- 栈上分配:如果对象不会逃逸出方法,可以在栈上分配内存,减少GC压力
- 同步消除:如果对象不会逃逸出线程,可以消除对该对象的同步操作
- 标量替换:将对象分解为若干个基本数据类型,直接在栈上分配
11. 常见的垃圾收集器有哪些?各自的特点是什么?
答案:
- Serial收集器:单线程,新生代复制算法,老年代标记-整理算法
- ParNew收集器:Serial的多线程版本,与CMS配合使用
- Parallel Scavenge收集器:吞吐量优先,新生代复制算法,老年代标记-整理算法
- CMS收集器:低延迟,标记-清除算法,有内存碎片问题
- G1收集器:区域化分代式,整体标记-整理,局部复制算法,可预测停顿时间
- ZGC收集器:JDK11引入,低延迟,支持TB级堆内存
- Shenandoah收集器:低延迟,与ZGC竞争
12. 什么是JIT编译器?它是如何工作的?
答案 :
JIT(Just-In-Time)编译器是JVM的一部分,负责将热点代码(频繁执行的代码)编译为本地机器码,以提高执行效率。
工作过程:
- 解释器首先解释执行字节码
- 识别热点代码(方法调用计数器、回边计数器)
- JIT编译器将热点代码编译为本地机器码
- 后续执行直接使用编译后的机器码
JVM中有两种JIT编译器:C1(Client Compiler)和C2(Server Compiler),GraalVM还引入了新的JIT编译器。