1.java运行时数据区图
这里写图片描述

2.程序计数器
线程私有内存。是当前线程所执行的字节码的行号指示器。简单来说:在一个确定时刻,处理器只会执行一条线程中的指令,为了线程切换后能恢复到正确的执行位置,每条线程就会需要独立的程序计数器来存储执行位置等。
如果线程正在执行一个java方法,计数器记录的是正在执行的虚拟机字节码指令的地址,如果是native方法,则计数器为空。

3.java虚拟机栈
线程私有内存。描述的是java方法执行的内存模型:每个方法被执行的时候会创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息。每个方法调用就对应一个栈帧在虚拟机栈中入栈到出栈过程。
局部变量表存放了编译期间可知的基本数据类型(boolean,byte,char..)和对象引用

4.本地方法栈
与虚拟机栈类似,只不过虚拟机栈服务的是java方法,本地方法栈服务的是native方法。

5.java堆
所有线程共享内存。存放对象实例,是垃圾回收的主要区域,java堆可以处于物理上不连续的内存空间,逻辑上连续即可。

6.方法区
所有线程共享内存。存储被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
运行时常量池
运行时常量池是方法区的一部分。Class文件中从除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池,用于存放编译生成的各种字面量和符号引用,这部分内容在类加载后存放到方法区的运行时常量池。
运行时常量池相对于class文件常量池的一个重要的特性就是具备动态性,如运行期间也可能将新的常量放入池中,如String的intern()方法。

7.直接内存
上图没画出来是因为这个并不是虚拟机运行时数据区的一部分,它是使用native函数直接分配堆外内存,java nio中DirectByteBuffer就是直接内存。这样避免了在java堆和native堆中来回复制数据。

对象访问
Object obj = new Object();
Object obj 这部分将会反映到java栈的本地变量表中,作为reference类型数据出现。new Object()将会反映到java堆中,并且java堆中还要包含查找到此对象类型数据(如对象类型,父类,实现的接口,方法等)的地址信息,这些类型数据则是存储在方法区中。
不同的虚拟机访问堆中的方式有所不同,主流有两种:使用句柄和直接指针。

1.使用句柄
java堆中会划分一块内存作为句柄池,reference中存储的是对象的句柄池,句柄池中包含了对象实例数据和类型数据各自的具体地址信息。如下图:
这里写图片描述

2.直接指针
直接指针就是直接存储的对象的地址。如下图:
这里写图片描述

使用句柄方式好处是reference中存储的是稳定的句柄地址,对象被移动只会改变句柄池中实例数据指针,并不改变reference
使用直接指针好处就是速度快,Sun HotSpot就是使用这种。

今天先到这,后续在分析虚拟机知识。
老生常谈:深圳有爱好音乐的会打鼓(吉他,键盘,贝斯等)的程序员和其它职业可以一起交流加入我们乐队一起嗨。我的QQ:657455400

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐