Java 类加载过程
1. 加载. 把.class二进制文件读入内存。
2. 链接
- 验证。 验证正确性,和我们自己写函数要验证入参一样,必须验证该类为正确以后才能继续。否则会造成程序崩溃
- 准备。分配静态变量内存空间
- 解析。 解析出类中符号引用。比如函数的符号应用。
3.初始化
Java类被初始化的条件
1. 被调用new, put static, get static 或者invoke static指令。通俗讲就是调用new, 设置静态变量,获取静态变量或者调用静态函数。
2. Reflect反射。比方说Class.forname(xxx)
3. 调用子类时,父类需要提前初始化。
4. Main函数的类也会被初始化。
如下示例只会输出,子类不会被初始化
super class initialization
128
128
public class Initilization {
public static void main(String[] args) {
System.out.println(subClass.value);
}
}
class superClass
{
public static int value =128;
static
{
System.out.println("super class initialization");
}
}
class subClass extends superClass
{
static
{
System.out.println("sub class initialization");
}
}
如下示例不会有输出,数组的初始化只是初始化了指针而已。
public class Initilization {
public static void main(String[] args) {
//System.out.println(subClass.value);
superClass arr[]= new superClass[10];
}
}
class superClass
{
public static int value =128;
static
{
System.out.println("super class initialization");
}
}
class subClass extends superClass
{
static
{
System.out.println("sub class initialization");
}
}
如下代码不会输出const class initialization. 常量的初始化已经在准备阶段完成。
public class Initilization {
public static void main(String[] args) {
//System.out.println(subClass.value);
//superClass arr[]= new superClass[10];
System.out.println(constClass.msg);
}
}
class superClass
{
public static int value =128;
static
{
System.out.println("super class initialization");
}
}
class subClass extends superClass
{
static
{
System.out.println("sub class initialization");
}
}
class constClass
{
static
{
System.out.println("const class initialization");
}
public final static String msg = "const class final static variable has no relationship with original class";
}
Java类加载器
1. Bootstrap ClassLoader : 将存放于<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如 rt.jar 名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用
2. Extension ClassLoader : 将<JAVA_HOME>\lib\ext目录下的,或者被java.ext.dirs系统变量所指定的路径中的所有类库加载。开发者可以直接使用扩展类加载器。
3. Application ClassLoader : 负责加载用户类路径(ClassPath)上所指定的类库,开发者可直接使用。
2. Extension ClassLoader : 将<JAVA_HOME>\lib\ext目录下的,或者被java.ext.dirs系统变量所指定的路径中的所有类库加载。开发者可以直接使用扩展类加载器。
3. Application ClassLoader : 负责加载用户类路径(ClassPath)上所指定的类库,开发者可直接使用。
Java类加载的时候总是先试图让自己的父加载器加载,如果不成功再自己加载。
这主要是由Java的单根结构决定,让每一个确定的类在虚拟机中都有唯一的解释。