Java类的加载Java类的加载是由类加载器来完成的。 普通来说, 类加载器分成两类:启动类加载器(bootstrap)和用户自定义的类加载器(user-defined)。 两者的区别在于启动类加载器是由JVM的原生代码实现的, 而用户自定义的类加载器都继承自Java中的java. lang. ClassLoader类。 在用户自定义类加载器的部分, 普通JVM都会提供一些根本实现。 应用顺序的开发人员也可以依据需要编写自己的类加载器。 JVM中最常运用的是零碎类加载器(system), 它用来启动Java应用顺序的加载。 通过java. lang. ClassLoader的getSystemClassLoader()方法可以获取到该类加载器对象。类加载器需要完成的最终功能是定义一个Java类, 即把Java字节代码转换成JVM中的java. lang. Class类的对象。 但是类加载的进程并不是这么简单。 Java类加载器有两个比较重要的特征:层次组织构造和代理形式。 层次组织构造指的是每个类加载器都有一个父类加载器, 通过getParent()方法可以获取到。 类加载器通过这种父亲-后代的方式组织在一起, 构成树状层次构造。 代理形式则指的是一个类加载器既可以自己完成Java类的定义任务, 也可以代理给其它的类加载器来完成。由于代理形式的存在, 启动一个类的加载进程的类加载器和最终定义这个类的类加载器能够并不是一个。 前者称为初始类加载器, 然后者称为定义类加载器。 两者的关联在于:一个Java类的定义类加载器是该类所导入的其它Java类的初始类加载器。 比方类A通过import导入了类 B, 那么由类A的定义类加载器负责启动类B的加载进程。普通的类加载器在尝试自己去加载某个Java类之前, 会首先代理给其父类加载器。 当父类加载器找不到的时候, 才会尝试自己加载。 这个逻辑是封装在java. lang. ClassLoader类的loadClass()方法中的。 普通来说, 父类优先的战略就足够好了。 在某些状况下, 能够需要采取相反的战略, 即先尝试自己加载, 找不到的时候再代理给父类加载器。这种做法在Java的Web容器中比较常见, 也是Servlet规范推荐的做法。 比方, Apache Tomcat为每个Web应用都提供一个独立的类加载器, 运用的就是自己优先加载的战略。 IBM WebSphere Application Server则允许Web应用选择类加载器运用的战略。类加载器的一个重要用途是在JVM中为相同名称的Java类创立隔离空间。 在JVM中, 判断两个类是否相同, 不仅是依据该类的二进制名称, 还需要依据两个类的定义类加载器。 只有两者完全一样, 才认为两个类的是相同的。 因此, 即便是异样的Java字节代码, 被两个不同的类加载器定义之后, 所失掉的Java类也是不同的。 假如试图在两个类的对象之间停止赋值操作, 会抛出java. lang. ClassCastException。这个特性为异样名称的Java类在JVM中共存创造了条件。 在实际的应用中, 能够会要求同一名称的Java类的不同版本在JVM中可以同时存在。 通过类加载器就可以满足这种需求。 这种技术在OSGi中失掉了广泛的应用。