1.线程私有的(这一部分不会被垃圾回收,线程执行完就会被销毁)
1.1 程序计数器
当前线程所执行的字节码的行号指示器,可以在多线程中找到原方法执行到的位置。是唯一没有规定out of memory error(内存溢出)的区域。
1.2 虚拟机栈
每一个线程对应一个Java栈,线程每调用一个方法就会压入一个栈帧,栈帧是用来储存方法数据和部分过程结果的数据结构,例如String str=“ABC”,str被存放在栈中,在方法执行结束后出栈。 当栈的深度大于虚拟机所允许的深度时,会报StackOverflowError异常,该异常常见于使用递归函数中。
每个方法对应一个栈帧,栈帧包括:局部变量表,操作数栈,动态链接,返回地址;
局部变量表:用来存放方法中声明的基本类型的局部变量,引用类型的局部变量存放在Java堆中;
操作数栈:方法中的一些指令,诸如加减等,在里面操作;
动态链接:用来调用元空间中的其他方法,储存引用地址;
返回地址:返回方法被调用的位置。
1.3 本地方法栈
该部分与虚拟机栈类似,只不过不过虚拟机栈是为Java方法服务的,而本地方法栈是为Native方法服务的。
2.线程公有的
2.1 堆
用来存放new出来的对象和数组,当没有实体指向它时,会自动被回收。 虚拟机启动时创建,被所有线程共享。Java堆可以物理不连续,但在逻辑上是连续的。 堆可以细分为新生代和老年代。当堆中没有内存可以用于实例分配并且堆无法被扩展时,会抛出out of memory error。
堆中老年代占2/3,新生代占1/3,新生代中,分为三个空间,分别占80%,10%,10%;平时用80%和10%的两个空间储存数据,另一个用作垃圾回收时保存剩下的信息的。
2.2 方法区(元空间)
是用于存储类结构信息的地方(类名、修饰符等),是线程共享的,包括常量池、静态变量、构造函数等类型信息,类型信息是由类加载器在类加载时从类文件中提取出来的。 无垃圾回收,与堆共享物理内存,但与堆不相连,可认为在堆中。常量池包含着一些常量和符号引用,String类型的数据会存放在常量池中,方法区也会抛出out of memory error。