JVM简介

56 阅读4分钟

JVM有什么用?

1. 让Java“一次编写,到处运行”

你写了一个Java程序,在Windows上编译后生成的是 .class 文件(叫“字节码”)。 这个字节码不是直接给电脑CPU看的,而是给 JVM 看的。 只要在 Windows、Mac、Linux 等系统上安装对应的 JVM,它就能把字节码翻译成该系统能执行的指令。 所以你的程序不需要重写,换个地方也能跑!

2. 自动管理内存(会自己“打扫卫生”)

你创建的对象(比如 new Person()),都放在内存里。 当对象没用了(比如变量不再引用它),JVM 会自动回收这块内存,这叫“垃圾回收”(GC)。 你不用手动清理,减少出错,也更安全。

3. 提高程序运行速度(越用越快)

JVM 有个“聪明助手”叫 JIT 编译器(Just-In-Time)。 它会把经常运行的代码(热点代码)直接编译成机器码,下次执行就飞快! 就像你反复读一段文章,后来直接背下来了,读得更快。

4. 保证程序安全

JVM 可以限制程序的行为,比如: 不能随意访问硬盘文件 不能直接操作内存地址 特别适合运行网络下载的代码(比如早期的小程序 Applet),防止恶意行为。

5. 支持多任务同时运行(多线程)

JVM 内部对“多线程”有良好支持。 多个任务(比如一边下载文件,一边响应用户点击)可以并行执行,互不干扰。

JVM内存模型

image.png

一句话总结:
JVM 内存模型是 Java 程序运行时的“内存布局”,它把内存分成几个区域,各司其职,管理代码和数据的存储与使用。

就像一间公司有不同的部门(财务、人事、技术),JVM 也把内存划分为多个“区域”,每个区域负责不同的任务。


JVM 主要包含 5 大内存区域

区域作用特点
方法区(Method Area)存放类信息、常量、静态变量、方法代码等所有线程共享
堆(Heap)存放对象实例(new 出来的对象)最大一块,GC 主战场,线程共享
虚拟机栈(Java Stack)每个方法调用时创建栈帧,保存局部变量、参数、返回地址等每个线程私有
本地方法栈(Native Method Stack)类似虚拟机栈,但用于调用 native 方法线程私有
程序计数器(PC Register)记录当前线程执行到哪一行代码最小,线程私有

image.png

详细通俗解释

1. 堆(Heap)—— 对象的“大宿舍”

  • 所有通过 new 创建的对象都住在这里。
  • 是 JVM 中最大的一块内存。
  • 被所有线程共享(大家都能访问同一个对象)。
  • 垃圾回收器(GC)主要工作地:自动清理不再使用的对象。

📌 示例:

Person p = new Person(); // new Person() 这个对象在堆里

2. 方法区(Method Area)—— 类的“档案馆”

  • 存放:
    • 类的名字、字段、方法定义
    • 静态变量(static int count)
    • 常量(比如字符串常量 "hello")
  • 也是所有线程共享的。
  • 在 HotSpot JVM 中:
    • JDK 7 及以前:称为“永久代”(PermGen)
    • JDK 8+:改为“元空间”(Metaspace),使用本地内存
public class Person {
    public static int count = 0; // count 存在方法区
}

3. 虚拟机栈(Java Stack)—— 每个线程的“工作台”

  • 每个线程有自己的栈,用来支持方法调用。
  • 每调用一个方法,就会创建一个“栈帧”(Stack Frame),压入栈中。
  • 栈帧里包含:
    • 局部变量表(如 int a = 10;)
    • 操作数栈
    • 返回地址

特点:

  • 方法执行完,栈帧就弹出,资源自动释放。
  • 如果递归太深,会抛出 StackOverflowError。

4. 程序计数器(PC Register)—— 线程的“书签”

  • 每个线程都有自己的 PC 寄存器。
  • 它记录当前线程正在执行的字节码指令的位置。
  • 就像你看书时夹的书签,知道看到第几页了。

注意:如果执行的是 native 方法,PC 值为 undefined。

5. 本地方法栈(Native Method Stack)—— 调用非 Java 代码的桥梁

  • 当 Java 调用 native 方法(如 Thread.start0())时,使用这个栈。
  • 和虚拟机栈类似,但服务的是底层语言(如 C/C++)。