1. 对象的创建

  虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程,在类的加载检查通过后,接下来java虚拟机会为新生对象会在堆中划分出一定的内存。对象所需内存大小在类加载完成后即可完全确定。

  假设,java堆中的内存是绝对规整的,分配内存仅仅是把指针指向空闲空间那边挪动一段与对象大小相等的距离,叫“指针碰撞”,如果java堆中的内存不是规整的,则虚拟机需要维护一个列表记录哪些内存块可用,然后找到一个足够大的去空间划分给对象,然后更新列表记录,叫“空闲列表”。具体选择哪种分配方式由java堆是否规整决定,是否规整又由所采用的垃圾搜集器是否带有压缩整理功能决定。

  内存分配的线程安全性:①.对分配内存空间的动作进行同步处理——实际上虚拟机采用CAS配上失败重试的方式保证操作的原子性;②.把内存分配的动作按照线程划分在不同的空间之中进行(即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer, TLAB),哪个线程需要分配内存,就在那个线程的TLAB上分配,只有当TLAB用完并分配新的TLAB时,才需要同步锁定虚拟机是否使用TLAB:可通过-XX:+/-UseTLAB参数来设定)。

  内存分配完后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)。如果使用TLAB,也可以提前到TLAB分配时。这操作保证了对象实例字段在Java代买中可以不赋初始值就直接使用。

  虚拟机对对象进行的必要设置存放于对象头之中。

  在完成new指令之后,紧接着会调用<init>方法将对象初始化,这时一个完整的对象才算创建了出来。

  完结之后把对象的引用入栈。

2.对象的内存布局

  对象在内存存储的布局可以分为三大类:对象头(Header),实例数据(Instance Data),和对齐填充(Padding)。

  HotSpot虚拟机的对象头包含两部分信息:①用于存储对象本身的运行时数据(哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等),长度在32位和64位的虚拟机中分别为32bit和64bit,官方称“Mark

Word”。②是类型指针,即对象指向它的类源数据的指针虚拟机通过这个指针来确定对象是哪个类的实例。但是并不是所有的虚拟机实现都必须在对象数据上保留类型指针(即查找对象的元数据信息并不一定要经过对象本身,另外如果对象是一个数组,那么对象头中还必须要一块记录数组长度的数据,因为Java虚拟机可以通过普通java对象的元数据信息确定Java对象的大小,但是从数据元数据中却无法知道数组的大小)。

  实例数据部分是对象真正存储的有效信息,也就是在程序代码中所定义的各种类型的字段内容。不论父类继承的还是子类定义的,其存储顺序会受到java虚拟机分配策略参数和字段在java源码中定义顺序的影响。HotSpot默认分配策略是:longs/doubles,ints,shorts/chars,bytes/booleans,oops(Ordinary
Object
Pointers)。相同宽度的字段总是分配在一起,在满足这个条件下,父类中定义的变量会出现在之类之前。如果CompactFields参数为true(默认的),那么子类中较窄的变量也可能插入到父类变量的空隙之中。

  第三部分对齐填充不是必然存在的。仅仅是占位符作用。

3. 对象的访问定位

  java程序需要通过栈上的reference数据来操作堆上的具体对象。reference类型在Java虚拟机规范中之规定了一个指向对象的引用,并没有定义这个引用应该通过何种方式去定位、访问堆中对象的具体位置。看虚拟机具体实现,主流有使用句柄和直接指针:

  ①使用句柄要从Java堆中划出一块内存作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据与类型数据格子的具体地址,优点是在对象被移动时只会改变句柄中的实例数据指针,reference本身不需要修改。缺点是多了一次指针定位时间开销。

  ②直接指针访问,reference中存储的直接就是对象地址,好处是速度更快,节省一次指针定位的时间开销,但是对象移动需要修改reference本身。

2.Java对象创建的更多相关文章

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

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

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

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

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

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

  4. Java对象创建过程补遗

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

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

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

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

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

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

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

  8. Java对象创建模式

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

  9. 详述Java对象创建

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

随机推荐

  1. Redis 初

    tcl8.6.1 $wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz $tar xzvf tcl8.6.1-src.tar.g ...

  2. bootstrap初接触

    Bootstrap 是最受欢迎的 HTML.CSS 和 JS 框架.(主要是结合HTML5 CSS3的样式, 基于jquery+Bootstrap 自带 12 种 jQuery 插件,扩展了功能,可以 ...

  3. 使用C#访问SQLLite

    1.SQLLite如何集成在C#中 2.相关C#与SQLLite资源,及说明 3.简单示例

  4. gradle大体内容

    buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:grad ...

  5. shell script练习

    执行脚本的几种方式: 1. sh a.sh 或者  bash a.sh  调用的是 /bin/bash 进程执行的,所以脚本不需要执行权限. 2. 直接使用绝对路径执行, /home/script/a ...

  6. iOS开发官方文档汇总

    程序员的学习过程是无止境的,程序员学习的途径是多样的.可以从视频教程中领悟,也可以从他人的代码中 理解.但当我们专注于某一个平台在开发的时候,对于某个API使用或者功能实现有疑问,通常简单的测试可以让 ...

  7. alarm rtc

    http://sharp2wing.iteye.com/blog/1329518 http://blog.csdn.net/sking002007/article/details/6593809 io ...

  8. MoleHill Getting Started AGAL(转)

    1.The OpCode This is what AGAL looks like: //vertex shader m44 op, va0, vc0 // pos to clipspace mov ...

  9. json和字符串转换

    json对象转js字符串 JSON.stringify(json) js字符串转json对象 var json= $.parseJSON(str);

  10. C++连接mysql的两种方式(ADO连接和mysql api连接)

    一.ADO连接mysql 1.安装mysql-5.5.20-win32.msi和mysql-connector-odbc-5.3.4-win32.msi(一般两个安装程序要匹配,否则可能连接不上)  ...