build scripts: add tools.jar to classpath of the system classloader (IDEA-206314)

Otherwise internal javac classes used in JavacReferenceCollectorListener will be incompatible with the classes loaded by javax.tools.ToolProvider.
This commit is contained in:
nik
2019-02-15 09:47:53 +03:00
parent 063b88c582
commit 9e33362183
2 changed files with 32 additions and 0 deletions
@@ -38,6 +38,16 @@ class BuildUtils {
addToClassLoaderClassPath(path, ant, BuildUtils.class.classLoader)
}
@CompileDynamic
static void addToSystemClasspath(File file) {
def classLoader = ClassLoader.getSystemClassLoader()
if (!(classLoader instanceof URLClassLoader)) {
throw new BuildException("Cannot add to system classpath: unsupported class loader $classLoader (${classLoader.getClass()})")
}
classLoader.addURL(file.toURI().toURL())
}
static void addToJpsClassPath(String path, AntBuilder ant) {
//we need to add path to classloader of BuilderService to ensure that classes from that path will be returned by JpsServiceManager.getExtensions
addToClassLoaderClassPath(path, ant, Class.forName("org.jetbrains.jps.incremental.BuilderService").classLoader)
@@ -42,6 +42,7 @@ import org.apache.tools.ant.BuildException
import org.jetbrains.annotations.NonNls
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.intellij.build.BuildMessages
import org.jetbrains.intellij.build.CompilationContext
import org.jetbrains.jps.api.CmdlineRemoteProto
import org.jetbrains.jps.api.GlobalOptions
@@ -67,6 +68,7 @@ import org.jetbrains.jps.model.module.JpsModule
*/
@CompileStatic
class JpsCompilationRunner {
private static boolean ourToolsJarAdded
private final CompilationContext context
private final JpsCompilationData compilationData
@@ -150,6 +152,9 @@ class JpsCompilationRunner {
private void runBuild(final Set<String> modulesSet, final boolean allModules, Collection<String> artifactNames, boolean includeTests,
boolean resolveProjectDependencies) {
if (!modulesSet.isEmpty() || allModules) {
addToolsJarToSystemClasspath(context.paths.jdkHome, context.messages)
}
System.setProperty(GlobalOptions.USE_DEFAULT_FILE_LOGGING_OPTION, "false")
final AntMessageHandler messageHandler = new AntMessageHandler()
AntLoggerFactory.ourMessageHandler = messageHandler
@@ -217,6 +222,23 @@ class JpsCompilationRunner {
}
}
/**
* Add tools.jar to the system classloader's classpath. {@link javax.tools.ToolProvider} will load javac implementation classes by its own URLClassLoader,
* which uses the system classloader as its parent, so we need to ensure that tools.jar will be accessible from the system classloader,
* otherwise the loaded classes will be incompatible with the classes loaded by {@link org.jetbrains.jps.javac.ast.JavacReferenceCollectorListener}.
*/
private static void addToolsJarToSystemClasspath(String jdkHome, BuildMessages messages) {
if (ourToolsJarAdded) {
return
}
File toolsJar = new File(jdkHome, "lib/tools.jar")
if (!toolsJar.exists()) {
messages.error("Failed to add tools.jar to classpath: $toolsJar doesn't exist")
}
BuildUtils.addToSystemClasspath(toolsJar)
ourToolsJarAdded = true
}
private class AntMessageHandler implements MessageHandler {
private MultiMap<String, String> errorMessagesByCompiler = MultiMap.createLinked()
private float progress = -1.0