Java是一门面向对象的语言,Java程序运行过程中无时无刻都有对象被创建出来。在语言层面上,创建对象(克隆、反序列化)就是一个new关键字而已,但是虚拟机层面上却不是如此。我们看一下在虚拟机层面上创建对象的步骤:
  (1)虚拟机遇到一条new指令,首先去检查这个指令的参数能否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化。如果没有,那么必须先执行类的初始化过程。

  (2)类加载检查通过后,虚拟机为新生对象分配内存。对象所需内存大小在类加载完成后便可以完全确定,为对象分配空间无非就是从Java堆中划分出一块确定大小的内存而已。这个地方会有两个问题:
  ①如果内存是规整的,那么虚拟机将采用的是指针碰撞法来为对象分配内存。意思是所有用过的内存在一边,空闲的内存在另外一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针向空闲那边挪动一段与对象大小相等的距离罢了。如果垃圾收集器选择的是Serial、ParNew这种基于压缩算法的,虚拟机采用这种分配方式。
  ②如果内存不是规整的,已使用的内存和未使用的内存相互交错,那么虚拟机将采用的是空闲列表法来为对象分配内存。意思是虚拟机维护了一个列表,记录上哪些内存块是可用的,再分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的内容。如果垃圾收集器选择的是CMS这种基于标记-清除算法的,虚拟机采用这种分配方式。
  另外一个问题及时保证new对象时候的线程安全性。因为可能出现虚拟机正在给对象A分配内存,指针还没有来得及修改,对象B又同时使用了原来的指针来分配内存的情况。虚拟机采用了CAS配上失败重试的方式保证更新更新操作的原子性和TLAB两种方式来解决这个问题。

照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)。哪个线程需要分配内存,就在哪个线程的TLAB上分配。虚拟机是否使用TLAB,可以通过-XX:+/-UseTLAB参数来设定。这么做的目的之一,也是为了并发创建一个对象时,保证创建对象的线程安全性。TLAB比较小,直接在TLAB上分配内存的方式称为快速分配方式,而TLAB大小不够,导致内存被分配在Eden区的内存分配方式称为慢速分配方式。

  (3)内存分配结束,虚拟机将分配到的内存空间都初始化为零值(不包括对象头)。这一步保证了对象的实例字段在Java代码中可以不用赋初始值就可以直接使用,程序能访问到这些字段的数据类型所对应的零值。
  (4)对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息,这些信息存放在对象的对象头中。
  (5)执行<init>方法,把对象按照程序员的意愿进行初始化。

  到此,一个真正可用的对象才算完全产生出来。
  上述建立对象是为了使用对象,Java程序需要通过栈上的reference(引用)数据来操作堆上的具体对象。比如我们写了一句:

Object obj = new Object();

  在new Object()之后,其实有两部分内容,一部分是类数据(比如代表类的Class对象),一部分是实例数据。
  由于reference在Java虚拟机规范中只是一个指向对象new Object()的引用obj,并没有规定obj应该通过何种方式去定位,以及访问堆中对象的具体位置,所以对象访问方式也是取决于虚拟机而定的。主流方式有两种:
  (1)句柄访问。Java堆中划分出一块句柄池,obj指向的是对象的句柄地址,句柄中则包含了类数据的地址和实例数据的地址
  (2)指针访问。对象中存储所有的实例数据和类数据的地址,obj指向的是这个对象
  HotSpot虚拟机采用的是后者,不过前者的对象访问方式也是十分常见的。  

详述Java对象创建的更多相关文章

  1. 深入学习Java对象创建的过程:类的初始化与实例化

    在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类构造器完 ...

  2. 2.Java对象创建

    1. 对象的创建 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.解析和初始化过.如果没有,那必须先执行相应的类 ...

  3. Java虚拟机4:Java对象创建和对象访问

    1.对象创建 Java是一门面向对象的语言,Java程序运行过程中无时无刻都有对象被创建出来.在语言层面上,创建对象(克隆.反序列化)就是一个new关键字而已,但是虚拟机层面上却不是如此.看一下在虚拟 ...

  4. Java对象创建的过程及对象的内存布局与访问定位

    这里以HotSpot为例,且所说的对象指普通的Java对象,不包括数组和Class对象等. 1.对象创建的过程 1.类加载.解析.初始化:虚拟机遇到new时先检查此指令的参数是否能在常量池中找到类的符 ...

  5. Java对象创建过程补遗

    一.static修饰的东东是属于这个类的,是所有的该类的实例共享的,因此它们的初始化先于实例对象的初始化. 二.Java中没有静态构造方法,但是有静态代码块.当类中同时存在静态代码块和静态成员变量声明 ...

  6. 深入理解java虚拟机(二)HotSpot Java对象创建,内存布局以及访问方式

    内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的 ...

  7. JVM(2)--深入理解java对象创建始终

    java对象探秘 java是一门面向对象的语言,我们无时无刻不在创建对象和使用对象,那么java虚拟机是如何创建对象的?又是如何访问对象的?java对象中究竟存储了什么运行时所必需的数据?在学习了ja ...

  8. HotSpot Java对象创建,内存布局以及访问方式

    内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的 ...

  9. Java对象创建模式

    创建Java对象时,对于可为空的属性,创建对象的时候有3种模式:重叠构造器模式.JavaBeans模式.Builder模式(推荐).Stream模式(推荐).                     ...

随机推荐

  1. BZOJ 2742: [HEOI2012]Akai的数学作业

    2742: [HEOI2012]Akai的数学作业 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 535  Solved: 226[Submit][S ...

  2. 【BZOJ3064】CPU监控(线段树)

    [BZOJ3064]CPU监控(线段树) 题面 BZOJ 洛谷 题解 神仙\(zsy\)出在了\(noip\)模拟的题目.(然而\(zsy\)出的还是这题的升级版) 首先明确一点,这题是一个吉司机线段 ...

  3. BZOJ 3143 游走 | 数学期望 高斯消元

    啊 我永远喜欢期望题 BZOJ 3143 游走 题意 有一个n个点m条边的无向联通图,每条边按1~m编号,从1号点出发,每次随机选择与当前点相连的一条边,走到这条边的另一个端点,一旦走到n号节点就停下 ...

  4. BZOJ 1036 树的统计 | 树链剖分模板题

    又做了一遍--去掉读入优化只有八十行~ #include <cstdio> #include <cstring> #include <algorithm> usin ...

  5. Android Emoji兼容包使用详解

    Emoji兼容性 我们经常会遇到这样的问题: 给朋友发的emoji表情, 在自己手机上展示是正常的, 但是到朋友手机上, 却没有展示出来, 或者展示出来了, 但是也跟自己手机上展示的不一样. 所以,  ...

  6. BZOJ4589 Hard Nim 【FWT】

    题目链接 BZOJ4589 题解 FWT 模板题 #include<algorithm> #include<iostream> #include<cstdlib> ...

  7. 洛谷 P2389 电脑班的裁员 解题报告

    题意: 给定一段长为N的序列,选取其中的至多M段使这些子段和最大. 当N=1000时,我们可以采用动态规划解法 令\(dp[i][j][k]\)代表当前选至位置\(i\)处于第\(j\)段当前是否选取 ...

  8. Nginx web服务优化 (一)

    1.Nginx基本安全优化 a.更改配置文件参数隐藏版本 编辑nginx.conf配置文件增加参数,实现隐藏Nginx版本号的方式如下.在nginx配置文件nginx.conf中的http标签段内加入 ...

  9. Linux内核分析第八周——进程的切换和系统的一般执行过程

    Linux内核分析第八周--进程的切换和系统的一般执行过程 李雪琦+原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/cou ...

  10. Memcache PHP 使用笔记

    Memcache PHP 使用笔记 最近在做网站迁移 看到之前的一个网站目录下Cache文件里上万的缓存文件真是害怕 新的服务器上配置了memcache扩展 于是乎准备折腾一下看看能不能把之前的文件缓 ...