Class Loader也叫类加载器,是负责加载类的对象,jdk中的ClassLoader类是一个抽象类,只要提供一个类的二进制名称,类加载器会试图定位并生成类的数据对象,典型的加载策略是,转换类名为一个文件名称,然后从文件系统中读取类文件并加载该类。
每一个类对象都有一个getClassLoader()方法,该方法返回定义该类的classLoader。
数组对象不是由类加载器来创建,而是由java在运行时动态地创建。数组对象的getClassLoader()方法返回的是该数组元素类的classLoader,如果元素时基本类型,则无类加载器。
应用程序可定义ClassLoader类的子类,用于扩展在JVM中加载类的方式。
类加载器典型的使用场景是在安全管理器(security manager)表明安全的域中。
ClassLoader使用代理模式去发现和查找类和资源,加载器实例会将对类或资源的搜索委托给其父类加载器,然后再尝试查找类或资源本身。java虚拟机的内置类加载器称为“引导类加载器”,本身本身没有父类,但可以作为加载器实例的父类。
支持并发加载类的类加载器叫并发加载器,并发加载器需要在其初始化时通过registerAsParallelCapable()方法注册为并发加载器。需要注意的是,默认情况下,ClassLoader类被注册为并发加载器,其子类需要自行注册为并发加载器。在代理模式不是很严格的环境中,类加载器需要具有并行功能,否则类加载会导致死锁,因为在类加载过程中持有了加载器锁。
通常,java虚拟机从文件系统中加载类,例如,在unix环境中,虚拟机从定义在环境变量CLASSPATH的目录中加载类。
然而,有的类并不是来源与文件系统,而是通过其他的来源,比如,通过网络或者通过应用程序来构造。defineClass(String, byte[], int, int)方法能够将字节数组转换为类的实例对象。这种类实例可通过Class.newInstanse()方法创建。
被类加载器创建的对象,其构造器和方法可以引用其他的类,为了确定所引用的类,Java虚拟机调用该类的加载器的loadClass方法。
例如,引用程序可创建一个网络类加载器,从服务器端下载类文件,代码示例如下:
ClassLoader loader = new NetworkClassLoader(host, port);
Object main = loader.loadClass("Main", true).newInstance();
作为子类的网络类加载器,必须定义findClass方法和loadClassData方法,用以从网络上加载类,一旦它从网络上下载了组成类的字节,它就将通过defineClass创建一个类的实例。以下是一个示例的代码:
class NetworkClassLoader extends ClassLoader {
String host;
int port;
public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
}
private byte[] loadClassData(String name) {
// load the class data from the connection
...
}
}
任何一个传给ClassLoader的方法的参数,都是在java中定义该类的String类型的名称,合法的名称如下列所示:
"java.lang.String"
"javax.swing.JSpinner$DefaultEditor"
"java.security.KeyStore$Builder$FileBuilder$1"
"java.net.URLClassLoader$3$1"