| Java在需要使用类的时候,才会将类载入,Java的类载入是由类载入器(Class loader)来达到的,默认上,在程序启动之后,主要会有三个类载入器:Bootstrap Loader、ExtClassLoader与AppClassLoader。 Bootstrap Loader是由C++撰写而成,默认上它负责搜寻JRE所在目录的classes或lib目录下的.jar文件中(例如rt.jar)是否有指定的类并载入(实际上是由系统参数sun.boot.class.path指定);默认上ExtClassLoader负责搜寻JRE所在目录的lib/ext 目录下的classes或.jar中是否有指定的类并载入(实际上是由系统参数java.ext.dirs指定);AppClassLoader则搜寻 Classpath中是否有指定的classes并载入(由系统参数java.class.path指定)。 Bootstrap Loader会在JVM启动之后载入,之后它会载入ExtClassLoader并将ExtClassLoader的parent设为Bootstrap Loader,然后BootstrapLoader再载入AppClassLoader,并将AppClassLoader的parent设定为 ExtClassLoader。 在载入类时,每个类载入器会先将载入类的任务交由其parent,如果parent找不到,才由自己负责载入,如果自己也找不到,就会丢出 NoClassDefFoundError。 每一个类被载入后,都会有一个Class的实例来代表它,每个Class的实例都会记得是哪个ClassLoader载入它的,可以由Class的getClassLoader()取得载入该类的ClassLoader。 来撰写一个简单的程序测试类载入器,首先写一个测试类:
public class ClassLoaderTest {
将这个类先放在Classpath的路径下,然后撰写以下的程序:
public class ClassLoaderDemo {
执行程序之后,会出现以下的讯息:
这表示ClassLoaderTest类是由sun.misc.Launcher产生的AppClassLoader所载入,而 AppClassLoader的parent是ExtClassLoader(AppClassLoader与ExtClassLoader都是内部类 别),ExtClassLoader的parent则是Bootstrap Loader,最后一个显示null并不是表示没有ClassLoader,而是因为Bootstrap Loader是由C++撰写而成,在Java中并没有一个实际代表它的类,因而没有类实例来表示Bootstrap Loader。 如果把ClassLoaderTest的class文件放到JRE目录下的lib/ext/classes下,并重新执行程序,您会看到以下的讯息:
这次ClassLoaderTest是由ExtClassLoader找到了,由于Bootstrap Loader并没有代表它的实例,所以是null,因而最后一行试图再使用getParent()时会出现NullPointException。 如果您将ClassLoaderTest的class文件移至JRE目录下的classes目录下,执行程序的话会出现以下的讯息:
出现null讯息,表示这次ClassLoaderTest是由Bootstrap Loader载入的。 这边只是对类载入器作个简单的描述,想更深入了解类载入器,可引用这篇 深入类载入器。 |