JVM 系列(2)对象的创建

对象的创建和访问

1 对象的创建过程

	当java虚拟机遇到一条字节码new指令时
	(1)检查这个指令的参数能否在常量池定位到一个符号引用
	(2)检查该引用是否加载,解析,初始化过,如果没有,先加载类
	(3)虚拟机为新生代分配内存
	(4) 对对象进行必要的设置
			  将对象的元信息,对象的哈希值,GC分代年龄等信息存放在对象头
	
	从虚拟机视角看,一个对象已经产生
	但是从java程序的视角,对象的创建才刚开始

1.1对象的分配方式

	对象的分配方式有两种:
			(1)指针碰撞:
						就只是将指针向空闲的一边挪动一段与对象大小相等的距离
						如果已经使用的内存和空闲的内存交错在一起,就没有办法使用指针碰撞
			(2)压缩指针:
						虚拟机需要维护一个列表,记录哪些内存时可用的
						分配的时候找到一块足够大的空间划分给对象实例
						跟新列表上的记录

1.2 创建对象的线程安全问题

	创建对象时非常频繁的行为,可能出现正在给A分配内存,指针还未来得及修改,B又使用了原来的指针
	解决这个问题有两个方案:
				(1) 对分配的内存的动作进行同步处理
						实际上虚拟机时采用CAS+失败重试的方式保证更新操作的原子性
				(2)将内存分配的动作按照线程划分在不同的空间内进行
						 每个线程在java堆中预先分配一小块内存(本地线程分配缓冲区 TLAB)
						 那个线程要分配内存,就在那个线程的本地缓冲区分配
						 只有本地线程分配完了,分配新内存时才需要同步
						 TLAB 通过 -XX:+/-UseTLAB 设置

2 对象的访问方式

	主流的访问方式有句柄访问和直接访问:
				(1)句柄访问:
						 从java堆中划分出一块内存作为句柄池
						 reference(引用类型)存储的就是对象的句柄地址
						 句柄中包含了对象实例数据和类型数据各自的指针
						 当对象被移动时(垃圾回收对象移动是很普遍的行为)只需改变句柄中的指针就好
						 无需改变reference
				(2)直接指针:
						 reference 存储的就是对象的地址
						 如果只是访问对象本身,就无需多一次开销,速度更快

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/kznsbs/article/details/107550846