Cache classloaders for tools.jar and kapt in Gradle workers

#KT-28852 fixed

The loaders and hence some classes were repeatedly loaded and
jit-compiled everytime when KaptExecution were dispatched. Those
classes, like JavaCompiler, can be very large and therefore created a
significant overhead. In some projects, the overhead accounted for more
than 40% of total CPU time of annotation processing.

This change tries to cache the classloaders so that they won't be
reloaded and re-jitted.
This commit is contained in:
Ting-Yuan Huang
2018-11-29 16:14:11 -08:00
committed by Alexey Tsvetkov
parent 1ba6d5361b
commit 6c627fa5c1
@@ -100,19 +100,24 @@ private class KaptExecution @Inject constructor(
private const val JAVAC_CONTEXT_CLASS = "com.sun.tools.javac.util.Context"
private fun kaptClass(classLoader: ClassLoader) = Class.forName("org.jetbrains.kotlin.kapt3.base.Kapt", true, classLoader)
private var cachedClassLoaderWithToolsJar: ClassLoader? = null
private var cachedKaptClassLoader: ClassLoader? = null
}
override fun run(): Unit = with(optionsForWorker) {
val kaptClasspathUrls = kaptClasspath.map { it.toURI().toURL() }.toTypedArray()
val rootClassLoader = findRootClassLoader()
val classLoaderWithToolsJar = if (toolsJar != null && !javacIsAlreadyHere()) {
val classLoaderWithToolsJar = cachedClassLoaderWithToolsJar ?: if (toolsJar != null && !javacIsAlreadyHere()) {
URLClassLoader(arrayOf(toolsJar.toURI().toURL()), rootClassLoader)
} else {
rootClassLoader
}
cachedClassLoaderWithToolsJar = classLoaderWithToolsJar
val kaptClassLoader = cachedKaptClassLoader ?: URLClassLoader(kaptClasspathUrls, classLoaderWithToolsJar)
cachedKaptClassLoader = kaptClassLoader
val kaptClassLoader = URLClassLoader(kaptClasspathUrls, classLoaderWithToolsJar)
val kaptMethod = kaptClass(kaptClassLoader).declaredMethods.single { it.name == "kapt" }
kaptMethod.invoke(null, createKaptOptions(kaptClassLoader))
}