一、关键字new概述
1.Java关键字new是一个运算符。与+、-、*、/等运算符具有相同或类似的优先级。
2.创建一个Java对象需要三部:声明引用变量、实例化、初始化对象实例。
3.实例化:就是“创建一个Java对象”-----分配内存并返回指向该内存的引用。
4.初始化:就是调用构造方法,对类的实例数据赋初值。
5.Java对象内存布局:包括对象头和实例数据。如下图:
对象头:它主要包括对象自身的运行行元数据,比如哈希码、GC分代年龄、锁状态标志等;同时还包含一个类型指针,指向类元数据,表明该对象所属的类型。
实例数据:它是对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身拥有的字段)。
在hotSpot虚拟机中,对象在内存中的布局可以分成对象头、实例数据、对齐填充三部分。
对齐填充:它不是必要存在的,仅仅起着占位符的作用。
6.Object obj = new Object();
那“Object obj”这部分的语义将会反映到Java栈的本地变量表中,作为一个reference类型数据出现。而“new Object()”这部分的语义将会反映到Java堆中,形成一块存储了Object类型所有实例数据值(Instance Data,对象中各个实例字段的数据)的结构化内存,根据具体类型以及虚拟机实现的对象内存布局(Object Memory Layout)的不同,这块内存的长度是不固定的。另外,在Java堆中还必须包含能查找到此对象类型数据(如对象类型、父类、实现的接口、方法等)的地址信息,这些类型数据则存储在方法区中。
---------------------------------------------------------
二、内存分配原理
1.在Java语法层面上创建一个对象,使用一个简单的new关键字即可,但是在JVM中细节的实现相当复杂,而且过程繁多。
2.当Java语法层面使用new关键字创建一个Java对象时,JVM首先会检查相对应的类是否已经成功经历加载、解析和初始化等步骤;当类完成装载步骤之后,就已经完全确定出创建对象实例时所需的内存空间大小,才能对其进行内存分配,以存储所生成的对象实例。
3.实例化之后,进行初始化(初始化对象头和实例数据)。
4.内存分配方式有:指针碰撞(Bump the Pointer)、快速分配策略、空闲列表(Free List)。
5.在并发环境下从堆中划分内存空间是非线程安全的,new运算符具有-------数据操作的原子性;也就是说创建一个Java对象分配内存,要么所有步骤都成功,返回对象的引用,要么回归到创建之前的内存状态,返回为NULL。
6.通过new创建一个Java对象,如果成功则返回这个对象的引用,开发者不可直接操作对象实例,需要通过这个引用“牵引”。
看完这篇文章,相信你对Java关键字new及Java对象的完整创建过程有了更深的认识,就不会只停留在new一个对象就完了。
---------------------