jvm内存结构
先上图
由上图可知,jvm内存结构包含方法区、堆、虚拟机栈、程序计数器、本地方法栈
1. 程序计数器
用来记录线程执行到字节码的哪个位置,是线程私有的
2. 本地方法栈
由jvm本身的native方法使用,存储的是native方法之间的调用关系
3. 堆
堆是jvm中内存最大的一块空间,几乎所有的对象或者数组都是在堆上分配内存的,在分代收集理论中,堆可以分为新生代、老年代。新生代又可以分为Eden区(伊甸园)和Survivor区(存活区),Survivor区又可以分为From Survivor区(s0)和To Survivor区(s1)
4. 方法区
方法区是线程共享的,它用于存储已被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等
4.1 类信息:
类名、父类名、接口名列表
4.2 JIT编译后的代码:
是热点代码编译后的本地机器代码。
这里顺便说下jvm解释器,jvm解释器是jvm架构中负责执行java字节码的一个组件,解释器的工作原理是边解释边执行,每遇到一条字节码指令就把它解释成对应的本地机器语言,并执行对应的操作,但是这样的执行效率较低,所以就有了JIT,它会监控热点代码,并把这些代码动态编译成本地机器代码,提高执行效率
4.3 常量:
就是运行时常量池,在说运行时常量池之前要先说下字节码文件中的常量池,通过jclasslib插件可以看到下面的信息,常量池中包含字面量和符号引用,字节码文件中的常量池在类被加载后存放到方法区就是运行时常量池,在程序运行的时候这里的符号引用会被替换为真实地址
字面量:字符串或者是数值等等
符号引用:包括类引用、字段引用、方法引用
4.4 方法区在 JDK6、7、8中的演进细节
jdk1.6 用永久代实现方法区,静态变量存放在永久代上
jdk1.7 逐步进行去永久代操作,字符串常量池和静态变量改为保存在堆里
jdk1.8 改为元空间,同时元空间是保存在本地内存里面,不是在虚拟机虚拟内存里面了
5. 虚拟机栈
虚拟机栈是线程私有的内存空间,每个线程创建时,会在虚拟机栈中申请一个线程栈,每一次方法调用都会往栈中压入一个栈帧,如下图
栈帧中包含:
局部变量表:函数的局部变量
操作数栈:保存计算过程中的结果,即临时变量
动态链接:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接
静态链接:在类加载或者第一次调用的时候运行时常量池中的符号引用会转化为直接引用
动态链接:符号引用在每一次运行时才会转化为直接引用
返回地址:方法的返回地址