深入理解JVM(二)--对象的创建
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(二)--对象的创建的更多相关文章
- 深入理解JVM(4)——对象的创建和访问
1.对象的创建 在语言层面上,创建对象(例如克隆,反序列化)通常仅仅是一个new关键字而已. 在虚拟机中,对象(文中讨论的对象限于普通 Java 对象,不包括数组和 Class 对象等)的创建过程如下 ...
- JVM中对象的创建过程
JVM中对象的创建过程如以下流程图中所示: 对其主要步骤进行详细阐述: 为新生对象分配内存: 内存的分配方式: 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存在另一边, ...
- 深入理解JVM(二)Java内存区域
2.1 C.C++内存管理是由开发人员管理,而Java则交给了JVM进行自动管理 2.2 JVM运行时数据区:方法区.堆(运行时线程共享),虚拟机栈.本地方法栈.程序计数器(运行时线程隔离,私有) 1 ...
- JVM(二) 对象存活判断和垃圾回收算法
对象的创建 概述 下面简要介绍创建对象的几个重要步骤 : 检查能否在常量池定位到一个类的符号引用,并检查这个符号代表的类是否已被加载,解析和初始化过.如果没有则执行类加载的操作.(即是说对象的引用放在 ...
- 深入理解java虚拟机---对象的创建过程(八)
1.对象的创建过程 由于类的加载是一个很复杂的过程,所以这里暂时略过,后面会详细讲解,默认为是已加载过的类.着重强调对象的创建过程. 注意: 最后一步的init方法是代码块和构造方法. 以上是总图,下 ...
- 深入理解JVM(三) -- 对象的内存布局和访问定位
一 对象的内存布局: 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding). HotSpot的对 ...
- JVM(三) 对象的创建过程
1.对象的创建过程 1.1 . 给对象分配内存 对象的内存分配有两种方式,一种是指针碰撞另外一种是空闲列表的方式,堆是否规整由我们垃圾回收器来决定的 ,如果垃圾回收带有我们的压缩算法,那么他会规整的分 ...
- 理解JVM之对象的生命周期
1.对象的创建 1) 当虚拟机遇到一条new的指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载,解析和初始化过. 2) 在类加载检查通 ...
- 深入理解JVM(二)--垃圾收集算法
一. 概述 说起垃圾收集(Garbage Collection, GC), 大部分人都把这项技术当做Java语言的伴随生产物. 事实上, GC的历史远远比Java久远, 1960年 诞生于MIT的Li ...
随机推荐
- 思科 DHCP服务器配置及DHCP中继
思路: 1.配置 DHCP 客户端 确保每个 PC 为 自动获取IP地址的方式: 2.配置 SW1 # 创建 VLAN 10 , 20 # 将相关的端口,放入到对应的 VLAN : # 配置交换机之间 ...
- 【软工实践】Beta冲刺(3/5)
链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 新增数据分析展示等功能API 服务器后端部署,API接口的beta版实现 展示 ...
- JdkDynamicAopProxy 拦截器链的获得与递归执行
JdkDynamicAopProxy类的invoke方法 1.获得拦截器链 List<Object> chain = this.advised.getInterceptorsAndDyna ...
- Java3d 案例程序
今天偶尔翻出了很久以前写的java3d程序,很怀念曾经探索java3d解析.渲染ifc数据的日子 package com.vfsd.test0621; import java.applet.Apple ...
- saltstack执行state.sls耗时长的坑
一直用的 jenkins + saltstack 自动化构建发布项目,一共也就不超过20台服务器,奈何运行时间越来越慢,并且负载越来越高(这里大部分都是使用state模块),但是不用state模块效率 ...
- Swift编码总结4
1.swift @discardableResult 声明: swift正常的方法如果有返回值的话,调用的时候必须有一个接收方,否则的话编译器会报一个警告,如果在方法前加上 @discardableR ...
- [LeetCode] 500. Keyboard Row 键盘行
Given a List of words, return the words that can be typed using letters of alphabet on only one row' ...
- [计算机视觉][神经网络与深度学习]SSD安装及其训练教程
SSD的安装 在home目录下,获取SSD的代码,下载完成后有一个caffe文件夹 git clone https://github.com/weiliu89/caffe.git cd caffe g ...
- k8s-RC副本机制
一.libeness probe的三种检测机制 HTTP GET:对容器的IP(指定的端口和路径)执行HTTP GET请求,收到响应并返回状态码不代表错误(2xx/3xx),成功 TCP socket ...
- jquery trigger使用方法
jquery trigger使用方法比方说写了下面点击事件 采用trigger 要触发他<pre> $('.biaoqian_ula').on('click',function () { ...