JVM的内存划分

发布于:2025-05-21 ⋅ 阅读:(17) ⋅ 点赞:(0)

JVM(Java Virtual Machine)的内存划分主要包括以下几个运行时数据区域:

1. 程序计数器(Program Counter Register)

  • 作用:当前线程执行的字节码行号指示器。
  • 特点
    • 线程私有(每个线程独立拥有)。
    • 执行Java方法时记录字节码指令地址,执行Native方法时为空(Undefined)。
    • 唯一不会抛出OutOfMemoryError的区域。

2. 虚拟机栈(VM Stack)

  • 作用:存储方法执行的栈帧(局部变量表、操作数栈、动态链接、方法出口等)。
  • 特点
    • 线程私有,生命周期与线程相同。
    • 每个方法执行时创建栈帧,方法结束后栈帧销毁。
  • 异常
    • 栈深度超过限制时抛出StackOverflowError(如递归过深)。
    • 动态扩展失败时抛出OutOfMemoryError(如-Xss参数设置过小)。

3. 本地方法栈(Native Method Stack)

  • 作用:与虚拟机栈类似,但为Native方法服务(如Object.wait()等)。
  • 特点
    • 线程私有。
    • 不同JVM实现可能不同(如HotSpot将其与虚拟机栈合并)。
  • 异常:同虚拟机栈,可能抛出StackOverflowErrorOutOfMemoryError

4. 堆(Heap)

  • 作用:存储对象实例和数组,是垃圾回收的主要区域。
  • 特点
    • 线程共享,所有对象实例和数组都在此分配。
    • 可通过-Xms-Xmx参数调整大小。
  • 分区(以HotSpot为例)
    • 新生代(Young Generation)
      • Eden区:新对象初始分配的区域。
      • Survivor区(S0、S1):Eden区满时,存活对象被移至Survivor区。
    • 老年代(Old Generation):长期存活的对象进入老年代(如多次GC后仍存活的对象)。
    • 永久代/元空间(PermGen/Metaspace)
      • 永久代(Java 7及以前):存储类信息、常量池等,固定大小,可能导致OutOfMemoryError: PermGen space
      • 元空间(Java 8+):使用本地内存,默认无上限,避免了永久代的内存溢出问题。
  • 异常:堆内存不足时抛出OutOfMemoryError: Java heap space

5. 方法区(Method Area)

  • 作用:存储已被虚拟机加载的类信息、常量、静态变量等。
  • 特点
    • 线程共享。
    • 逻辑上属于堆的一部分,但HotSpot在Java 8后用元空间(本地内存)实现。
  • 运行时常量池(Runtime Constant Pool)
    • 方法区的一部分,存储编译期生成的常量和符号引用。
    • 支持运行时动态生成常量(如String.intern())。
  • 异常:元空间不足时抛出OutOfMemoryError: Metaspace

6. 直接内存(Direct Memory)

  • 作用:不属于JVM运行时数据区,使用UnsafeNIOByteBuffer.allocateDirect()直接分配堆外内存。
  • 特点
    • 不受堆大小限制,但受物理内存和-XX:MaxDirectMemorySize参数限制。
  • 异常:内存不足时抛出OutOfMemoryError

总结

区域 线程私有 存储内容 常见异常
程序计数器 字节码行号
虚拟机栈 方法栈帧(局部变量、操作数栈等) StackOverflowError
本地方法栈 Native方法栈帧 StackOverflowError
对象实例、数组 OutOfMemoryError: Heap Space
方法区(元空间) 类信息、常量、静态变量 OutOfMemoryError: Metaspace
直接内存 堆外内存(NIO直接缓冲区) OutOfMemoryError

补充

  • 垃圾回收(GC):主要针对堆和方法区(元空间)。
  • JVM参数示例
    • -Xms2048m:堆初始大小2GB。
    • -Xmx2048m:堆最大大小2GB。
    • -XX:MetaspaceSize=256m:元空间初始大小256MB。
    • -XX:MaxDirectMemorySize=512m:直接内存最大512MB。

网站公告

今日签到

点亮在社区的每一天
去签到