从汇编码分析java对象的创建过程(推荐)

源码:

class T {
	int m = 8;
}
T t = new T();

汇编码:

0 new #2 <T>
3 dup
4 invokespecial #3 <T.<init>>
7 astore_1
8 return

new #2

申请内存,在堆里面创建一个新对象。

半初始化,新建对象中的m值是0。

dup

复制操作,因为invokespecial会消耗一份引用,所以先复制一份

invokespecial

4 invokespecial #3 <T.>

init是调用它的构造方法。

此时对象中的m值是8。

astore_1

将符号和对象建立关联,即t和堆中的对象。

其实很简单,今天看一个视频说了半天。。。

知识点补充:java对象的创建过程

大家都知道,java使用new 关键字进行对象的创建,但这只是从语言层次上理解了对象的创建,下边我们从jvm的角度来看看,对象是怎么被创建出来的,即对象的创建过程。

对象的创建大概分为以下几步:

1:检查类是否已经被加载;

2:为对象分配内存空间;

3:为对象字段设置零值;

4:设置对象头;

5:执行构造方法。

第一步,当程序遇到new 关键字时,首先会去运行时常量池中查找该引用所指向的类有没有被虚拟机加载,如果没有被加载,那么会进行类的加载过程,如果已经被加载,那么进行下一步,为对象分配内存空间;

第二步,加载完类之后,需要在堆内存中为该对象分配一定的空间,该空间的大小在类加载完成时就已经确定下来了,这里多说一点,为对象分配内存空间有两种方式:

(1)第一种是jvm将堆区抽象为两块区域,一块是已经被其他对象占用的区域,另一块是空白区域,中间通过一个指针进行标注,这时只需要将指针向空白区域移动相应大小空间,就完成了内存的分配,当然这种划分的方式要求虚拟机的对内存是地址连续的,且虚拟机带有内存压缩机制,可以在内存分配完成时压缩内存,形成连续地址空间,这种分配内存方式成为“指针碰撞”,但是很明显,这种方式也存在一个比较严重的问题,那就是多线程创建对象时,会导致指针划分不一致的问题,例如A线程刚刚将指针移动到新位置,但是B线程之前读取到的是指针之前的位置,这样划分内存时就出现不一致的问题,解决这种问题,虚拟机采用了循环CAS操作来保证内存的正确划分;

(2)第二种也是为了解决第一种分配方式的不足而创建的方式,多线程分配内存时,虚拟机为每个线程分配了不同的空间,这样每个线程在分配内存时只是在自己的空间中操作,从而避免了上述问题,不需要同步。当然,当线程自己的空间用完了才需要需申请空间,这时候需要进行同步锁定。为每个线程分配的空间称为“本地线程分配缓冲(TLAB)”,是否启用TLAB需要通过 -XX:+/-UseTLAB参数来设定。

第三步,分配完内存后,需要对对象的字段进行零值初始化,对象头除外,零值初始化意思就是对对象的字段赋0值,或者null值,这也就解释了为什么这些字段在不需要进程初始化时候就能直接使用;

第四步,这里,虚拟机需要对这个将要创建出来的对象,进行信息标记,包括是否为新生代/老年代,对象的哈希码,元数据信息,这些标记存放在对象头信息中,对象头非常复杂,这里不作解释,可以另行百度;

第五步,也就是最后一步,执行对象的构造方法,这里做的操作才是程序员真正想做的操作,例如初始化其他对象啊等等操作,至此,对象创建成功。

这里其实讲的比较粗浅,只是对象创建的大概过程,例如对象头、类的加载等等都是非常复杂的过程,我会在接下来解释。

总结

到此这篇关于从汇编码分析java对象的创建过程的文章就介绍到这了,更多相关从汇编码分析java对象的创建过程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • js+ajax处理java后台返回的json对象循环创建到表格的方法

    本文实例讲述了js+ajax处理java后台返回的json对象循环创建到表格的方法.分享给大家供大家参考,具体如下: //注:LO是表格的id: 需要自己创建表头, n行,9列的表格: var tab_id; function varify(cardinno) { tab_id=document.getElementById("Layer1"); displayDiv(); tab_id.style.display="none"; var url="get

  • 浅析Java中对象的创建与对象的数据类型转换

    Java:对象创建和初始化过程 1.Java中的数据类型     Java中有3个数据类型:基本数据类型(在Java中,boolean.byte.short.int.long.char.float.double这八种是基本数据类型).引用类型和null类型.其中,引用类型包括类类型(含数组).接口类型.     下列语句声明了一些变量: int k ; A a; //a是A数据类型的对象变量名. B b1,b2,-,b10000;// 假定B是抽象类或接口. String s; 注意:从数据类型

  • Java中五种不同方法的创建对象

    前言 作为Java开发者,我们每天都会创建大量的对象,但是,我们总是使用管理依赖系统(如Spring框架)来创建这些对象.其实还有其他方法可以创建对象,在接下来的文章中我会进行详细介绍. 1.使用new关键字 这是最常见的创建对象的方法,并且也非常简单.通过使用这种方法我们可以调用任何我们需要调用的构造函数. Employee emp1 = new Employee(); 0: new #19 // class org/programming/mitra/exercises/Employee 3

  • java教学笔记之对象的创建与销毁

    本课程的目标是帮你更有效的使用Java.其中讨论了一些高级主题,包括对象的创建.并发.序列化.反射以及其他高级特性.本课程将为你的精通Java的旅程提供指导. 1. 引言 在TIOBE 编程语言排名中,Sun 公司于1995年开发的Java语言是世界上使用最广泛的编程语言之一.作为一种通用编程语言,因为强大的工具包和运行时环境.简单的语法.丰富的平台支持(一次编写,到处运行)以及的异常活跃的社区支持,Java语言对软件开发工程师极具吸引力. 在这一系列的文章中,涵盖了Java相关的高级内容,因此

  • 从汇编码分析java对象的创建过程(推荐)

    源码: class T { int m = 8; } T t = new T(); 汇编码: 0 new #2 <T> 3 dup 4 invokespecial #3 <T.<init>> 7 astore_1 8 return new #2 申请内存,在堆里面创建一个新对象. 半初始化,新建对象中的m值是0. dup 复制操作,因为invokespecial会消耗一份引用,所以先复制一份 invokespecial 4 invokespecial #3 <T.

  • 深入理解JVM之Java对象的创建、内存布局、访问定位详解

    本文实例讲述了深入理解JVM之Java对象的创建.内存布局.访问定位.分享给大家供大家参考,具体如下: 对象的创建 一个简单的创建对象语句Clazz instance = new Clazz();包含的主要过程包括了类加载检查.对象分配内存.并发处理.内存空间初始化.对象设置.执行ini方法等. 主要流程如下: 1. 类加载检查 JVM遇到一条new指令时,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.解析和初始化过.如果没有,那必须先执

  • 理解Javascript_06_理解对象的创建过程

    简单的代码 我们先来看一段简单的代码: 复制代码 代码如下: function HumanCloning(){ } HumanCloning.prototype ={ name:'笨蛋的座右铭' } var clone01 = new HumanCloning(); alert(clone01.name);//'笨蛋的座右铭' alert(clone01 instanceof HumanCloning);//true HumanCloning.prototype = {}; alert(clon

  • 实例分析java对象中浅克隆和深克隆

    引言: 在Object基类中,有一个方法叫clone,产生一个前期对象的克隆,克隆对象是原对象的拷贝,由于引用类型的存在,有深克隆和浅克隆之分,若克隆对象中存在引用类型的属性,深克隆会将此属性完全拷贝一份,而浅克隆仅仅是拷贝一份此属性的引用.首先看一下容易犯的几个小问题 clone方法是Object类的,并不是Cloneable接口的,Cloneable只是一个标记接口,标记接口是用用户标记实现该接口的类具有某种该接口标记的功能,常见的标记接口有三个:Serializable.Cloneable

  • 实例分析java对象的序列化和反序列化

    引言: 序列化是将对象的状态信息转换为可以存储或传输的形式的过程,在序列化期间,对象将其带你过去的状态写入到临时或持储存区,反序列化就是重新创建对象的过程,此对象来自于临时或持久储存区. 序列化的作用: 就好比如存储数据到数据库,将一些数据持久化到数据库中,而有时候需要将对象持久化,虽然说将对象状态持久化的方式有很多,但是java给我们提供了一种很便捷的方式,那就是序列化,序列化可以实现对象到文件之间的直接转换,实现细节对我们隐藏. 具体的三种用途: •将对象的状态信息持久化保存到硬盘上 •将对

  • 了解Java线程池创建过程

    前言 最近在改进项目的并发功能,但开发起来磕磕碰碰的.看了好多资料,总算加深了认识.于是打算配合查看源代码,总结并发编程的原理. 准备从用得最多的线程池开始,围绕创建.执行.关闭认识线程池整个生命周期的实现原理.后续再研究原子变量.并发容器.阻塞队列.同步工具.锁等等主题.java.util.concurrent里的并发工具用起来不难,但不能仅仅会用,我们要read the fucking source code,哈哈.顺便说声,我用的JDK是1.8. Executor框架 Executor是一

  • Java虚拟机之对象创建过程与类加载机制及双亲委派模型

    目录 一.对象的创建过程: 1.对象的创建过程: 2.对象的访问方式: 二.类加载机制: 2.1.加载阶段: 2.2.验证阶段: 2.3.准备阶段: 2.4.解析阶段: 2.5.初始化: 2.5.1.类的主动引用: 2.5.2.类的被动引用: 2.5.3.()方法的特点: 三.类加载器与双亲委派模型: 3.1.JVM 的类加载器: 3.2.双亲委派模型: 3.2.1.双亲委派模型的工作原理: 3.2.2.双亲委派模型的优点: 3.3.类加载器源码:loadClass() 3.4.如何破坏双亲委派

  • Java基础之创建虚拟机对象的过程详细总结

    一.对象的创建 1.1 new 类名 虚拟机遇到一条new指令时,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已经被加载.解析和初始化过.如果没有,先执行相应的类加载过程. 1.2 分配内存 虚拟机为新生对象分配内存.对象所需内存大小在类加载完成后就可以确定,为对象分配内存等同于把一块确定大小的内存从Java堆中划分出来. (1)内存分配的方式有两种: ① 指针碰撞: java堆如果规整,一边是用过的内存,一边是空闲的内存,中间一个指针作为边界指示

  • 详解Java对象创建的过程及内存布局

    一.对象的内存布局 对象头 对象头主要保存对象自身的运行时数据和用于指定该对象属于哪个类的类型指针. 实例数据 保存对象的有效数据,例如对象的字段信息,其中包括从父类继承下来的. 对齐填充 对齐填充不是必须存在的,没有特别的含义,只起到一个占位符的作用. 二.对象的创建过程 实例化一个类的对象的过程是一个典型的递归过程. 在准备实例化一个类的对象前,首先准备实例化该类的父类,如果该类的父类还有父类,那么准备实例化该类的父类的父类,依次递归直到递归到Object类. 此时,首先实例化Object类

  • JAVA 对象创建与对象克隆

    目录 一.对象的4种创建方式 二.通过new创建对象 三.反射 四.克隆对象 浅拷贝 深拷贝 五.反序列化 六.补充 一.对象的4种创建方式 new 创建 反射 克隆 反序列化 二.通过new创建对象 一般情况下,对象通过new 关键字创建,首先会在堆上给对象分配空间,然后执行构造函数进行一系列的初始化,在分配的内存空间上为一众属性赋值:完成初始化后再将堆区对象的引用传递给栈区,最终参与程序的运行. 三.反射 调用Java.lang.Class或者java.lang.reflect.Constr

随机推荐