过程
总的来说可以分为两步(对于第一次创建的对象来说):
- 加载并初始化
- 创建对象
类加载检测
Java 在初始化对象之前,会对对象所属的类进行检查,看该类有无被加载到JVM中,如果没有就会通过类的全限定名和类加载器加载到JVM中去,再进行类的创建过程,类的加载过程如下:
这里需要提到一个JVM的类加载模型:双亲委派模型:如果一个类加载器收到了类加载的请求,它不会自己去尝试加载这个类,而是会将请求委派给父类加载器去完成(父类再去委派它的父类),每一级都是向上委派,父类无法加载时,子加载器才会去自己完成加载
这样做的好处是:保证了类的全局唯一性,有多个限定名相同的类时,保证只有一个类加载到JVM中(方法区-元空间)
具体的类加载过程如下图:
从上可以看到,类加载的时候就已经完成了:
- 静态变量的赋值
- 静态代码块的执行
- 常量的赋值
这些都是属于类的属性,只会加载一次
类加载完成后,会进行对象的创建过程
创建对象
在堆区为对象分配内存空间
对象都分配在堆内存中,所以需要先分配内存初始化对象
包括对实例变量的赋值,代码块的执行,构造方法的执行(先父类后子类)将对象的堆地址赋值给栈中的引用类型
补充
综上所述,代码的执行顺序也一目了然:
- 父类静态变量
- 父类静态代码块
- 子类静态变量
- 子类静态代码块
- 父类普通变量
- 父类普通代码块
- 父类构造方法
- 子类普通变量
- 子类普通代码块
- 子类构造方法
以上就完成了对一个对象的new过程
Others
类加载器:
实际上JVM只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),另一种是其他所有的类加载器(摘抄自《深入理解Java虚拟机》)实际上,随着JIT(即时编译技术)的发展以及逃逸分析技术,对象都分配在堆中已经变得没这么绝对,也有可能在栈上分配(方法中的变量,并没有作为参数传递到其他方法,或在方法外有引用)