对象创建(new一个对象)
创建一个对象的流程
这边着重讲几个东西
一个对象在创建前就已经知道会占用多大的空间
关于分配内存时候的并发问题
关于分配内存的并发问题,需要从垃圾回收器等方面考虑
首先先介绍两个概念,指针碰撞与空闲列表
假如我们的回收算法,在回收对象的时候还会有整理的功能,那么我们对中的内存始终是一块未使用,一块已使用的。然后他们中间放着一个指针作为分界点。每次分配空间就是将指针往空闲空间挪动指定大小
但是有些垃圾回收器并不会去做整理,此时就会产生很多不连续的空闲内存空间。对于这种,虚拟机就需要维护一个列表,来记录那些空闲空间。然后在分配对象需要申请空间的时候,就会去空闲列表上找出足够大的空间分配给对象实例
对应的一些使用场景
以Serial、ParNew等带有压缩整理过程的收集器,系统采用的是指针碰撞,即简单又高效
对于CMS这种基于清除(Sweep)算法的收集器,需要空闲列表来分配内存
说完了分配空间,回到一开始并发问题。分配空间是的并发问题指的是:
线程A在给对象A分配内存时,还未来得及将指针指向内存空间,此时线程B进来给对象B分配内存,重复使用了这块内存空间。
对此,虚拟机有两种方式解决:
- CAS+失败重试
- 把内存分配的操作按照线程划分在不同的空间上进行(即每个线程在Java堆中实现分配一小块内存 本地线程分配缓冲) TLAB
- 会将赋零值的操作在这一步就完成
句柄访问,直接指针的优缺点在哪里
句柄访问:Java堆中会额外划分出一块内存作为句柄池,reference中存储的就是对象的句柄地址,句柄中包括了对象实例数据与类型数据格子具体的地址信息
优点:因为垃圾回收时移动对象是一个很普遍的行为,在移动对象时我们只需要改变句柄中的实例数据的指针,不需要逐个修改reference
但是访问时会多加一次句柄池的访问,效率会较直接指针低一点
直接指针:堆中对象实例数据会保留对象类型数据的地址信息
对象头
对象在堆内存中存储布局分为三个部分:对象头、实例数据、对齐填充
- Post title:对象创建(new一个对象)
- Post author:大黄
- Create time:2021-12-30 22:01:35
- Post link:https://huangbangjing.cn/2021/12/30/对象创建(new一个对象)/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.