HotSpot虚拟机对象创建
2.3.1对象创建
Java是一门面向对象的语言,在Java程序的运行过程中无时无刻都有新的对象被创建出来。从语言的层面看,创建对象通常仅仅是一个new关键字而已,从虚拟机的角度看,创建对象又是怎样的一个过程呢?
虚拟机遇到一条new指令时,首先将会去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有,必须想执行相应的类加载过程。
在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需内存的大小在类加载完成后便可完全确定,为对象分配空间其实就是把一块大小确定的内存从java堆中划分出来。
假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那分配内存的工作其实就是将这个指针向空闲空间挪动一段与对象大小相等的距离,这种分配方式称为“指针碰撞”。
如果Java堆中的内存并不是规整的,已使用的内存和未使用的内存交错存在,那就没有办法进行简单的指针碰撞了,虚拟机必须维护一个列表,记录哪些内存是尚未使用的、可分配的,在分配内存的时候从列表中找到一块足够大的空闲空间划分给对象实例,并更新列表上的记录,这种分配方式称为“空闲列表”
具体使用哪种方式分配内存由Java堆是否规整决定,而Java堆是否规整又由采用的垃圾收集器是否带有压缩整理功能决定。
除了如何划分可用空间,另外还需要注意空间划分时的线程安全问题。对象的创建在虚拟机中是非常频繁的,以较为简单的“指针碰撞”为例,即使只是简单的修改指针指向的位置,在在并发情况下一样存在线程安全问题,比如说正在给A分配内存,指针还没来得及修改,对象B也请求分配内存,也需要修改指针。
上述问题有两个解决方案:
方案一 对分配内存的操作进行同步处理——实际上虚拟机采用CAS配上失败重试的方式保证更新操作的原子性。
方案二 把分配内存的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)。哪个线程要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完并需要分配新的TLAB的时候,才需要进行同步锁定。虚拟机是否使用TLAB,可以通过-XX:+/-UseTLAB参数来设定。
内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头,因为对象头中要保存其他信息),如果使用TLAB,这一工作可以提前至TLAB分配的时候进行。这一操作保证了对象的实例字段在Java代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。
接下来,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头(Object Header)之中。根据虚拟机当前运行状体的不同,如是否启动偏向锁等,对象头会有不同的设置方式。
上面的工作完成之后,从虚拟机的视角来看,一个新的对象就已经产生了,但从Java程序的视角看,对象的创建才刚刚开始——<init>方法还没有执行,所有的字段还是零值。所以,一般来说(由字节码中是否跟随invoke special指令所决定),执行new指令之后会接着执行<init>方法,把对象按照程序员的意愿进行初始化,这样一个真正的对象才算产生出来了。
总结对象的创建过程:
类加载检查→对象内存分配→各字段赋零值→对象头信息设置→初始化
HotSpot虚拟机对象创建的更多相关文章
- HotSpot虚拟机对象相关内容
一.对象的创建 1.类加载检查 普通对象的创建过程:虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.解析和初始化 ...
- 深入理解Java虚拟机读书笔记1----Java内存区域与HotSpot虚拟机对象
一 Java内存区域与HotSpot虚拟机对象 1 Java技术体系.JDK.JRE? Java技术体系包括: · Java程序设计语言: · 各种硬件平台上的 ...
- 深入理解JVM(③)——之HotSpot虚拟机对象探秘
前言 上篇文章介绍了Java虚拟机的运行时数据区域,大致明白了Java虚拟机内存模型的概况,下面就基于实用优先的原则,以最常用的虚拟机HotSpot和最常用的内存区域Java堆为例,升入探讨一下Hot ...
- HotSpot虚拟机对象探秘(对象创建,对象内存布局,对象访问定位)
以常用的HotSpot虚拟机和JAVA内存区域堆为例,探讨对象的创建,对象的内存布局以及对象的访问定位 一.对象的创建 1)类加载:虚拟机遇到一条new指令时,先检测这个指令的参数能否在常量池中定位到 ...
- 深入理解java虚拟机(二)HotSpot Java对象创建,内存布局以及访问方式
内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的 ...
- HotSpot虚拟机对象探秘-笔记
学习目的:探讨HotSpot虚拟机在Java堆中对象分配.布局和访问的全过程. 1.对象的创建 虚拟机在执行到一条new指令时,先要检查指令的参数(将要实例化的类)是否已经被加载.解析.初始化过,如果 ...
- HotSpot 虚拟机对象揭秘【转载】
对象的创建 Java 对象的创建过程, ①类加载检查: 虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过.解 ...
- Java内存区域与内存溢出异常--HotSpot虚拟机对象探秘
以常用的HotSpot和常用的Java堆为例,深入探讨HotSpot虚拟机在Java堆中对象分配.布局和访问的全过程 1.对象的创建 ①虚拟机遇到一条new指令后,首先将去检查这个指令的参数是否能够在 ...
- 【深入理解JAVA虚拟机】第二部分.内存自动管理机制.2.HotSpot虚拟机对象探秘
对象的创建过程 1.加载类 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载. 解析和初始化过. 如果没有,那必须 ...
随机推荐
- spring cloud 微服务之 -- 配置文件拆分之道
0-前言 在spring cloud微服务架构中,基本上每个拆分的微服务都会部署多个运行实例,这些运行实例,配置基本都是一样的,不同的是少数配置,比如端口,而这些不同的配置又是必不可少的 那我们怎么来 ...
- netcore 自动生成Dockerfile的坑
简介 之前采用shell脚本+dockerfile的方式构建项目,后来发现有Docker在17.05版本之后有多阶段构建方式,该文主要记录了netcore采用dockerfile构建遇到的坑. 原 ...
- 【转】ArcGIS 10.1 for Server 架构
前一段时间在博客中公布了我们的计划,我们采用博客的形式将对ArcGIS10.1 for Server进行全面介绍.但这种形式有一定的遗憾:缺少互动的空间,所以我们希望广大爱好者能将自己感兴趣的话题在博 ...
- 搭建个人OpenAPI
简介 OpenAPI Open API 即开放 API,也称开放平台. 所谓的开放 API(OpenAPI)是服务型网站常见的一种应用,网站的服务商将自己的网站服务封装成一系列 API(Applica ...
- vue超简单加载字体方法,解决scss难加载字体的问题
vue超简单加载字体方法,解决scss难加载字体的问题 scss在加载字体方面一直不太好用,需要繁杂的配置才能达到想要的效果,这里说一种非常简单的方法 在App.vue的style标签下引入字体文件后 ...
- dp-完全背包(题)
理解了这道题 , 我感觉对背包又有了一个更深的认识 …… HDU 2159 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务.久而久之xhd开始对杀怪产生的厌恶感, ...
- scratch3.0二次开发scratch3.0基本介绍(第一章)
为什么要自己开发而不使用官方版本? 这个问题要看我们的做少儿编程教育的需求是怎么样的. scratch本身提供了离线版本以及官网在线平台供我们使用,这足以满足我们对于编程教学模块的需求.但是对于一些教 ...
- Jenkins配置安装
一.安装 [root@localhost ~]# wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins.io/redhat-stable/j ...
- 机器学习-TensorFlow建模过程 Linear Regression线性拟合应用
TensorFlow是咱们机器学习领域非常常用的一个组件,它在数据处理,模型建立,模型验证等等关于机器学习方面的领域都有很好的表现,前面的一节我已经简单介绍了一下TensorFlow里面基础的数据结构 ...
- hge引擎使用技巧
图片周围最好留出一像素,即上下左右都多出一像素.然后使用pngopt.exe处理一下.这样可以减少图片拉伸.旋转时边界模糊的情况 图片宽高最好是 2的N次方