类通过类加载器加载,一个类由加载它的类加载器和其本身决定其在JVM中的唯一性,每一个类加载器,都拥有一个独立的类名称空间
public class Test {
public static void main(String[] args) throws Exception{
ClassLoader myLoader = new ClassLoader() {
@Override
public Class> loadClass(String name) throws ClassNotFoundException {
try {
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream is = getClass().getResourceAsStream(fileName);
if (is == null) {
return super.loadClass(name);
}
byte[] b = new byte[is.available()];
is.read(b);
return defineClass(name, b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
throw new ClassNotFoundException(name);
}
}
};
Object obj = myLoader.loadClass("Test").newInstance();
System.out.println(obj.getClass());
System.out.println(obj instanceof Test);
}
}
如上,自定义了一个类加载器去加载Test,instanceof 输出false
class Test
false
从JVM角度看存在
从开发者角度看存在:

除了启动类加载器外,其余的类加载器都有自己的父类加载器,通过组合而非继承关系来复用父加载器的代码
双亲委派模型让类随着它的类加载器形成优先级的层次关系,如对于Object,无论哪个类加载器加载,最终都委派给启动类加载器,从而保证了唯一性
protected synchronized Class> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// 首先,检查请求的类是否已经被加载过了
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// 如果父类加载器抛出ClassNotFoundException
// 说明父类加载器无法完成加载请求
}
if (c == null) {
// 在父类加载器无法加载时
// 再调用本身的findClass方法来进行类加载
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
上面为java.lang.ClassLoader的loadClass()方法中双亲委派模型的代码实现
双亲委派模型在JDK1.2推出,在此之前的类加载器都是通过复写loadClass()方法加载类
为了兼容,无法再以技术手段避免loadClass()被子类复写,即可以通过复写loadClass()方法双亲委派模型
为了避免破坏双亲委派模型,JDK1.2新增protect的findClass()方法,让用户尽可能重写findClass()而不是loadClass(),这样既不影响用户自定义加载类,又可保证新写的类加载器符合双亲委派模型
根据双亲委派模型,越基础的类由越上层的加载器加载,基础类型是作为被用户代码继承、调用的API存在
而基础类型要调用回用户的代码(加载资源类),则需通过线程上下文类加载器(Thread Context ClassLoader)
这是一种由父类加载器去请求子类加载器完成类加载的行为,打通了双亲委派模型的层次结构来逆向使用类加载器,典型应用有JNDI、JDBC等
IBM推出的OSGi为了实现模块热部署,每个程序模块(称为Bundle)都有自身的类加载器,当需要更换Bundle时连同类加载器一起换掉以实现代码的热替换
在OSGi环境下,类加载器不再是双亲委派模型的树状结构,而是网状结构,当收到类加载请求时,按照下面的顺序进行类搜索
上面只有前两点仍符合双亲委派模型,其余的类查找都是在平级的类加载器中进行的