深入理解JVM(二)--对象的创建
Java是一门面向对象的语言,在Java程序运行的过程中,无时无刻都会有对象被创建出来,在程序语言中,创建对象(例如克隆,反序列化)通常仅仅是一个new关键字,但是在虚拟机中是怎样的呢?本文主要了解一下一个对象(仅代指普通对象,不包含Class类和数组)在虚拟机中的创建过程。
当虚拟机遇到一条new指令时,首先将去检查这个指令的参数能否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载,解析和初始化过,如果没有,那必须先执行相应的类的加载过程。
在类加载检查通过后,接下来虚拟机将为新生对象分配内存,对象的大小在类加载完毕之后就可以确认,从物理上来讲就是从堆中分配与新生对象大小相等的内存区域来存放新生对象。假设内存是规整的,即已经使用的内存区域是连续的,剩余空闲内存区域也是连续的,此时可以使用一个指针来划分已使用内存区域和可用内存区域,在这种情况下当需要产生新生对象时,只须将该指针向后移动与新生对象大小相等的长度即可,这种分配内存的方式叫“指针碰撞”。当内存并不是规整的时候,就没有办法进行简单的指针碰撞来分配内存了,这时候虚拟机就需要维护一个列表,记录内存上哪些区域是可用的并记录这些区域的大小和起始位置,需要分配内存时,从列表中找到合适的内存位置为新对象分配内存,这种分配方式叫做“空闲列表”。选择哪种内存分配方式由内存区域是否规整决定,而是否规整又取决于该区域采用的垃圾回收算法是否带有整理内存的功能,对于Serial,ParNew等带有compact过程的收集器时,可以使用指针碰撞来分配内存(例如老年代),对于CMS这种mark-sweep算法的收集器,采用空闲列表的方式。
除了如何划分可用空间之外,还需要考虑在虚拟机中创建对象是非常频繁的行为,即使仅仅移动一个指针的操作,在并发情况下也是不安全的,可能出现正在给A对象分配内存,指针还没来得及修改,对象B又使用了原来的指针位置来分配内存。解决这个问题有两种方式,一是对分配内存空间的动作进行同步处理,实际上虚拟机使用CAS配上失败重试的方式来保证更新操作的原子性。另一种方式是把内存分配的动作按照线程在内存中进行划分,即每个线程在内存中都预先分配一小块区域,称为本地线程分配缓冲(TLAB,Thread Local Allocation Buffer)当这个线程需要创建新生对象的时候,在本线程的内存区域中进行创建,只有TLAB使用完并分配新的TLAB的时候,才需要进行同步处理。虚拟机是否使用TLAB,可以通过 -XX:+/-UseTLAB参数来设定。
在内存分配完成之后,虚拟机会将新分配的内存空间全部初始化为0值(不包括对象头),如果使用了TLAB,这一过程也可以提前至分配TLAB时执行,这一步保证了对象的实例字段在Java代码中不赋初始值就可以直接使用,程序能访问到这些字段的数据类型对应的零值,如:。


接下来,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例,哈希码是多少,对象的分代年龄是多少等信息,这些信息存放在对象头(Object Head)中。这些工作都完成之后,从虚拟机来看,一个对象已经产生了,但是从Java程序的角度看,对象创建才刚刚开始,--<init>方法还没有执行,所有的字段都还为零,执行new指令后会接着执行<init>方法,把对象按照程序员的意愿进行初始化,这样一个完整可用的对象才产生出来。
深入理解JVM(二)--对象的创建的更多相关文章
- 深入理解JVM(4)——对象的创建和访问
1.对象的创建 在语言层面上,创建对象(例如克隆,反序列化)通常仅仅是一个new关键字而已. 在虚拟机中,对象(文中讨论的对象限于普通 Java 对象,不包括数组和 Class 对象等)的创建过程如下 ...
- JVM中对象的创建过程
JVM中对象的创建过程如以下流程图中所示: 对其主要步骤进行详细阐述: 为新生对象分配内存: 内存的分配方式: 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存在另一边, ...
- 深入理解JVM(二)Java内存区域
2.1 C.C++内存管理是由开发人员管理,而Java则交给了JVM进行自动管理 2.2 JVM运行时数据区:方法区.堆(运行时线程共享),虚拟机栈.本地方法栈.程序计数器(运行时线程隔离,私有) 1 ...
- JVM(二) 对象存活判断和垃圾回收算法
对象的创建 概述 下面简要介绍创建对象的几个重要步骤 : 检查能否在常量池定位到一个类的符号引用,并检查这个符号代表的类是否已被加载,解析和初始化过.如果没有则执行类加载的操作.(即是说对象的引用放在 ...
- 深入理解java虚拟机---对象的创建过程(八)
1.对象的创建过程 由于类的加载是一个很复杂的过程,所以这里暂时略过,后面会详细讲解,默认为是已加载过的类.着重强调对象的创建过程. 注意: 最后一步的init方法是代码块和构造方法. 以上是总图,下 ...
- 深入理解JVM(三) -- 对象的内存布局和访问定位
一 对象的内存布局: 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding). HotSpot的对 ...
- JVM(三) 对象的创建过程
1.对象的创建过程 1.1 . 给对象分配内存 对象的内存分配有两种方式,一种是指针碰撞另外一种是空闲列表的方式,堆是否规整由我们垃圾回收器来决定的 ,如果垃圾回收带有我们的压缩算法,那么他会规整的分 ...
- 理解JVM之对象的生命周期
1.对象的创建 1) 当虚拟机遇到一条new的指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载,解析和初始化过. 2) 在类加载检查通 ...
- 深入理解JVM(二)--垃圾收集算法
一. 概述 说起垃圾收集(Garbage Collection, GC), 大部分人都把这项技术当做Java语言的伴随生产物. 事实上, GC的历史远远比Java久远, 1960年 诞生于MIT的Li ...
随机推荐
- 刷题3:给定一个数组 nums,判断 nums 中是否存在三个下标 a,b,c数相加等于targe且a,b,c不相等
题目: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,下标 ,a ,b , c 对应数相加等于 targe 找出所有满足条件且不重复的三元组下标 解析: ...
- maven 私服上有jar包但是却下载不下来
解决办法: 在parent中执行deploy命令就解决了. 原因:第一次建项目,上传jar包的时候直接进入到该项目中进行deploy到私服.最终发现私服仓库有,但是别人引用的时候无法下载.是因为别人下 ...
- 【大数据应用技术】作业十二|Hadoop综合大作业
本次作业的要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3339 前言 本次作业是在<爬虫大作业>的基础上进行的 ...
- 【转】使用fastboot命令刷机流程详解
一.Fastboot是什么? 1.1 首先介绍Recovery模式(卡刷) 在系统进行定制时,编译系统会编译出一份ZIP的压缩包,里面是一些系统分区镜像,提供给客户进行手动升级.恢复系统.需要提前将压 ...
- 玩转@Git三剑客
扫码时备注或说明中留下邮箱 付款后如未回复请至https://shop135452397.taobao.com/ 联系店主
- 第2课第4节_Java面向对象编程_多态性_P【学习笔记】
摘要:韦东山android视频学习笔记 面向对象程序的三大特性之继承性: 1.向上转换:只能定义被子类覆写的方法,不能调用在子类中定义的方法. class Father { private int ...
- THOR: Tracking Holistic Object Representations
THOR: Tracking Holistic Object Representations BMVC 2019 Oral 2019-08-04 10:30:09 Paper: https://arx ...
- Springboot单元测试Junit深度实践
Springboot单元测试Junit深度实践 前言 单元测试的好处估计大家也都知道了,但是大家可以发现在国内IT公司中真正推行单测的很少很少,一些大厂大部分也只是在核心产品推广单测来保障质量,今天这 ...
- rqalpha学习-1
1 setup 安装 C:\work\python\rqalpha\setup.py install C:\work\python\rqalpha 2 mod list 列出mod C:\work\p ...
- Github-Dorks与辅助工具
前言 Github搜索功能非常强大且有用,可用于在开源出来的Github仓库中搜索敏感数据.可以找到敏感的个人和/或组织信息(例如私钥,凭据,身份验证令牌等). 文中的github dork列表可以在 ...