程序计数器:线程私有,每个线程任何时刻都只会执行一个方法的代码,这个方法称为该线程的当前方法,如果当前方法是java方法,程序xxx记录的是虚拟机字节码指令的地址,如果是native方法,则为空
堆:线程共享 ,存放对象和数组对象的地方,对象由垃圾回收器统一管理和回收
虚拟机栈:线程私有,与线程同时创建,存放栈帧,一个java方法的执行就是一个栈帧入栈和出栈的过程,存放了方法的局部变量表,动态链接,操作数栈,方法出口
本地方法栈:线程私有,对应的native方法执行的出栈与入栈
方法区:线程共享,存放类的结构信息,比如:运行时常量池,字段,构造函数等等一些共享变量,字符串常量池,普通方法的字节码类容,一些类,实例,接口初始化用到的特殊方法
运行时常量池:在方法区里。是类或者接口的常量池表在运行时的表示形式。包括编译时已知的字面量和运行时解析后才能获取的字段和方法引用。
常量池:class文件常量池,运行时常量池,字符串常量池
class文件常量池:属于class文件中的一项,在类被编译成class文件时生成,存放编译期生成的字面量和符号引用,字面量包括文本字符串,final修饰的常量值等,符号引用包括类或接口的全限定名,字段的名称和描述符等。
运行时常量池:jvm把类加载到内存中时,class常量池的内容会放到运行时常量池,每个类在执行的时候都有自己的独立的运行时常量池。
字符串常量池:是一个hash表,存放的是字符串对象实例的引用,字符串对象实例本身放在堆中,字符串常量池本身放在直接内存中。
运行时常量池和字符串常量池的联系:运行时常量池中CONSTANT_STRING_INFO类型常量在解析的时候,先到字符串常量池看是否有该字符串的引用,有就返回,没有就在堆创建一个字符串对象,然后在字符串常量池中驻留一个引用,然后返回该引用。所以运行时常量池里CONSTANT_STRING_INFO类型常量解析后存的是和字符串常量池一样的引用。
永久代:被java8移除了,存放的是类静态变量,类元数据,字符串对象实例。移除后,类静态变量和字符串对象放在堆里,元数据放在java8新加的元数据区里。
永久代和方法区的联系:方法区是jvm的一个逻辑概念,永久代部分的实现了它,但是像字符串实例这部分是要算在堆里的,不会在方法区里,所以永久代不只是实现了方法区。
元空间:存放类元数据,元空间不在jvm里,在本地内存里,可以通过参数-xx:MaxmetaSpaceSize来调节大小。默认限制是机器内存。
引入元空间的原因:随着动态加载的情况变多,以前用来存放元数据的永久代的大小变得不好控制,而元空间可以根据实际情况动态自己调整内存大小