java类加载机制-类定义中new如何理解
package my.test.jvm;
public class testJVM2 {
void print1(A2 a){
System.out.println("void print1: ");
}
static void print2(A2 a){
System.out.println("static void print2: ");
}
public static void main(String[] args) {
// A2 src;
A2 src=new A2();
// new testJVM2().print1(src);
}
}
class A2{
//public A2 e=new A2(5);stack overflow error
public static A2 d=new A2(4);
public static final A2 a=new A2(1);
public static final A2 b=new A2(2);
public static final A2 c=new A2(3);
A2(){
System.out.println("constructor A2: ()");
}
A2(int i){
System.out.println("constructor A2: "+i);
}
}
我这么描述一下问题吧:编译运行这个文件,首先进入main函数,new A2()的时候进入A2的类加载过程,前几步忽略,在最后一部类初始化过程中,排除abc(因为它们在准备阶段完成进入常量池),讨论d的话,d的语句走到new A2(4)的时候,此时A2类的类加载过程尚未完成(因为最后一步尚在进行之中),那么这时是否会启动一个新的类加载过程?如果未启动,那这个过程又是如何进行的?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在运行 java 程序的时候,每个类只被加载一次。不可能重复加载的。所以也就不存在题主说的递归了。
推荐先了解一下JVM虚拟机中内存
AVA对象实例化过程中,主要使用到的包括虚拟机栈,JAVA堆和方法区。
JAVA文件经编译之后首先会被加到到JVM方法区,JVM方法区中很重要的一个部分是运行时常量池——用以存储class文件类的版本、字段、方法、接口等描述信息和编译期间的常量和静态变量。
JAVA对象真正进行实例化的地方在JAVA堆和虚拟机栈中,Object A = New Object();在实际内存中,A其实相当于我们给Ojbect这个类的实现起的一个名字,在面向对象编程中,就像狗是属于一类动物,但是特指的那一条狗我们会给他起一个名字用以区分一样。Object用以标记A是属于这个类,而A是特指Object的一个具体实现,而New Object就相当于对这个类创建一个具体实现。所以我们可以了解到,一个对象他首先必须可以指明所属的类,其次它还必须能指明他所特指的哪一个具体实现。
对应的有两种实现方式:
1.句柄访问对象
2.直接指针访问对象
直接指针访问对象
HotSpot采用的是第二种实现方式。
Class的装载包括3个步骤:加载(loading),连接(link),初始化(initialize)
加载
根据上图所示,我们不难理解,当一个对象进行实例化的时候,JVM会根据所需对象类型在JAVA堆中划分内存区,并生成指向方法区对象数据类型的指针用以标识对象。
链接
虚拟机栈中的本地变量表(也有称为局部变量表)中指针指向JAVA堆中划分好的内存区域。JAVA虚拟机采用动态链接方式,只有编译后的class文件并未存储最终方法在内存的表现形式。
初始化
初始化实际上是对class文件中的初始化方法进行调用,其核心还是虚拟机栈中栈帧的一次POP/PUSH。相当于对类中的对象进行一次同样的装载过程。
至此,一个对象完整的实例化过程就全部介绍完毕。
类内部初始化顺序为 静态域->非静态域->构造方法
推荐看一下:
【JAVA笔记——道】对象生命周期详解
【JAVA笔记——道】Class初始化理解
是不是把类加载和对象初始化搞混了?
楼主是不是想的太高深了?实例化和声明定义是2个概念和阶段。
A2有几个静态的成员变量在声明时实例化,而类的实例化过程是通过构造函数完成的。
这里看上去出现了嵌套,其实不然。编译器可以在编译实例化语句的时候申明指令跳转,跳转地址在二次编译的时候确定。
这样,类申明阶段,在实例化a,b,c,d的时候编译程序会跳转到A2(int i)的构造方法程序块。
在类实例化阶段的时候跳转到A()构造方法。
说白了就是在不同阶段调用对应的构造方法而已,没有楼主以为的循环嵌套。
类加载时,对于静态变量和构造方法的加载顺序不一样吧。构造方法本质也是静态方法。
也不怎么懂,先占个板凳