摘要:本文主要介绍类加载器、类的唯一性、启动类加载器、拓展类加载器、应用程序类加载器。
内容目录:
1.类加载器
把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”的这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类,实现这个动作的代码模块称为“类加载器”;
2.类的唯一性
对于任意一个类,都需要由加载它的类加载器和这个类本身这两点一同确定其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。这句话也可以理解为:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载他们的类的加载器不同,那么,这两个类必定不相等。
这个相等,包含代表类的Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法的返回结果,也包括使用instanceof关键字做对象所属关系判定等情况。
在Java虚拟机中,从Java虚拟机的角度看,有两种不同的类加载器:
启动类加载器(Bootstrap ClassLoader),这个类加载器使用C 语言实现的,是虚拟机自身的一部分;
这种分类是大方向上的,除了启动类加载器,其他的类加载器都是非启动类加载器,这些类加载器是Java语言实现的,独立于虚拟机外部,并且全都继承自抽象类java.lang.ClassLoader。
从Java开发人员的角度看,类加载器可以再细分一下,绝大部分Java程序都会使用到以下3种系统提供的类加载器:
3.启动类加载器 Bootstrap ClassLoader
这个类加载器负责将存放在<JAVA_HOME>lib目录中的,或者被-Xbootclasspath参数指定的路径中的,并且是虚拟机识别(这里说的识别,仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)的类库加载到虚拟机内存中。启动类加载器无法被Java程序直接使用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那直接使用null代替即可。
4.拓展类加载器 Extension ClassLoader
扩展类加载器是由sun.misc.Launcher$ExtClassLoader实现的,由Java语言实现的,是Launcher的静态内部类,它负责加载:
开发者可以直接使用扩展类加载器。
Launcher.class中的部分代码:
代码语言:javascript复制 public class Launcher {
static class ExtClassLoader extends URLClassLoader {
public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {
final File[] var0 = getExtDirs();
try {
return (Launcher.ExtClassLoader)AccessController.doPrivileged(new PrivilegedExceptionAction<Launcher.ExtClassLoader>() {
public Launcher.ExtClassLoader run() throws IOException {
int var1 = var0.length;
for(int var2 = 0; var2 < var1; var2) {
MetaIndex.registerDirectory(var0[var2]);
}
return new Launcher.ExtClassLoader(var0);
}
});
} catch (PrivilegedActionException var2) {
throw (IOException)var2.getException();
}
}
......
}
}
5.应用程序类加载器 Application ClassLoader
应用程序类加载器是由sun.misc.Launcher$AppClassLoader实现的,由Java语言实现,由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以也称为系统类加载器,它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器。
ClassLoader.class中的部分代码:
代码语言:javascript复制public abstract class ClassLoader {
private static java.lang.ClassLoader scl;
@CallerSensitive
public static java.lang.ClassLoader getSystemClassLoader() {
initSystemClassLoader();
if (scl == null) {
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
......
}
如果应用程序中没有自定义过自己的类加载器,一般情况下就是程序中默认的类加载器。