java的运行时数据区分为:线程独占区、线程共享区
线程独占区包括:程序技术器、虚拟机栈(我们常说的那个栈)、本地方法栈;
虚拟机栈是为执行java方法服务的;本地方法栈是为了虚拟机执行native方法服务
线程共享区包括:java堆、方法区
1.程序技术器
程序计数器是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器
程序计数器处于线程独占去
如果线程执行的是java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是native方法,这个计数器的值为undifiend
此区域是唯一一个在java虚拟机中没有规定任何outofmemoryError的区域(作为程序开发者是不需要操作程序计数器的)
2.虚拟机栈
虚拟机栈描述的是java方法执行的动态内存模型
栈帧:每个方法执行,都会创建一个栈帧,伴随着方法从创建到执行完成;用于存储局部变量表,操作数栈,动态链接,方法出口等。
栈帧里包括:局部变量表、操作数栈、动态连接、返回地址等信息
局部变量表:存放的是基本数据类型,抽象数据类型的引用,我们说栈指向堆 其实具体说是局部变量表里的东西指向堆
局部变量表的内存空间再编译期间完成分配,当进入一个方法时,这个方法在帧分配多少内存是固定的,在方法运行期间是不会改变局部变量表的大小
String s1="abc"
String s2="abc"
String s3=new String("abc");
此时s1.s2.s3在局部变量表;
任何人一个非new方式字符串的创建都要扔到常量池里,s1,s2所指向的"abc"在运行时常量池,并且里面只有一个“abc”,因为运行时常量池里面有一个字符串表,类似于hashSet类型,不可重复,所以s1==s2 返回true;
每次创建实例都要在堆内开辟内存空间,因此s3所指向的“abc”在堆里面,所以 s1==s3返回false
操作数栈:在方法执行的过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈,入栈操作,例如,在做算术运算的时候是通过操作数栈来进行的,又或者在调用其他方法的时候通过操作数栈来进行方法传递。java虚拟机的解释执行引擎称为“基于栈的执行引擎”,其中所指的栈就是操作数栈。
动态连接:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个方法的引用是为了支持方法调用过程中的动态连接。
返回地址:方法退出实际就是方法出栈,有2种情况,一种是正常执行完毕,一种是执行过程中遇到的了异常,不管以何种方式退出,都要返回到方法被调用的位置,程序才能继续执行,因此退出时可执行的操作有:恢复上层方法的局部变量表和操作数栈,把返回值压入中,调整PC技术器的值以指向方法调用指令后面的一条指令。
3.本地方法栈
hotSoptVM是不区分这2个栈的,将他们合二为一
4.方法区
hotSoptVm使用永久代来实现方法区,这样就省去了为方法区编写垃圾回收代码的工作
存储虚拟机加载的类信息,常量,静态变量,编译后的代码等数据,其中类的信息包括:类的版本,字段,方法,接口
5.java堆
存放对象实例
垃圾回收器管理的主要区域