JVM内存划分
- 虚拟机栈 —
Stack Frame
,存储方法运行时所需的数据 - 程序计数器 —
Program Counter
,记录当前线程所执行的字节码行号 - 本地方法栈 —主要用于执行本地方法,为JVM所调用到的Native即本地方法服务
- 堆 —
Heap
,JVM管理的最大的一块内存空间,存储对象实例 - 方法区—
Method Area
,存储运行时的常量池,已被JVM加载的类信息,常量,静态变量,即时编译器编译后的代码等数据永久代(Permanent Generation)
—从JDK1.8开始,已经废弃了永久代,使用元空间(Meta Space
)- 运行时常量池—方法区的一部分内容,用来存放编译期生成的各种自变量以及符号引用
- 直接内存—
Direct Memory
,由OS管理
1虚拟机栈
虚拟机栈描述的是java方法执行的动态内存模型
1.1栈帧-(Stack Frame)
栈帧是一种用于帮助JVM执行方法调用与方法执行的数据结构,每个方法执行都会创建一个栈帧,伴随着方法从创建到执行完成
栈帧本身是一种数据结构,封装如下信息
- 局部变量表
Local Variables
- 操作数栈
Operand Stack
- 指向当前方法所属的类的运行时常量池的引用
Reference to runtime constant pool
- 方法返回地址
Return Address
- 额外的附加信息
1.2局部变量表
存储编译期可知的各种基本数据类型,引用类型,returnAddress类型
局部变量表的内存空间在编译期完成分配,当进入一个方法时,这个方法需要在帧分配多少内存是固定的,在方法运行期间是不会改变局部变量表的大小
2 程序计数器
- 是一块较小的内存空间,可以看作是当前线程锁执行的字节码的行号指示器
- 程序计数器出于线程独占区
- 此区域是唯一一个在JVM规范没有规定任何
OutOfMemoryError
情况的区域 - 如果线程执行的是Java方法,这个计数器记录的就正在执行的虚拟机字节码指令的地址
- 如果执行的native方法,这只计数器的置为undefined
3 本地方法栈
与虚拟机栈的区别
- 虚拟机栈为执行java方法服务
- 本地方法为虚拟机执行native方法服务
4 堆内存
- 存放对象实例
- 是Java虚拟机管理内存中最大的一块
- 垃圾收集器管理的主要区域
- 现代垃圾收集器都采用了分代收集算法,堆空间也基于这一点进行了响应的划分
- 新生代
- Eden空间
- From Survivor空间
- To Survivor空间
- 老生代
- 新生代
相关JVM参数
-Xms3m
—设置最小堆内存
-Xmx3m
—设置最大堆内存
-XX:+HeapDumpOnOutOfMemoryError
—输出内存溢出相关错误信息
-Xss200k
—虚拟栈大小JVM参数
在堆中,尤其是在新生代中,常规应用进行一次GC一般可回收70%~95%的空间,而方法区的GC效率远小于次
5 方法区
存储运行时的常量池,已被JVM加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
其中类信息包括
- 类的版本
- 字段
- 方法
- 接口
- 在Java虚拟机规范表示可以不要求虚拟机在该区实现GC—原因是GC性价比较低
5.1 方法区的回收内容
当前的商业JVM都有实现方法区的GC,主要回收两部分内容:
- 废弃常量
- 无用类
其中
- 类回收需要满足3个条件
- 该类所有的实例都已被GC,也就是JVM中不存在改Class的任何实例
- 加载该类的ClassLoader已经被回收
- 该类对应的
java.lang.Class
对象没有在任何地方被引用,如不能在任何地方通过反射访问该类的的方法
在大量通过反射,动态代理,CGLib等字节码框架,动态生成JSP以及OSGi这类频繁自定义ClassLoader的场景都需要JVM具备类卸载的支持以保证方法区不会溢出
6 运行时常量池
方法区的一部分
7 直接内存 Direct Memory
与Java NIO
密切相关,JVM通过堆上的DirectByteBuffer
来操作直接内存
例:
public void method(){
Object obj = new Objdect();
}
- 上述代码再运行时生成了2部分的内存区域
obj
这个引用变量,因为是方法内的变量,放到虚拟机栈(Stack)
里面- 真正的
Object
的实例对象,放到堆(Heap)
里面
- 上述的new语句一共消耗了12个bytes,
- JVM规定
- 引用占4个bytes(在虚拟机栈Stack)
- 空对象是8个bytes(在堆内存Heap中)
- JVM规定
- 方法结束后,对应的Stack中的变量马上回收,但是在Heap中的对象要等GC来回收