java 对象的创建与使用
2016-03-15 20:30:54 最后更新: 2016-03-15 20:30:54 访问数量:870
2016-03-15 20:30:54 最后更新: 2016-03-15 20:30:54 访问数量:870
HotSpot 是在 JIT 之后的一款 java 虚拟机的开源实现,sun 从 JDK 1.3.1 开始使用
它主要使用 C++ 实现的,相对于 JIT,性能有大幅提高
HotSpot 将部分代码直接编译为本地可执行代码,从而显著提升了性能
java 中,最经常发生的就是对象的创建,那么,虚拟机在 java 对象创建过程中发生了什么呢?
虚拟机遇到一条 new 指令时,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已经被加载、解析和初始化过,如果没有,则执行相应的类加载流程
接下来,虚拟机为新生对象分配内存,对象所需内存的大小在类加载完成后可以完全确定,因此可以将一块确定大小的内存从 java 堆中划分出来
在堆中的内存分配有两种方式:
由于 java 是线程模型,所以需要考虑频繁的对象创建的线程安全问题
有两种方案解决这个问题:
jvm 在为对象分配空间后需要将分配的空间初始化为零值,并且根据对象头中的对象信息如哈希码、GC 分代年龄等信息对对象进行必要的设置
随后,一般来说执行 new 指令之后会接着执行 init 方法,将对象初始化成程序所希望得到的样子
一个真正可用的对象就完全诞生了
在 HotSpot 虚拟机中,对象在内存中分为三个部分:对象头、实例数据、对齐填充
对象头包含两部分信息:
实例数据部分是对象存储的有效信息,也就是程序中定义的各种类型字段内容
这部分数据不是必须存在的,也没有特别含义,因为 HotSpot 是8字节对齐的,因此需要通过对其填充补全8字节
在 java 栈中,维护了一个本地变量表,当需要访问一个变量时,jvm 就会在本地变量表中查找到变量的类型信息,如果是一个 reference 类型的变量,jvm 就需要去加载相应的对象
下面的两图分别展示了通过句柄访问对象和通过指针访问对象的存储模式:
使用句柄最大的好处是 reference 中存储的是稳定的句柄地址,在对象移动、垃圾收集等工作中,只需要更新指针,而不需要改变 java 栈中的 reference 的指向(句柄地址不变)
而显然指针访问方式的优势就是速度更快,节省了一次指针定位的开销,对于频繁的对象操作,这类开销累积起来是十分可观的,因此 HotSpot 采用了指针直接访问对象的方式进行对象访问和操作