一、jvm运行时的数据区域
jvm运行时数据区域
在jvm运行时的数据区域,方法区和堆是线程共享的区域,而java 栈,本地方法栈,程序计数器 这三部分是每个线程私有的空间。
1.程序计数器
程序计数器是很小的一块内存区域,可以看成是所执行的字节码文件的行号指示器,字节码解释器就是通过程序计数器的值选取下一条需要执行的指令。处理器切换线程时不会记录上个线程执行到了那个位置,为了每个线程能够切换到上次执行的位置,因此程序计数器是每个线程私有的。在执行Native方法时,由于Native方式不是由java语言编写的,不需要存储字节码行号,因此此时程序计数器为空。
2.java虚拟机栈
java 虚拟机栈是线程锁私有的,生命周期和线程相同,随着线程的开始而产生,随着线程的消亡而结束。java虚拟机栈是描述java方法执行的内存模型,每个方法执行的同时就会创建一个栈帧,存储局部变量表,操作数栈,方法出口等信息,
3.本地方法栈
本地方法栈是为程序运行过程中使用到的本地方法而服务的,在虚拟机规范中,并没有对本地方法所使用的的语言,使用方法,数据结构进行规范,因此有的虚拟机会把虚拟机栈和本地方法栈合一。
4.java 堆
堆是内存区域最大的一块,是所有线程所共享的区域,在虚拟机启动的时候创建,主要用来存放实例对象,几乎所有的对象实例都是在堆中分配内存,堆也是垃圾收集器主要工作的地方,java堆可以处在不连续的物理空间上,只要逻辑上连续即可。
5.方法区
方法区也是被线程所共享的区域,存储的是已被虚拟机加载的类的信息,静态变量等。方法区可以不选择实现垃圾收集,这个区域主要是对常量的回收和类型的卸载。
二、对象的创建
在java程序运行时,对象时时刻刻在被创建出来,当虚拟机遇到一个new指令时,先去检查这个类是否已经被加载,解析,初始化过。当检查完后,会为这个对象分配内存,内存分配完成后,需要将分配的空间都初始化为零值,当执行完init方法后,一个真正可用的对象才算被创建出来。
三、对象的访问定位
目前主流的对象的访问方式有2种,使用句柄和直接指针访问。
1.使用句柄访问。
使用句柄访问的话,java堆会划分出来一块内存为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据和类型数据各自的具体地址信息。
句柄访问
2.使用直接地址访问
如果使用直接地址访问,那么java堆对象的布局中就要考虑如何放置类型数据的相关信息。而reference中存储的就是对象地址。
直接指针访问对象
使用句柄访问最大的好处就是reference中储存的是稳定的句柄地址,在对象被移动的时候,只会改变句柄中的实例数据指针。
使用直接指针的好处就是速度非常的快,节省了一次指针定位的时间。