diff options
Diffstat (limited to 'jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java')
-rw-r--r-- | jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java | 149 |
1 files changed, 78 insertions, 71 deletions
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 77538c6b6881..94b00d9838a1 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -15,7 +15,6 @@ */ package org.jetbrains.jps.incremental.java; -import com.intellij.execution.process.BaseOSProcessHandler; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; @@ -32,8 +31,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.ProjectPaths; -import org.jetbrains.jps.api.GlobalOptions; -import org.jetbrains.jps.api.RequestFuture; import org.jetbrains.jps.builders.BuildRootIndex; import org.jetbrains.jps.builders.DirtyFilesHolder; import org.jetbrains.jps.builders.FileProcessor; @@ -63,13 +60,11 @@ import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.module.JpsModuleType; import org.jetbrains.jps.service.JpsServiceManager; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; +import javax.tools.*; import java.io.*; import java.net.ServerSocket; import java.util.*; import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; /** @@ -81,7 +76,6 @@ public class JavaBuilder extends ModuleLevelBuilder { public static final String BUILDER_NAME = "java"; private static final String JAVA_EXTENSION = "java"; private static final String DOT_JAVA_EXTENSION = "." + JAVA_EXTENSION; - public static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null; private static final Key<Integer> JAVA_COMPILER_VERSION_KEY = Key.create("_java_compiler_version_"); public static final Key<Boolean> IS_ENABLED = Key.create("_java_compiler_enabled_"); private static final Key<JavaCompilingTool> COMPILING_TOOL = Key.create("_java_compiling_tool_"); @@ -396,7 +390,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } try { final boolean rc; - if (USE_EMBEDDED_JAVAC) { + if (!shouldForkCompilerProcess(context, chunk, compilingTool)) { final Collection<File> _platformCp = calcEffectivePlatformCp(platformCp, options, compilingTool); if (_platformCp == null) { diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, @@ -409,16 +403,18 @@ public class JavaBuilder extends ModuleLevelBuilder { ); } else { - final JavacServerClient client = ensureJavacServerLaunched(context, compilingTool); - final RequestFuture<JavacServerResponseHandler> future = client.sendCompileRequest( - options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer - ); - while (!future.waitFor(100L, TimeUnit.MILLISECONDS)) { - if (context.getCancelStatus().isCanceled()) { - future.cancel(false); - } + // fork external javac + final String sdkHome = getChunkSdkHome(chunk); + if (sdkHome == null) { + diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "Cannot start javac process for " + chunk.getName() + ": unknown JDK home path.\nPlease check project configuration.")); + return true; } - rc = future.getMessageHandler().isTerminatedSuccessfully(); + + final List<String> vmOptions = getCompilationVMOptions(context, compilingTool); + final ExternalJavacServer server = ensureJavacServerStarted(context); + rc = server.forkJavac( + context, options, vmOptions, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer, sdkHome, compilingTool + ); } return rc; } @@ -426,6 +422,20 @@ public class JavaBuilder extends ModuleLevelBuilder { counter.await(); } } + + private static boolean shouldForkCompilerProcess(CompileContext context, ModuleChunk chunk, JavaCompilingTool tool) { + final int compilerSdkVersion = getCompilerSdkVersion(context); + if (compilerSdkVersion < 9) { + // javac up to version 9 supports all previous releases + return false; + } + final int chunkSdkVersion = getChunkSdkVersion(chunk); + if (chunkSdkVersion < 0) { + return false; // was not able to determine jdk version, assuming in-process compiler + } + // according to JEP 182: Retiring javac "one plus three back" policy + return Math.abs(compilerSdkVersion - chunkSdkVersion) > 3; + } // If platformCp of the build process is the same as the target plafform, do not specify platformCp explicitly // this will allow javac to resolve against ct.sym file, which is required for the "compilation profiles" feature @@ -482,31 +492,16 @@ public class JavaBuilder extends ModuleLevelBuilder { }); } - private static synchronized JavacServerClient ensureJavacServerLaunched(@NotNull CompileContext context, @NotNull JavaCompilingTool compilingTool) throws Exception { - final ExternalJavacDescriptor descriptor = ExternalJavacDescriptor.KEY.get(context); - if (descriptor != null) { - return descriptor.client; + private static synchronized ExternalJavacServer ensureJavacServerStarted(@NotNull CompileContext context) throws Exception { + ExternalJavacServer server = ExternalJavacServer.KEY.get(context); + if (server != null) { + return server; } - // start server here - final int port = findFreePort(); - final int heapSize = getJavacServerHeapSize(context); - - // use the same jdk that used to run the build process - final String javaHome = SystemProperties.getJavaHome(); - - final BaseOSProcessHandler processHandler = JavacServerBootstrap.launchJavacServer( - javaHome, heapSize, port, Utils.getSystemRoot(), getCompilationVMOptions(context, compilingTool), compilingTool - ); - final JavacServerClient client = new JavacServerClient(); - try { - client.connect("127.0.0.1", port); - } - catch (Throwable ex) { - processHandler.destroyProcess(); - throw new Exception("Failed to connect to external javac process: ", ex); - } - ExternalJavacDescriptor.KEY.set(context, new ExternalJavacDescriptor(processHandler, client)); - return client; + final int listenPort = findFreePort(); + server = new ExternalJavacServer(); + server.start(listenPort); + ExternalJavacServer.KEY.set(context, server); + return server; } private static int convertToNumber(String ver) { @@ -564,17 +559,10 @@ public class JavaBuilder extends ModuleLevelBuilder { } catch (IOException e) { e.printStackTrace(System.err); - return JavacServer.DEFAULT_SERVER_PORT; + return ExternalJavacServer.DEFAULT_SERVER_PORT; } } - private static int getJavacServerHeapSize(CompileContext context) { - final JpsProject project = context.getProjectDescriptor().getProject(); - final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project); - final JpsJavaCompilerOptions options = config.getCurrentCompilerOptions(); - return options.MAXIMUM_HEAP_SIZE; - } - private static final Key<List<String>> JAVAC_OPTIONS = Key.create("_javac_options_"); private static final Key<List<String>> JAVAC_VM_OPTIONS = Key.create("_javac_vm_options_"); private static final Key<String> USER_DEFINED_BYTECODE_TARGET = Key.create("_user_defined_bytecode_target_"); @@ -628,19 +616,12 @@ public class JavaBuilder extends ModuleLevelBuilder { options.add(langLevel); } - JpsJavaCompilerConfiguration compilerConfiguration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration( - context.getProjectDescriptor().getProject()); + final JpsJavaCompilerConfiguration compilerConfiguration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration( + context.getProjectDescriptor().getProject() + ); + String bytecodeTarget = null; - int chunkSdkVersion = -1; for (JpsModule module : chunk.getModules()) { - final JpsSdk<JpsDummyElement> sdk = module.getSdk(JpsJavaSdkType.INSTANCE); - if (sdk != null) { - final int moduleSdkVersion = convertToNumber(sdk.getVersionString()); - if (moduleSdkVersion != 0 /*could determine the version*/&& (chunkSdkVersion < 0 || chunkSdkVersion > moduleSdkVersion)) { - chunkSdkVersion = moduleSdkVersion; - } - } - final String moduleTarget = compilerConfiguration.getByteCodeTargetLevel(module.getName()); if (moduleTarget == null) { continue; @@ -662,6 +643,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } final int compilerSdkVersion = getCompilerSdkVersion(context); + final int chunkSdkVersion = getChunkSdkVersion(chunk); if (bytecodeTarget != null) { options.add("-target"); @@ -721,17 +703,19 @@ public class JavaBuilder extends ModuleLevelBuilder { } private static String getLanguageLevel(JpsModule module) { - LanguageLevel level = JpsJavaExtensionService.getInstance().getLanguageLevel(module); - if (level == null) return null; - switch (level) { - case JDK_1_3: return "1.3"; - case JDK_1_4: return "1.4"; - case JDK_1_5: return "1.5"; - case JDK_1_6: return "1.6"; - case JDK_1_7: return "1.7"; - case JDK_1_8: return "8"; - default: return null; + final LanguageLevel level = JpsJavaExtensionService.getInstance().getLanguageLevel(module); + if (level != null) { + switch (level) { + case JDK_1_3: return "1.3"; + case JDK_1_4: return "1.4"; + case JDK_1_5: return "1.5"; + case JDK_1_6: return "1.6"; + case JDK_1_7: return "1.7"; + case JDK_1_8: return "8"; + case JDK_1_9: return "9"; + } } + return null; } private static boolean isEncodingSet(List<String> options) { @@ -743,7 +727,6 @@ public class JavaBuilder extends ModuleLevelBuilder { return false; } - private static int getCompilerSdkVersion(CompileContext context) { final Integer cached = JAVA_COMPILER_VERSION_KEY.get(context); if (cached != null) { @@ -754,6 +737,30 @@ public class JavaBuilder extends ModuleLevelBuilder { return javaVersion; } + private static int getChunkSdkVersion(ModuleChunk chunk) { + int chunkSdkVersion = -1; + for (JpsModule module : chunk.getModules()) { + final JpsSdk<JpsDummyElement> sdk = module.getSdk(JpsJavaSdkType.INSTANCE); + if (sdk != null) { + final int moduleSdkVersion = convertToNumber(sdk.getVersionString()); + if (moduleSdkVersion != 0 /*could determine the version*/&& (chunkSdkVersion < 0 || chunkSdkVersion > moduleSdkVersion)) { + chunkSdkVersion = moduleSdkVersion; + } + } + } + return chunkSdkVersion; + } + + private static String getChunkSdkHome(ModuleChunk chunk) { + for (JpsModule module : chunk.getModules()) { + final JpsSdk<JpsDummyElement> sdk = module.getSdk(JpsJavaSdkType.INSTANCE); + if (sdk != null) { + return sdk.getHomePath(); + } + } + return null; + } + private static void loadCommonJavacOptions(@NotNull CompileContext context, @NotNull JavaCompilingTool compilingTool) { final List<String> options = new ArrayList<String>(); final List<String> vmOptions = new ArrayList<String>(); |