java对象在虚拟机中创建与访问
2019-03-19 19:25:12 66 举报
java对象在虚拟机中的创建与访问
作者其他创作
大纲/内容
程序计数器
对象头:对象头由两个部分第一部分:span style=\"font-size: 13px;\
本地方法栈
short
2
执行相应的类加载过程
对象的访问定位
堆
int
直接内存直接内存不是虚拟机运行时数据区的一部分。JDK1.4加入了NIO技术,该技术引入了一种基于通道与缓冲区的I/O方式,它可以直接使用Native函数库直接分配堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行相关操作。这样做的目的是为了避免在java堆和Native堆中来回复制数据。我们在考虑虚拟机的内存分配时,往往会忽略直接内存,导致各个内存区域总和大于物理内存限制,从而导致动态扩展时出现OutOfMemoryError异常。
对象头
对象
方法区
检查这个符号引用代表的类是否已被加载、解析和初始化过
加载过
对象知识点
....
到对象类型的指针
方法区线程共享用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。hotspot用GC分代收集扩展到方法区,也就是说用管理java堆的方式管理方法区。在hotspot中方法区在虚拟机启动时被创建,且有-XX:MaxPermSize的内存上限。在hotspot实现中,有不少人愿意把方法区称为\"永久代\
java堆
对象的指针
堆虚拟机启动时创建,java堆内存区域可以处于物理上不连续的内存空间中。所有线程共享。堆的唯一目的就是为了存放对象实例,几乎所有的对象实例都是在这里分配内存的。java堆可以细分为:新生代和老年代;更细致一点可以分为Eden、From Survivor、To Survivor;java堆的主流实现都是支持可扩展,可以通过-Xmx和-Xms控制。该区域可能抛出OutOfMemoryError错误。
句柄池
虚拟机要对对象的对象头进行必要的设置,对象头包含以下内容:对象是哪个类的实例、如何找到类、对象的hashcode、对象的GC分代年龄。
对象的内存布局
前面的步骤完成后,从虚拟机的角度来看,一个新的对象已经产生了,但从java程序的角度来看,对象创建才刚刚开始,此时<init>方法还没有执行,所有的字段都还是零。所以一般来说,执行new指令之后接着执行<init>方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生。
java虚拟机栈的局部变量表
6
运行时常量池
从java堆中分配新对象的内存
reference
本地方法栈本地方法栈与虚拟机栈所发挥的作用是非常类似的,它们之间的区别不过是虚拟机栈为java方法服务,本地方法栈为Native方法服务。虚拟机规范没有对本地方法栈的实现做出强制规定。sun hospot直接把本地方法栈和虚拟机栈合二为一。该区域与虚拟机栈一样,可能抛出StackOverflowError与OutOfMemoryError异常。
没有加载
3.2
对象类型
运行时数据区
内存分配完成后,虚拟机将分配到的内存空间都初始化为0(不包括对象头)初始化为0意味着:基础类型都赋值为0,对象指向NULL.
实例数据:存储类中定义的字段,和类继承的字段这部分的存储顺序会受到虚拟机分配策略参数和字段在java源码中定义顺序的影响。Hotspot虚拟机默认的分配策略为long/doube/int/short/char/byte/boolean/oops。父类中定义的变量会出现在子类之前。
对象类的指针
对齐填充该部分不是一定存在,该部分的作用仅仅起着占位符的作用。因为HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,对象大小必须是8字节的整数倍。因此,当对象前两个部分的总和不是8字节的整数倍,这里需要通过对齐填充来补全。
实例数据
对象创建完成以后,java程序需要通过虚拟机栈中的局部变量表中的reference数据来操作堆中的对象。主流的访问定位方式有两种:使用句柄方式、直接指针方式
7
句柄方式访问:虚拟机会在java堆中划分出一块内存作为句柄池,句柄池中的句柄包含了对象实例数据的地址和类型数据的地址。reference中存储的是句柄的地址。这种方式实现的对象访问定位,对象的内存布局中的对象头不需要存储对象的类型指针。
运行时常量池运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等表述外,还有一项信息是常量池,用于存放编译期间生成的各种字面量和符号引用。Class文件中的常量池将在类被加载后,放入方法区中的运行时常量池。运行时常量池具备动态性。运行期间也可以将新的常量放入运行时常量池中,比如使用String类的intern()方法。这个特性表明: 运行时常量池 != Class常量池
对象的创建流程
1
虚拟机栈
直接指针方式访问:reference中直接对象的地址。这个方式,需要在对象中存放对象类的指针。
对齐填充
虚拟机栈用于记录线程的方法调用情况。顾名思义虚拟机栈的数据结构为栈,线程执行到某个方法,都会创建一个栈帧放到虚拟机栈中。方法的调用与执行完成,对应着虚拟机栈的入栈与出栈操作。栈帧:局部变量表+操作数栈+动态链接+方法出口局部变量表:存放方法执行时用到的变量该区域可能出现的错误:StackOverflowError,即虚拟机栈的深度超过一定的数值;OutOfMEemory异常。
程序计数器用于记录线程执行到了哪个位置,每个线程都有一个自己的程序计数器。各线程之间的程序计数器互不影响,相互独立。如果当前线程正在执行java方法,则程序计数器则记录正在执行的虚拟机字节码指令的地址;如果线程正在执行Native方法,这个 程序计数器的值为空。该区域不会出现OutOfMemoryError错误。
3.1
4
5
0 条评论
下一页