/**
* Encapsulates the set of parallel capable loader types.
*/
private static class ParallelLoaders {
private ParallelLoaders() {}
// the set of parallel capable loader types
private static final Set<Class<? extends ClassLoader>> loaderTypes =
Collections.newSetFromMap(
new WeakHashMap<Class<? extends ClassLoader>, Boolean>());
static {
synchronized (loaderTypes) { loaderTypes.add(ClassLoader.class); }
}
/**
* Registers the given class loader type as parallel capabale.
* Returns {@code true} is successfully registered; {@code false} if
* loader's super class is not registered.
*/
static boolean register(Class<? extends ClassLoader> c) {
synchronized (loaderTypes) {
if (loaderTypes.contains(c.getSuperclass())) {
// register the class loader as parallel capable
// if and only if all of its super classes are.
// Note: given current classloading sequence, if
// the immediate super class is parallel capable,
// all the super classes higher up must be too.
loaderTypes.add(c);
return true;
} else {
return false;
}
}
}
/**
* Returns {@code true} if the given class loader type is
* registered as parallel capable.
*/
static boolean isRegistered(Class<? extends ClassLoader> c) {
synchronized (loaderTypes) {
return loaderTypes.contains(c);
}
}
}
原来,一个类加载器想要成为一个并行类加载器,是需要自己注册的,看看注册方法
@CallerSensitive
protected static boolean registerAsParallelCapable() {
Class<? extends ClassLoader> callerClass =
Reflection.getCallerClass().asSubclass(ClassLoader.class);
return ParallelLoaders.register(callerClass);
}
最终还是调用了内部类的注册方法。源码在上面,可以看到,一个类加载器要想注册,它的父类必须已经注册了,也就是说从继承路径上的所有父类都必须是并行类加载器。而且一开始,就把ClassLoader这个类注册进去了。
我有个疑问,这里有父类的什么事呢,光注册自己这个类就好了呀。想了半天,还是不明白,是有关于安全吗?哎,大牛就是大牛,哈哈。读者如有明白的,请直言相告。
最后,来看看并行类加载在Tomcat上的应用。原本WebappClassLoader没有注册,只能串行加载类。后来,是阿里意识到了这个问题,解决方案被Tomcat采纳。
static {
// Register this base class loader as parallel capable on Java 7+ JREs
Method getClassLoadingLockMethod = null;
try {
if (JreCompat.isJre7Available()) {
final Method registerParallel =
ClassLoader.class.getDeclaredMethod("registerAsParallelCapable");
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
registerParallel.setAccessible(true);
return null;
}
});
registerParallel.invoke(null);
getClassLoadingLockMethod =
ClassLoader.class.getDeclaredMethod("getClassLoadingLock", String.class);
}
} catch (Exception e) {
// ignore
}
这段代码出现在WebappClassLoader类的父类WebappClassLoaderBase里,通过反射调用了ClassLoader类的注册方法。
类的加载能够并行后,我们启动应用的时候,肯定会更快。