diff --git a/compiler/preloader/src/org/jetbrains/jet/preloading/ClassCondition.java b/compiler/preloader/src/org/jetbrains/jet/preloading/ClassCondition.java new file mode 100644 index 00000000000..a2d689373e9 --- /dev/null +++ b/compiler/preloader/src/org/jetbrains/jet/preloading/ClassCondition.java @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2014 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.jet.preloading; + +public interface ClassCondition { + boolean accept(String className); +} diff --git a/compiler/preloader/src/org/jetbrains/jet/preloading/ClassPreloadingUtils.java b/compiler/preloader/src/org/jetbrains/jet/preloading/ClassPreloadingUtils.java index 3b5898df090..cd42f53fffb 100644 --- a/compiler/preloader/src/org/jetbrains/jet/preloading/ClassPreloadingUtils.java +++ b/compiler/preloader/src/org/jetbrains/jet/preloading/ClassPreloadingUtils.java @@ -50,35 +50,38 @@ public class ClassPreloadingUtils { * @param classCountEstimation an estimated number of classes in a the jars * @param parentClassLoader parent class loader * @param handler handler to be notified on class definitions done by this class loader, or null + * @param classesToLoadByParent condition to load some classes via parent class loader * @return a class loader that reads classes from memory * @throws IOException on from reading the jar */ public static ClassLoader preloadClasses( - Collection jarFiles, int classCountEstimation, ClassLoader parentClassLoader, ClassHandler handler + Collection jarFiles, + int classCountEstimation, + ClassLoader parentClassLoader, + ClassCondition classesToLoadByParent, + ClassHandler handler ) throws IOException { Map entries = loadAllClassesFromJars(jarFiles, classCountEstimation, handler); - return createMemoryBasedClassLoader(parentClassLoader, entries, handler); + return createMemoryBasedClassLoader(parentClassLoader, entries, handler, classesToLoadByParent); } public static ClassLoader preloadClasses( - Collection jarFiles, int classCountEstimation, ClassLoader parentClassLoader + Collection jarFiles, int classCountEstimation, ClassLoader parentClassLoader, ClassCondition classesToLoadByParent ) throws IOException { - return preloadClasses(jarFiles, classCountEstimation, parentClassLoader, null); + return preloadClasses(jarFiles, classCountEstimation, parentClassLoader, classesToLoadByParent, null); } private static ClassLoader createMemoryBasedClassLoader( final ClassLoader parent, final Map preloadedResources, - final ClassHandler handler + final ClassHandler handler, + final ClassCondition classesToLoadByParent ) { return new ClassLoader(null) { @Override public Class loadClass(String name) throws ClassNotFoundException { - // When compiler is invoked from JPS, we should use loaded incremental cache interface from its class loader, - // because implementation is loaded from it, as well - if (name.startsWith("org.jetbrains.jet.lang.resolve.kotlin.incremental.cache.") || - name.equals("org.jetbrains.jet.config.CompilerServices")) { + if (classesToLoadByParent != null && classesToLoadByParent.accept(name)) { if (parent == null) { return super.loadClass(name); } diff --git a/compiler/preloader/src/org/jetbrains/jet/preloading/Preloader.java b/compiler/preloader/src/org/jetbrains/jet/preloading/Preloader.java index ca9a546d3b4..df851fbb586 100644 --- a/compiler/preloader/src/org/jetbrains/jet/preloading/Preloader.java +++ b/compiler/preloader/src/org/jetbrains/jet/preloading/Preloader.java @@ -60,7 +60,7 @@ public class Preloader { ClassLoader withInstrumenter = instrumentersClasspath.length > 0 ? new URLClassLoader(instrumentersClasspath, parent) : parent; final Handler handler = getHandler(mode, withInstrumenter); - ClassLoader preloaded = ClassPreloadingUtils.preloadClasses(files, classNumber, withInstrumenter, handler); + ClassLoader preloaded = ClassPreloadingUtils.preloadClasses(files, classNumber, withInstrumenter, null, handler); Class mainClass = preloaded.loadClass(mainClassCanonicalName); Method mainMethod = mainClass.getMethod("main", String[].class); diff --git a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerEnvironment.java b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerEnvironment.java index b2adcd155a4..1cfba633832 100644 --- a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerEnvironment.java +++ b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerEnvironment.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.cli.common.messages.MessageCollector; import org.jetbrains.jet.config.CompilerServices; +import org.jetbrains.jet.preloading.ClassCondition; import org.jetbrains.jet.utils.KotlinPaths; import org.jetbrains.jet.utils.PathUtil; @@ -34,9 +35,10 @@ public final class CompilerEnvironment { @NotNull KotlinPaths kotlinPaths, @Nullable File outputDir, @Nullable ClassLoader parentClassLoader, + @NotNull ClassCondition classesToLoadByParent, @NotNull CompilerServices compilerServices ) { - return new CompilerEnvironment(kotlinPaths, outputDir, parentClassLoader, compilerServices); + return new CompilerEnvironment(kotlinPaths, outputDir, parentClassLoader, classesToLoadByParent, compilerServices); } @NotNull @@ -45,6 +47,8 @@ public final class CompilerEnvironment { private final File output; @Nullable private final ClassLoader parentClassLoader; + @Nullable + private final ClassCondition classesToLoadByParent; @NotNull private final CompilerServices services; @@ -52,11 +56,13 @@ public final class CompilerEnvironment { @NotNull KotlinPaths kotlinPaths, @Nullable File output, @Nullable ClassLoader parentClassLoader, + @NotNull ClassCondition classesToLoadByParent, @NotNull CompilerServices services ) { this.kotlinPaths = kotlinPaths; this.output = output; this.parentClassLoader = parentClassLoader; + this.classesToLoadByParent = classesToLoadByParent; this.services = services; } @@ -80,6 +86,11 @@ public final class CompilerEnvironment { return parentClassLoader; } + @Nullable + public ClassCondition getClassesToLoadByParent() { + return classesToLoadByParent; + } + public void reportErrorsTo(@NotNull MessageCollector messageCollector) { if (output == null) { messageCollector.report(ERROR, "[Internal Error] No output directory", NO_LOCATION); diff --git a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerRunnerUtil.java b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerRunnerUtil.java index 410c3ac1d3f..ed46627bb53 100644 --- a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerRunnerUtil.java +++ b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerRunnerUtil.java @@ -20,7 +20,7 @@ import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.cli.common.messages.MessageCollector; -import org.jetbrains.jet.config.CompilerServices; +import org.jetbrains.jet.preloading.ClassCondition; import org.jetbrains.jet.preloading.ClassPreloadingUtils; import org.jetbrains.jet.utils.KotlinPaths; @@ -60,13 +60,14 @@ public class CompilerRunnerUtil { public static ClassLoader getOrCreatePreloader( @NotNull KotlinPaths paths, @Nullable ClassLoader parentClassLoader, + @Nullable ClassCondition classToLoadByParent, @NotNull MessageCollector messageCollector ) { ClassLoader answer = ourClassLoaderRef.get(); if (answer == null) { try { int estimatedClassNumber = 4096; - answer = ClassPreloadingUtils.preloadClasses(kompilerClasspath(paths, messageCollector), estimatedClassNumber, parentClassLoader); + answer = ClassPreloadingUtils.preloadClasses(kompilerClasspath(paths, messageCollector), estimatedClassNumber, parentClassLoader, classToLoadByParent); } catch (IOException e) { throw new RuntimeException(e); @@ -119,7 +120,8 @@ public class CompilerRunnerUtil { MessageCollector messageCollector, PrintStream out, boolean usePreloader ) throws Exception { ClassLoader loader = usePreloader - ? getOrCreatePreloader(environment.getKotlinPaths(), environment.getParentClassLoader(), messageCollector) + ? getOrCreatePreloader(environment.getKotlinPaths(), environment.getParentClassLoader(), + environment.getClassesToLoadByParent(), messageCollector) : getOrCreateClassLoader(environment.getKotlinPaths(), messageCollector); Class kompiler = Class.forName(compilerClassName, true, loader); diff --git a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java index a09cbed0ddf..ba809168e2f 100644 --- a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java +++ b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java @@ -42,6 +42,7 @@ import org.jetbrains.jet.config.IncrementalCompilation; import org.jetbrains.jet.jps.JpsKotlinCompilerSettings; import org.jetbrains.jet.jps.incremental.*; import org.jetbrains.jet.lang.resolve.kotlin.incremental.cache.IncrementalCacheProvider; +import org.jetbrains.jet.preloading.ClassCondition; import org.jetbrains.jet.utils.PathUtil; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.builders.DirtyFilesHolder; @@ -132,7 +133,13 @@ public class KotlinBuilder extends ModuleLevelBuilder { .build(); CompilerEnvironment environment = CompilerEnvironment.getEnvironmentFor( - PathUtil.getKotlinPathsForJpsPluginOrJpsTests(), outputDir, getClass().getClassLoader(), compilerServices); + PathUtil.getKotlinPathsForJpsPluginOrJpsTests(), outputDir, getClass().getClassLoader(), new ClassCondition() { + @Override + public boolean accept(String className) { + return className.startsWith("org.jetbrains.jet.lang.resolve.kotlin.incremental.cache.") || + className.equals("org.jetbrains.jet.config.CompilerServices"); + } + }, compilerServices); if (!environment.success()) { environment.reportErrorsTo(messageCollector); return ExitCode.ABORT;