java虚拟机——对象的创建

原创 2016年08月28日 22:39:39

对象的创建

java是一种面向对象的语言,通常我们在创建对象时,大多是通过 "类名 变量名 = new 类名()" ,那么在底层的虚拟机中是怎么进行的呢?
(1)当虚拟机检测到一条new指令时,首先先检查当前创建的这个对象的类是否加载(通过方法区的常量池的符号引用来定位),如果这个类没有加载,则先去加载这个类(具体如何加载,我会在以后的章节继续写)。如果该类已经加载,则执行接下来的步骤。
(2)类加载后,便开始执行对象的创建,其实也就是为对象分配内存空间(一般在年轻代的Eden区进行分配,大对象直接进入老年代)。对象的所占大小在类加载后根据类中分区(在HotSpot虚拟机中对象的内存中有对象头,实际数据和对齐填充,具体接下来会讨论)便可知。
(3)在分配空间时虚拟机会根据不同情况采用不同方式:
1.指针碰撞:当java堆中的内存布局是绝对规整的,什么是绝对规整?就是所有存活的对象在堆区的一端,空闲的内存在另一端,那么在存活的对象和空闲空间的分隔点(临界点)放置了一个类似指针的指示器,当分配一个新对象的空间时,就是将指针向空闲空间方向移动和该对象大小相等的距离。
2.空闲列表:当java堆中的内存不是规整的,凌乱不堪,存活对象所占的内存和空闲内存相互交错,那么就不能使用指针碰撞的方法了。这时候虚拟机就必须需要一个列表来记录哪些位置的内存是空闲的,可以使用的,在创建对象的时候从列表中划分出一个足够大的空间给对象。
(4)那么问题来了,java堆什么时候是绝对规整的,什么时候相互交错的情况呢?
这就要由JVM的垃圾收集器来决定了。比如Serial收集器、ParNew收集器和Parallel Scavenge收集器等,在对内存进行一次回收后,便将堆内存压缩成存活对象一端、空闲内存另一端的规整情况(这几种属于年轻代的垃圾收集器,采用了复制算法)。采用空闲列表的情况,主要是由于虚拟机采用了类似于CMS这种收集器来进行回收内存,而CMS属于老年代的垃圾回收器,采用的是标记-清除算法
(5)但是现在又有一个问题出现了,如果在创建A对象时,指针(指示器)会改变位置,但此时对象B又同时正在创建,又使用了原来的指针,此时会出现线程不安全的情况,针对这种情况,JVM采用两种方式进行解决:
1.可能大家都会想到,使用同步进行处理。
2.使用本地线程分配缓存,简称TLAB(Thread Local Allocation Buffer),就是把分配内存的行为按照线程分别分配到各自之中进行,每个线程中预先在堆中分配一块空间,在线程创建对象,分配内存的时候,首先在缓存中进行分配,在缓存使用完时,使用同步进行新的TLAB的分配。
(6)在分配完内存之后,需要进行内存空间的初始化。这一步操作保证了我们在创建对象时,不需要像局部变量声明时那样必须指定初始值,可以直接使用对象中的成员变量。接下来虚拟机需要对对象进行一些必要的设置,比如:对象属于哪个类,HashCode,GC分代年龄等(这些信息都放在对象头)。
(7)在这之后,虚拟机已经将一个对象创建完成了,那么对于我们来说,仅仅一句话而已,对象才刚刚创建完成,所有字段都为各自类型的0值,所以一般在执行new指令之后就要执行<init>方法,将对象按照程序员的方式进行初始化。
至此,一个真正可用的对象创建完成。
接下来的章节会跟大家简单的讨论对象的内存布局和对象的访问方式。
如有错误,还望大家指正,谢谢

JAVA虚拟机:对象的创建过程

简要说明的话,Java对象的创建过程分为下面几步: 1、执行相关检查; 2、为对象分配内存,将分配到的内存空间都初始化为零值; 3、进行构造代码块和构造函数的初始化  下面详细介绍这几个步骤: 1、执...
  • wanggg2760
  • wanggg2760
  • 2016年07月15日 10:46
  • 673

Java对象在虚拟机中的创建过程

虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用。并且检查代表这个符号引用的类是否已经被加载、解析和初始化过。如果没有,那么必须先执行相应的类加载。在类加载...
  • fjse51
  • fjse51
  • 2017年01月06日 16:34
  • 473

Java对象在哪里创建

对象在哪里创建?    Java数据存储在哪里? 1,寄存器,存取速度最快,在cpu里面 2,堆栈,地址引用放栈里,对象放堆里,Java中的引用可以理解为c中的指针 3,堆,方面灵活但...
  • SR2017
  • SR2017
  • 2017年04月08日 18:38
  • 478

Java对象与JVM(一) Java对象在Java虚拟机中的创建过程

下面我们详细了解Java程序中new一个普通对象时,HotSpot虚拟机是怎么样创建这个对象的,包括5个步骤:相应类加载检查过程、在Java堆中为对象分配内存、分配后内存初始化为零、对对象进行必要的设...
  • tjiyu
  • tjiyu
  • 2016年12月29日 07:47
  • 3480

虚拟机创建对象的过程探索

对象的创建Java是面向对象的语言,一般情况下创建对象都是通过new来创建的(少数情况是通过克隆和反射来发生的)。那么虚拟机中,对new创建出来的对象时,是要走什么过程的呢?首先是寻找类类型的过程: ...
  • ZW_KK
  • ZW_KK
  • 2017年03月24日 07:50
  • 231

Java虚拟机(四)——对象的创建、存储和定位

对象的创建  Java是一门面向对象的编程语言,Java 程序运行过程中无时无刻都有对象被创建出来,在语言层面上,创建对象(例如克隆,反序列化)通常仅仅是一个new关键字而已,例如下面的语句。Obje...
  • ylyg050518
  • ylyg050518
  • 2016年08月26日 00:16
  • 739

java类中创建一个自身的静态对象,如何理解不会无限创建导致堆溢出

public class MySharedObject { //static variable pointing to instance of MySharedObject pu...
  • THMAIL
  • THMAIL
  • 2017年04月26日 10:15
  • 402

《深入理解java虚拟机》读书笔记:Java对象的内存布局

一个int类型4占4个字节的内存,一个byte一个字节。但是他们的封装类型Integer,Byte对象内存损耗还是一样的吗?并不是,而且差距十分大。     HotSpot虚拟机中,一个普通的Java...
  • bruce128
  • bruce128
  • 2016年03月30日 21:46
  • 1672

java创建一个对象获取泛型的class

孔浩老师视频笔记。  private Class clz;          @SuppressWarnings("unchecked")   public Class getClz(...
  • TianHuMin
  • TianHuMin
  • 2017年02月09日 14:51
  • 1259

eclipse启动创建java 虚拟机失败

刚开始玩安卓开发的时候,打开开发包就出了这么个错误,网上找了一下,将自己的eclipse.ini改成如下式样: -startup plugins/org.eclipse.equinox.launche...
  • widenstage
  • widenstage
  • 2017年04月05日 09:13
  • 1427
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java虚拟机——对象的创建
举报原因:
原因补充:

(最多只允许输入30个字)