jvm内存结构
线程私有或共享划分jvm内存
线程私有的区域:
程序计数器(program counter register)
程序计数器是线程私有的,是用来记录每个线程下一步需要执行哪一条指令的。
在jvm中这里是没有任何内存问题的,是不会出现内存错误的区域
虚拟机栈(vm stack)
java程序运行时,每调用一个方法时,都会在这个区域产生一个栈帧。 这个栈帧用于存储:局部变量表、操作数栈、动态链接、方法出口信息等。 每个方法从调用开始到结束的过程,都对应这Vm Stack中的入栈出栈的过程! 在单线程情况下肯定是StackOverFlowError,多线程下OutOfMemoryError
1)局部变量表:是一组变量值的存储空间,存储着参数和方法内部定义的局部变量。
2)操作数栈:虚拟机把操作数栈作为它的工作区,程序中的所有计算过程都是在借助于操作数栈来完成的,大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。
3)动态链接:每个栈帧都包含一个指向运行时常量池(在方法区中)中该栈帧所属方法的引用, 持有这个引用是为了支持方法调用过程中的动态连接。
4)方法出口:当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址
本地方法栈(native method satck)
该区域与虚拟机栈所发挥的作用非常相似,只是虚拟机栈为虚拟机执行Java方法服务, 而本地方法栈则为使用到的本地操作系统(Native)方法服务。
线程共享区域
堆(heap)
堆是jvm管理最大的一块内存,用于存储生成的对象。是线程共享的。也是gc管理的区域。 堆中有一块区域,用于存储:类信息,类变量,常量等
Meta-Area 这块区域也是线程共享的区域,它主要存储jvm加载类的类信息,类变量,常量(这个在meta-area的常量区),即时编译器编译后的代码等数据。
运行时常量区
这个区域是Meta-Area的一部分,用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
public void test() {
Object obj = new Object();
}
对于这段代码会涉及Vm Stack、Java Heap、Meta-Area三个最重要的内存区域。
在调用test()方法使用,创建栈帧,obj会存放在局部变量表中,new Object(),我们前面说过我们大部分的对象都会存储在Java Heap这个区域, 所以,Java Heap存储了这个实例对象!那么你会很好奇,Meta-Area为啥会涉及到呢?
我们知道Meta-Area存储了类的信息,类变量常量等等东西!因为我们实例化Object对应的时候, 要用到Object这个类的信息,所以它会访问Meta-Area的Object.class这个Class对象来获得一些实例化对象需要的东西。