JVM类的加载
JVM是Java虚拟机,每当一个Java程序运行时都会有一个JVM实例,只有当程序结束运行后这个JVM才退出。Jvm实例通过调用MAIN函数来启动一个JAVA 程序,也就是找到main函数然后进行相关类的加载。
类的加载主要有三个步骤:
1.装载。根据查找路径找到相应的class文件,然后导入。
2.链接。具体再分为三个步骤
(1)检查 检查class文件的正确性
(2)准备 给类中的静态变量分配空间
(3)解析 将符号引用转换为直接引用(可选)
3.初始化。对静态变量和静态代码块块执行初始化工作
具体的举个例子来说明一下(代码来自互联网)
class
Insect
{
private
int
i
=9;
protected
int
j
;
Insect()
{
System.
out
.println(
"i="
+
i
+
" j="
+
j
);
j
= 39;
}
private
static
int
x
= printInit(
"static Insect.x initialized"
);
static
int
printInit(String
s
)
{
System.
out
.println(
s
);
return
47;
}
}
public
class
Beetle
extends
Insect
{
private
int
k
= printInit(
"Bettle.k initialized"
);
public
Beetle()
{
System.
out
.println(
"k="
+
k
+
" j="
+
j
);
}
private
static
int
x2
= printInit(
"static beetle initialized"
);
public
static
void
main(String[]
args
)
{
System.
out
.println(
"bettle constructor"
);
Beetle
b
=
new
Beetle();
}
}
运行结果:
对于这个java文件,在运行时程序一开始试图找到Beetle的main方法然后加载Beetle的class文件,在class文件加载的过程中,发现这个Beetle类继承了另外一个类Insect所以程序需要先加载Insect的class文件。在加载过程中会执行类加载的三个步骤,遇到静态变量惊醒初始化,之后再加载自身的class文件,同样遇到static修饰的也会初始化。所以会先输出
static Insect.x initialized
static beetle initialized
此时如果Insect类继承了另外一个类时,以同样的方法类推。
总结类初始化的顺序:
父类静态变量,父类静态代码块,子类静态变量,子类静态代码块,父类非静态变量,父类非静态代码块,父类构造函数,子类非静态变量,子类非静态代码块,子类构造函数。
ps: 如果去掉main函数,则会出现如下结果:
JVM类的加载
JVM是Java虚拟机,每当一个Java程序运行时都会有一个JVM实例,只有当程序结束运行后这个JVM才退出。Jvm实例通过调用MAIN函数来启动一个JAVA 程序,也就是找到main函数然后进行相关类的加载。
类的加载主要有三个步骤:
1.装载。根据查找路径找到相应的class文件,然后导入。
2.链接。具体再分为三个步骤
(1)检查 检查class文件的正确性
(2)准备 给类中的静态变量分配空间
(3)解析 将符号引用转换为直接引用(可选)
3.初始化。对静态变量和静态代码块块执行初始化工作
具体的举个例子来说明一下(代码来自互联网)
class
Insect
{
private
int
i
=9;
protected
int
j
;
Insect()
{
System.
out
.println(
"i="
+
i
+
" j="
+
j
);
j
= 39;
}
private
static
int
x
= printInit(
"static Insect.x initialized"
);
static
int
printInit(String
s
)
{
System.
out
.println(
s
);
return
47;
}
}
public
class
Beetle
extends
Insect
{
private
int
k
= printInit(
"Bettle.k initialized"
);
public
Beetle()
{
System.
out
.println(
"k="
+
k
+
" j="
+
j
);
}
private
static
int
x2
= printInit(
"static beetle initialized"
);
public
static
void
main(String[]
args
)
{
System.
out
.println(
"bettle constructor"
);
Beetle
b
=
new
Beetle();
}
}
运行结果:
对于这个java文件,在运行时程序一开始试图找到Beetle的main方法然后加载Beetle的class文件,在class文件加载的过程中,发现这个Beetle类继承了另外一个类Insect所以程序需要先加载Insect的class文件。在加载过程中会执行类加载的三个步骤,遇到静态变量惊醒初始化,之后再加载自身的class文件,同样遇到static修饰的也会初始化。所以会先输出
static Insect.x initialized
static beetle initialized
此时如果Insect类继承了另外一个类时,以同样的方法类推。
总结类初始化的顺序:
父类静态变量,父类静态代码块,子类静态变量,子类静态代码块,父类非静态变量,父类非静态代码块,父类构造函数,子类非静态变量,子类非静态代码块,子类构造函数。
ps: 如果去掉main函数,则会出现如下结果: