JAVA编程【JVM编程】
1. JVM 体系结构
JVM 主要包括以下几个核心部分:
类加载器(ClassLoader)
运行时数据区(Runtime Data Area)
执行引擎(Execution Engine)
本地方法接口(Native Interface)
JVM 运行流程如下:
Java 源码 → 字节码(.class 文件)
类加载器 加载字节码到 JVM
字节码校验 确保字节码合法
解释器 & JIT 编译器 执行字节码
垃圾回收 释放无用对象
2. 类加载机制
类加载是指 JVM 将 .class 文件加载到内存,并将其转换为 Class 对象。
类加载过程
JVM 采用 双亲委派模型 进行类加载,过程如下:
加载(Loading):从磁盘或网络读取 .class 文件
验证(Verification):检查 .class 文件的格式与安全性
准备(Preparation):分配静态变量内存
解析(Resolution):将符号引用转换为直接引用
初始化(Initialization):执行静态代码块
代码示例
自定义一个类加载器:
import java.io.*;
public class MyClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] data = loadClassData(name);
return defineClass(name, data, 0, data.length);
}
private byte[] loadClassData(String name) {
try {
File file = new File(name.replace(".", "/") + ".class");
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b;
while ((b = fis.read()) != -1) {
baos.write(b);
}
fis.close();
return baos.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws Exception {
MyClassLoader loader = new MyClassLoader();
Class<?> clazz = loader.loadClass("com.example.MyClass");
System.out.println("Class loaded: " + clazz.getName());
}
}
此代码实现了一个自定义类加载器,手动读取 .class 文件并加载。
3. 运行时数据区
JVM 运行时数据区包括:
方法区(Method Area)
堆(Heap)
虚拟机栈(JVM Stack)
本地方法栈(Native Method Stack)
程序计数器(PC Register)
内存分区示例
public class MemoryTest {
static int staticVar; // 方法区
int instanceVar; // 堆
void method() {
int localVar = 10; // JVM 栈
}
}
staticVar 存在 方法区
instanceVar 存在 堆
localVar 存在 JVM 栈
4. JVM 执行引擎
JVM 主要有两种执行方式:
解释执行(Interpreter):逐行执行字节码,速度较慢
JIT(Just-In-Time 编译器):热点代码编译成机器码,提高性能
JIT 代码优化
JIT 会优化热点代码,例如:
public class JITTest {
public static void main(String[] args) {
long start = System.nanoTime();
for (int i = 0; i < 1_000_000; i++) {
Math.pow(i, 2); // 热点代码
}
long end = System.nanoTime();
System.out.println("Execution Time: " + (end - start) / 1_000_000 + "ms");
}
}
JVM 会对 Math.pow(i, 2) 进行优化,提高执行效率。
5. 垃圾回收(GC)
垃圾回收用于回收无用对象,JVM 主要有以下几种垃圾回收器:
Serial GC(单线程)
Parallel GC(多线程)
CMS GC(低停顿)
G1 GC(大内存优化)
ZGC / Shenandoah GC(超低延迟)
对象生命周期
JVM 采用 GC Roots 可达性分析:
public class GCTest {
private static GCTest instance;
public static void main(String[] args) {
instance = new GCTest();
instance = null; // 失去引用,等待 GC
System.gc(); // 手动触发 GC
}
@Override
protected void finalize() throws Throwable {
System.out.println("GC is running!");
}
}
运行时可能会看到 GC is running!,表示对象被回收。
6. 逃逸分析与栈上分配
JVM 可能会优化对象分配,使其在栈上分配,减少 GC 负担。
代码示例
public class EscapeAnalysis {
static class MyObject {
int value;
}
public static void main(String[] args) {
long start = System.nanoTime();
for (int i = 0; i < 1_000_000; i++) {
MyObject obj = new MyObject(); // 可能分配到栈上
obj.value = 42;
}
long end = System.nanoTime();
System.out.println("Execution Time: " + (end - start) / 1_000_000 + "ms");
}
}
如果 JIT 认为对象未逃逸,可能会在栈上分配,而非堆上。
7. JVM 调优
JVM 提供多种参数进行调优,如:
-Xmx512m:最大堆大小 512MB
-Xms512m:初始堆大小 512MB
-XX:+UseG1GC:启用 G1 GC
-XX:MaxGCPauseMillis=200:最大 GC 停顿时间 200ms
JVM 监控工具
可以使用以下工具监控 JVM:
jps:列出 Java 进程
jstat:监控 GC
jmap:查看内存分配
jstack:线程栈分析
VisualVM:可视化监控 JVM