JVM-内存结构

1. 程序计数器(PC Counter Register)
定义
- 一般是机器的寄存器
作用
- 记录下一条JVM指令指定的地址
特点
- 线程私有
- 不会存在内存溢出
2. 虚拟机栈(JVM Stacks)
定义
- 栈:先进后出的存储结构
- 每个线程运行时所需要的内存空间,成为虚拟机栈
栈帧
- 每个栈由多个栈帧(Frame)组成
- 栈帧对应每个方法运行时需要的内存
- 每个线程只能有一个活动栈帧,对应当前正在执行的那个方法
思考1:垃圾回收是否涉及到栈内存?
答:不涉及。在调用结束后所有栈帧都会被弹出栈(自动出栈),并不需要垃圾回收。
思考2:栈内存的分配越大越好吗?
答:物理内存的大小一定,如果栈的内存分配过大,那么运行线程的数量就会变小。
思考3:方法内的局部变量是否线程安全?
答:如果方法内局部变量是没有逃离方法的作用范围则是安全的;如果局部变量引用了对象,并逃离了方法的作用范围则是不安全的。
栈的内存溢出
原因
- 栈帧过多
- 栈帧过大(不常见)
3. 本地方法栈(Native Method Stacks)
作用
- 为本地方法的运行提供运行空间
4. 堆(Heap)
定义
- Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建
- 通过new关键字创建对象都会使用堆内存
特点
- 线程共享,堆中的对象需要考虑线程安全问题
- 有垃圾回收机制
堆的内存溢出
- 大量对象强引用无法回收导致溢出
特殊情况:垃圾回收后内存占用仍然很高
排查手段:堆转储
5. 方法区(Method Area)

定义
- 方法区与java堆一样,是各个线程共享的内存区域
- 方法区在jvm启动的时候被创建
方法区内存溢出
- 1.8以前是永久代溢出
- 1.8以后是元空间溢出
运行时常量池
- 常量池:一张表。虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
- 运行时常量池:常量池是*.class文件中的,当该类被加载,它的常量池信息就会被放入运行时常量池,并将里面的符号地址改为真实地址。
浙公网安备 33010602011771号