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. nginx配置rewrite

    1. uri  和 url读取区别 区别就是URI定义资源,而URL不单定义这个资源,还定义了如何找到这个资源. 比如说,一个服务器上,到一个文件夹/网页的绝对地址(absolute path)就是U ...

  2. 鼠标滚动事件兼容性 wheel、onwheel

    wheelEvent = "onwheel" in document.createElement("div") ? "wheel" : // ...

  3. 迷你DVD管理器(Java版)

    import java.text.SimpleDateFormat;import java.util.Date;import java.util.Scanner;class Test {    pub ...

  4. vi编辑器的基本使用

      进入vi为命令模式,需要按 i/a/o 键进入插入模式(在左下角最后一行有“-- INSERT --”字样). i:光标所在位置,进行输入(相似命令cw) a:光标所在位置的下一个位置,进行输入o ...

  5. Scanner概述

    * Scanner:用于接收键盘录入数据. * System类下有一个静态的字段: * public static final InputStream in; 标准的输入流,对应着键盘录入. * * ...

  6. MapReduce、Hbase接口API实践

    读取hdfs中文件并做处理,取出卡号,通过卡号连接hbase查询出对应客户号,写入redis,因为不用输出,所以不调用context.write方法,整个操作在一个map中便可完成 protected ...

  7. JAVA虚拟机类型转换学习

    Java虚拟机包括血多进行基本类型转换工作的操作码,这些执行转换工作的操作码后面没有操作数,转换的值从栈顶端获得.Java虚拟机从栈顶端弹出一个值,对它进行转换,然后再把转换结果压入栈.进行int.l ...

  8. nodejs初探(二)第一个nodejs程序“hello world”

    直接用文本编辑器编写helloworld.js,保存在桌面 var http = require("http"); http.createServer(function(reque ...

  9. git 强制回退服务器上的commit

    假设你有3个commit如下: commit 3 commit 2 commit 1   其中最后一次提交commit 3是错误的,那么可以执行: git reset --hard HEAD~1 你会 ...

  10. 四则运算GUI设计

    使用了QT来设计GUI,目前也还在看视频学习中,目前还不会用这个软件,所以具体功能还未实现,初步绘制的界面如下: