深入理解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 ...
随机推荐
- 【Excel】定位条件快速将空值替换为指定值
现有如下表格,表格中存在一些空值,如下图: 目的 将上图的空值全部赋值为100,实现后效果如下: 实现步骤 1.选中数字区域,按CTRL+G 2.点击[定位条件]后,选择[空值]后[确定] 3.在编辑 ...
- 关于SpringCloud、SpringBoot简单讲解
什么是Spring Boot 用我的话来理解,Spring Boot就是整合了框架的框架,它让一切依赖都变得有序简单,你不用操心A.jar是什么版本,又依赖哪些版本的jar,它默认配置了很多框架的使 ...
- from bs4 import BeautifulSoup 引入需要安装的文件和步骤
调用beautifulsoup库时,运行后提示错误: ImportError: No module named bs4 , 意思就是没有找到bs4模块,所以解决方法就是将bs4安装上,具体步骤如下: ...
- Spring Boot-IntelliJ IDEA搭建SpringBoot
点击create new project 点击next 这里基本都已经自动生成了,简单介绍下: Name:项目名称 Type:我们是Maven构建的,那么选择第一个Maven Project Pack ...
- canvas api 速记
基本骨骼 <canvas id="canvas" width=1000 height=1000 style="border: 1px black dotted&qu ...
- Android近场通信---NFC基础转)
Android近场通信---NFC基础(一)(转) 本文介绍在Android系通过你所能执行的基本任务。它解释了如何用NDEF消息格式来发送和接收NFC数据,并且介绍了支持这些功能的Android框架 ...
- 以太坊公链Geth同步
1.安装所需基础工具 yum update -y && yum install git wget bzip2 vim gcc-c++ ntp epel-release nodejs c ...
- Robot Framwork关键字驱动+RedwoodHQ安装
一.Robot Framwork介绍 Robot Framwork是一款python编写的功能框架.具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行. ...
- Vue 引入 .md 文件,解析markdown语法
module.exports = { chainWebpack: config => { config.module .rule('md') .test(/\.md$/) .use('html- ...
- 【414 error】nginx GET请求过长导致414错误
server{ ... } 在上面一段配置中添加如下两行 client_header_buffer_size 5120k; large_client_header_buffers 5120k; 并重启 ...