java程序在运行前需要先编译成class文件,java类初始化的时候会调用java.lang.ClassLoader加载类字节码,ClassLoader会调用JVM的native方法来定义一个java.lang.Class实例。

一切的java类都必须经过JVM加载后才能运行。在JVM类加载器中最顶层的是Bootstrap ClassLoader(引导类加载器)、Extension ClassLoader(拓展类加载器)、App ClassLoader(系统类加载器)。

App ClassLoader是默认的类加载器。

ClassLoader类有如下核心方法:

  • loadClass(加载指定类)
  • findClass(查找指定类)
  • findLoadedClass(查找JVM已经加载的类)
  • defineClass(定义一个类)
  • resolveClass(链接指定类)

常用的类动态加载方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package one;

public class One {
public static void main(String[] args) throws ClassNotFoundException{
//第一种会默认初始化被加载类的静态属性和方法
//Class<?> cl=Class.forName("one.One");

//第二种不会初始化类方法
//ClassLoader cll=One.class.getClassLoader();
//cll.loadClass("one.One");
}
static class Hello{
public void say(){
System.out.println("Hello World");
}
}
}

加载流程

  1. 调用loadClass方法加载类。
  2. 调用findLoadedClass方法检查类是否已经初始化,如果JVM已初始化该类则直接返回类对象。
  3. 如果创建当前ClassLoader时传入了父类加载器就使用父类加载器加载类,否则用JVM的BootStrap ClassLoader加载。
  4. 如果还是无法加载就用自身的findClass方法尝试加载类。
  5. 如果当前的ClassLoader没有重写findClass方法,则直接返回类加载失败异常。如果当前类加载器重写了findClass方法并通过传入的类名找到了对应的类字节码,就调用defineClass方法去JVM中注册该类。
  6. 如果调用loadClass的时候传入的resolve参数为true,那么还需要调用resolveClass方法链接类,默认为false。
  7. 返回一个被JVM加载后的java.lang.Class类对象。