Use isolated classloader for in-process compilation
#KT-20233 fixed
This commit is contained in:
+2
-2
@@ -31,12 +31,12 @@ import com.intellij.openapi.util.io.FileUtil
|
|||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
import org.jetbrains.kotlin.daemon.client.CompileServiceSession
|
import org.jetbrains.kotlin.daemon.client.CompileServiceSession
|
||||||
import org.jetbrains.kotlin.daemon.common.*
|
import org.jetbrains.kotlin.daemon.common.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.ParentLastURLClassLoader
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||||
import org.jetbrains.kotlin.incremental.*
|
import org.jetbrains.kotlin.incremental.*
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
|
import java.net.URLClassLoader
|
||||||
|
|
||||||
internal const val KOTLIN_COMPILER_EXECUTION_STRATEGY_PROPERTY = "kotlin.compiler.execution.strategy"
|
internal const val KOTLIN_COMPILER_EXECUTION_STRATEGY_PROPERTY = "kotlin.compiler.execution.strategy"
|
||||||
internal const val DAEMON_EXECUTION_STRATEGY = "daemon"
|
internal const val DAEMON_EXECUTION_STRATEGY = "daemon"
|
||||||
@@ -298,7 +298,7 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
|
|||||||
val stream = ByteArrayOutputStream()
|
val stream = ByteArrayOutputStream()
|
||||||
val out = PrintStream(stream)
|
val out = PrintStream(stream)
|
||||||
// todo: cache classloader?
|
// todo: cache classloader?
|
||||||
val classLoader = ParentLastURLClassLoader(environment.compilerClasspathURLs, this.javaClass.classLoader)
|
val classLoader = URLClassLoader(environment.compilerClasspathURLs.toTypedArray())
|
||||||
val servicesClass = Class.forName(Services::class.java.canonicalName, true, classLoader)
|
val servicesClass = Class.forName(Services::class.java.canonicalName, true, classLoader)
|
||||||
val emptyServices = servicesClass.getField("EMPTY").get(servicesClass)
|
val emptyServices = servicesClass.getField("EMPTY").get(servicesClass)
|
||||||
val compiler = Class.forName(compilerClassName, true, classLoader)
|
val compiler = Class.forName(compilerClassName, true, classLoader)
|
||||||
|
|||||||
-103
@@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.plugin;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A parent-last classloader that will try the child classloader first and then the parent.
|
|
||||||
* This takes a fair bit of doing because java really prefers parent-first.
|
|
||||||
* <p/>
|
|
||||||
* For those not familiar with class loading trickery, be wary
|
|
||||||
*
|
|
||||||
* http://stackoverflow.com/questions/5445511/how-do-i-create-a-parent-last-child-first-classloader-in-java-or-how-to-overr
|
|
||||||
*/
|
|
||||||
public class ParentLastURLClassLoader extends ClassLoader {
|
|
||||||
private final ChildURLClassLoader childClassLoader;
|
|
||||||
|
|
||||||
public ParentLastURLClassLoader(@NotNull List<URL> classpath, @Nullable ClassLoader parent) {
|
|
||||||
super(Thread.currentThread().getContextClassLoader());
|
|
||||||
|
|
||||||
URL[] urls = classpath.toArray(new URL[classpath.size()]);
|
|
||||||
|
|
||||||
childClassLoader = new ChildURLClassLoader(urls, new FindClassClassLoader(parent));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected synchronized Class<?> loadClass(@NotNull String name, boolean resolve) throws ClassNotFoundException {
|
|
||||||
try {
|
|
||||||
// first we try to find a class inside the child classloader
|
|
||||||
return childClassLoader.findClass(name);
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException e) {
|
|
||||||
// didn't find it, try the parent
|
|
||||||
return super.loadClass(name, resolve);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class allows me to call findClass on a classloader
|
|
||||||
*/
|
|
||||||
private static class FindClassClassLoader extends ClassLoader {
|
|
||||||
public FindClassClassLoader(@Nullable ClassLoader parent) {
|
|
||||||
super(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Class<?> findClass(@NotNull String name) throws ClassNotFoundException {
|
|
||||||
return super.findClass(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class delegates (child then parent) for the findClass method for a URLClassLoader.
|
|
||||||
* We need this because findClass is protected in URLClassLoader
|
|
||||||
*/
|
|
||||||
static class ChildURLClassLoader extends URLClassLoader {
|
|
||||||
private final FindClassClassLoader realParent;
|
|
||||||
|
|
||||||
public ChildURLClassLoader(@NotNull URL[] urls, @NotNull FindClassClassLoader realParent) {
|
|
||||||
super(urls, null);
|
|
||||||
|
|
||||||
this.realParent = realParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Class<?> findClass(@NotNull String name) throws ClassNotFoundException {
|
|
||||||
Class<?> loaded = findLoadedClass(name);
|
|
||||||
if (loaded != null) {
|
|
||||||
return loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return super.findClass(name);
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException e) {
|
|
||||||
// if that fails, we ask our real parent classloader to load the class (we give up)
|
|
||||||
return realParent.loadClass(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user