过程

总的来说可以分为两步(对于第一次创建的对象来说):

  1. 加载并初始化
  2. 创建对象

类加载检测

Java 在初始化对象之前,会对对象所属的类进行检查,看该类有无被加载到JVM中,如果没有就会通过类的全限定名和类加载器加载到JVM中去,再进行类的创建过程,类的加载过程如下:

这里需要提到一个JVM的类加载模型:双亲委派模型:如果一个类加载器收到了类加载的请求,它不会自己去尝试加载这个类,而是会将请求委派给父类加载器去完成(父类再去委派它的父类),每一级都是向上委派,父类无法加载时,子加载器才会去自己完成加载

这样做的好处是:保证了类的全局唯一性,有多个限定名相同的类时,保证只有一个类加载到JVM中(方法区-元空间)

具体的类加载过程如下图:

New一个对象的过程(实例化过程) - 图1

从上可以看到,类加载的时候就已经完成了:

  1. 静态变量的赋值
  2. 静态代码块的执行
  3. 常量的赋值

这些都是属于类的属性,只会加载一次

类加载完成后,会进行对象的创建过程

创建对象

  1. 在堆区为对象分配内存空间
    对象都分配在堆内存中,所以需要先分配内存

  2. 初始化对象
    包括对实例变量的赋值,代码块的执行,构造方法的执行(先父类后子类)

  3. 将对象的堆地址赋值给栈中的引用类型

补充

综上所述,代码的执行顺序也一目了然:

  1. 父类静态变量
  2. 父类静态代码块
  3. 子类静态变量
  4. 子类静态代码块
  5. 父类普通变量
  6. 父类普通代码块
  7. 父类构造方法
  8. 子类普通变量
  9. 子类普通代码块
  10. 子类构造方法

以上就完成了对一个对象的new过程

Others

  • 类加载器:
    实际上JVM只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),另一种是其他所有的类加载器(摘抄自《深入理解Java虚拟机》)

  • 实际上,随着JIT(即时编译技术)的发展以及逃逸分析技术,对象都分配在堆中已经变得没这么绝对,也有可能在栈上分配(方法中的变量,并没有作为参数传递到其他方法,或在方法外有引用)