- 堆。 堆是Java对象的存储区域,任何用new字段分配的Java对象实例和数组,都被分配在堆上,Java堆可使用-Xms -Xmx进行内存控制
- 方法区。它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据,方法区在JDK1.7版本及以前被称为永久代,从JDK1.8永久代被移除。
- 虚拟机栈。虚拟机栈中执行每个方法的时候,都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法返回地址等信息。
- 本地方法栈。与虚拟机栈发挥的作用相似,相比于虚拟机栈为Java方法服务,本地方法栈为虚拟机使用的Native方法服务,执行每个本地方法的时候,都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法返回地址等信息。
- 程序计数器。指示Java虚拟机下一条需要执行的字节码指令。
以上五个区域是Java虚拟机内存划分情况,其中方法区和堆被JVM中多个线程共享,字符串常量池和静态变量在JDK1.7之后被放到堆区,供类对象之间共享,虚拟机栈,本地方法栈,pc寄存器是每个线程独立拥有的,不会与其他线程共享。
所以Java在通过new创建一个类对象实例的时候,一方面会在虚拟机栈中创建一个该对象的引用,另一方面会在堆上创建类对象的实例,然后将对象引用指向该对象的实例。对象引用存放在每一个方法对应的栈帧中。
方法区存储:类型信息,运行时常量池,静态变量,JIT代码缓存,域信息,方法信息
运行时常量池是方法区的一部分,常量池表是class文件的一部分,用户存放编译期生成的各种字面量与符号引用。
字节码文件中的常量池经过类加载器加载到方法区后,对应的结构就称为运行时常量池。
执行过程:
方法区保存代码的执行指令,方法的描述
JDK7将静态变量和字符串常量池从方法区移到堆区,但是使用的还是JVM虚拟内存 。
JDK8以后方法区独立出来,使用的是本地内存。
运行时数据区:
对象的内存布局:
句柄访问
直接引用