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(二)--对象的创建的更多相关文章

  1. 深入理解JVM(4)——对象的创建和访问

    1.对象的创建 在语言层面上,创建对象(例如克隆,反序列化)通常仅仅是一个new关键字而已. 在虚拟机中,对象(文中讨论的对象限于普通 Java 对象,不包括数组和 Class 对象等)的创建过程如下 ...

  2. JVM中对象的创建过程

    JVM中对象的创建过程如以下流程图中所示: 对其主要步骤进行详细阐述: 为新生对象分配内存: 内存的分配方式: 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存在另一边, ...

  3. 深入理解JVM(二)Java内存区域

    2.1 C.C++内存管理是由开发人员管理,而Java则交给了JVM进行自动管理 2.2 JVM运行时数据区:方法区.堆(运行时线程共享),虚拟机栈.本地方法栈.程序计数器(运行时线程隔离,私有) 1 ...

  4. JVM(二) 对象存活判断和垃圾回收算法

    对象的创建 概述 下面简要介绍创建对象的几个重要步骤 : 检查能否在常量池定位到一个类的符号引用,并检查这个符号代表的类是否已被加载,解析和初始化过.如果没有则执行类加载的操作.(即是说对象的引用放在 ...

  5. 深入理解java虚拟机---对象的创建过程(八)

    1.对象的创建过程 由于类的加载是一个很复杂的过程,所以这里暂时略过,后面会详细讲解,默认为是已加载过的类.着重强调对象的创建过程. 注意: 最后一步的init方法是代码块和构造方法. 以上是总图,下 ...

  6. 深入理解JVM(三) -- 对象的内存布局和访问定位

    一 对象的内存布局: 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding). HotSpot的对 ...

  7. JVM(三) 对象的创建过程

    1.对象的创建过程 1.1 . 给对象分配内存 对象的内存分配有两种方式,一种是指针碰撞另外一种是空闲列表的方式,堆是否规整由我们垃圾回收器来决定的 ,如果垃圾回收带有我们的压缩算法,那么他会规整的分 ...

  8. 理解JVM之对象的生命周期

    1.对象的创建 1) 当虚拟机遇到一条new的指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载,解析和初始化过. 2) 在类加载检查通 ...

  9. 深入理解JVM(二)--垃圾收集算法

    一. 概述 说起垃圾收集(Garbage Collection, GC), 大部分人都把这项技术当做Java语言的伴随生产物. 事实上, GC的历史远远比Java久远, 1960年 诞生于MIT的Li ...

随机推荐

  1. 带状矩阵的存储(c++)

    2     1     0     0 3     1     3     0 0     5     2     7 0     0     9     0 这个程序对于三对角矩阵都是有效的,为了精 ...

  2. 关于java nio的channel读写的一个困惑

    这里提的需求基本都是IM的,IM的解决方案是怎么样的? 网上的需求: 1. 某一用户发了一条信息, 需要服务器反回一个信息(这种最简单) 2. 某一用户发了一条信息,需要服务器广播给所有客户端 3. ...

  3. ORA-55624: 此时无法为闪回归档启用表

    我们在某应用中使用了FDA特性,但是某些表在解除归档后重新启用时报"ORA-55624: 此时无法为闪回归档启用表",经查询google和MOS相关信息,原因就是太频繁.解决方法: ...

  4. Linux-flock文件锁的使用

    在多个进程同时操作同一份文件的过程中,很容易导致文件中的数据混乱,需要锁操作来保证数据的完整性,这里介绍的针对文件的锁,称之为“文件锁”-flock. flock,建议性锁,不具备强制性.一个进程使用 ...

  5. LeetCode_412. Fizz Buzz

    412. Fizz Buzz Easy Write a program that outputs the string representation of numbers from 1 to n. B ...

  6. css选择器测试2-用ul和li简单排版

    之前的博文:测试了一些css样式的优先级,都是比较常见的选择器 ,这里测试一些其他一些选择方式. *:通配符,所有页面的元素都走这个.设置多个class:一个标签里不能有两个class,如果想要设置多 ...

  7. [LeetCode] 270. Closest Binary Search Tree Value 最近的二叉搜索树的值

    Given a non-empty binary search tree and a target value, find the value in the BST that is closest t ...

  8. [LeetCode] 531. Lonely Pixel I 孤独的像素 I

    Given a picture consisting of black and white pixels, find the number of black lonely pixels. The pi ...

  9. .Net Core 定时任务TimeJob

    转载自:https://blog.csdn.net/u013711462/article/details/53449799 定时任务 Pomelo.AspNetCore.TimedJob Pomelo ...

  10. Android属性动画-简单实例

    1.ValueAnimator //在2000毫秒内,将值从0过渡到1的动画 ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); anim.setD ...