最近在做 Java Agent 的相关开发,参考部分开源代码实现的自定义类加载器实现时,部分类加载器实现含有以下静态块:
1 | static { |
该方法的实现如下:
1 | /** |
可以看出是 JDK 7 引入的,再看看 ParallelLoaders
的代码:
1 | /** |
可以看出 ParallelLoaders.register(callerClass)
在超类具有并行加载能力时将当前类加载器往 loaderTypes
中添加,以使当前类加载器具有并行加载能力,其中 ParallelLoaders.isRegistered
方法在 ClassLoader
的构造函数中被调用:
1 | // Maps class name to the corresponding lock object when the current |
根据如上代码可以看出如果 classLoader
被注册为了并行类加载器,则对 parallelLockMap
字段进行了初始化,否则使用 classloader
实例作为锁。其中对 parallelLockMap
主要使用方法如下:
1 | /** |
当 parallelLockMap
为空即该 classLoader
不具有并行类加载能力时,直接返回当前 classLoader
实例作为锁的对象,当 parallelLockMap
不为空时,使用需要加载类的 className
作为 key
,并新创建了一个 Object
(如果创建过就使用之前创建的 Object
)作为锁的对象,getClassLoadingLock
方法在 loadClass
方法中被调用,其中 loadClass
方法代码如下:
1 | /** |
getClassLoadingLock
方法的返回值被 synchronized
关键字所使用,以上就是支持并行类加载的类加载器的不同之处,但是为什么要这样实现呢,关于这一点,可以参考:Multithreaded Custom Class Loaders in Java SE 7,该文档解释了为何引入该项特性,其中有一段提到:
Custom class loaders will not run into deadlocks if they adhere to an acyclic class loader delegation model. Acyclic delegation is what the architects of ClassLoader envisioned.
自定义类加载器如果遵循无环的类加载委托模型则不会导致死锁,无环的委托模型是 ClassLoader 的架构师所设想的。
In earlier releases of the Java platform, multithreaded custom class loaders could deadlock when they did not have an acyclic delegation model.
在早期的 Java 平台中,多线程自定义类加载器当没有遵循无环的委托模型时可能导致死锁。
该文档详细描述了自定义类加载器没有遵循无环委托模型时可能导致死锁的问题并给出了解决方案,即在 ClassLoader 及需要加载的 className
上进行同步,以解决可能存在的死锁问题。