external javac mode + options for switching it on; compile server defaults altered

This commit is contained in:
Eugene Zhuravlev
2012-01-25 12:45:44 +01:00
parent b5c92132c1
commit e3aeae9548
5 changed files with 93 additions and 24 deletions
@@ -397,7 +397,7 @@ public class CompileServerManager implements ApplicationComponent{
// commandLine.add((launcherUsed? "-J" : "") + "-D" + CharsetToolkit.FILE_ENCODING_PROPERTY + "=" + CharsetToolkit.getDefaultSystemCharset().name());
//}
private Process launchServer(int port) throws ExecutionException {
private Process launchServer(final int port) throws ExecutionException {
// validate tools.jar presence
final JavaCompiler systemCompiler = ToolProvider.getSystemJavaCompiler();
if (systemCompiler == null) {
@@ -406,7 +406,8 @@ public class CompileServerManager implements ApplicationComponent{
final Sdk projectJdk = JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
final GeneralCommandLine cmdLine = new GeneralCommandLine();
cmdLine.setExePath(((JavaSdkType)projectJdk.getSdkType()).getVMExecutablePath(projectJdk));
final String vmExecutablePath = ((JavaSdkType)projectJdk.getSdkType()).getVMExecutablePath(projectJdk);
cmdLine.setExePath(vmExecutablePath);
cmdLine.addParameter("-server");
cmdLine.addParameter("-ea");
cmdLine.addParameter("-XX:MaxPermSize=150m");
@@ -416,12 +417,21 @@ public class CompileServerManager implements ApplicationComponent{
cmdLine.addParameter("-Xmx" + Registry.intValue("compiler.server.heap.size") + "m");
// debugging
cmdLine.addParameter("-XX:+HeapDumpOnOutOfMemoryError");
//cmdLine.addParameter("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5008");
if (Registry.is("compiler.server.use.memory.temp.cache")) {
cmdLine.addParameter("-D"+Server.USE_MEMORY_TEMP_CACHE_OPTION + "=true");
final int debugPort = Registry.intValue("compiler.server.debug.port");
if (debugPort > 0) {
cmdLine.addParameter("-XX:+HeapDumpOnOutOfMemoryError");
cmdLine.addParameter("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=" + debugPort);
}
if (Registry.is("compiler.server.use.memory.temp.cache")) {
cmdLine.addParameter("-D"+ GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION + "=true");
}
if (Registry.is("compiler.server.use.external.javac.process")) {
cmdLine.addParameter("-D"+ GlobalOptions.USE_EXTERNAL_JAVAC_OPTION + "=true");
}
cmdLine.addParameter("-D"+ GlobalOptions.HOSTNAME_OPTION + "=" + NetUtils.getLocalHostString());
cmdLine.addParameter("-D"+ GlobalOptions.VM_EXE_PATH_OPTION + "=" + FileUtil.toSystemIndependentName(vmExecutablePath));
// javac's VM should use the same default locale that IDEA uses in order for javac to print messages in 'correct' language
final String lang = System.getProperty("user.language");
if (lang != null) {
@@ -0,0 +1,13 @@
package org.jetbrains.jps.api;
/**
* @author Eugene Zhuravlev
* Date: 1/24/12
*/
public interface GlobalOptions {
String USE_MEMORY_TEMP_CACHE_OPTION = "use.memory.temp.cache";
String USE_EXTERNAL_JAVAC_OPTION = "use.external.javac.process";
String HOSTNAME_OPTION = "localhost.name";
String VM_EXE_PATH_OPTION = "vm.executable.path";
}
@@ -18,6 +18,7 @@ import org.jetbrains.jps.Module;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.Project;
import org.jetbrains.jps.ProjectPaths;
import org.jetbrains.jps.api.GlobalOptions;
import org.jetbrains.jps.api.RequestFuture;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.messages.BuildMessage;
@@ -36,6 +37,7 @@ import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.io.*;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
@@ -48,9 +50,9 @@ import java.util.concurrent.ExecutorService;
*/
public class JavaBuilder extends Builder{
public static final String BUILDER_NAME = "java";
private static final String JAVA_EXTENSION = ".java";
private static final String FORM_EXTENSION = ".form";
private static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null;
private static final FileFilter JAVA_SOURCES_FILTER = new FileFilter() {
public boolean accept(File file) {
@@ -222,7 +224,6 @@ public class JavaBuilder extends Builder{
final Collection<File> classpath = paths.getCompilationClasspath(chunk, context.isCompilingTests(), false/*context.isProjectRebuild()*/);
final Collection<File> platformCp = paths.getPlatformCompilationClasspath(chunk, context.isCompilingTests(), false/*context.isProjectRebuild()*/);
final Map<File, Set<File>> outs = buildOutputDirectoriesMap(context, chunk);
final List<String> options = getCompilationOptions(context, chunk);
// begin compilation round
final DiagnosticSink diagnosticSink = new DiagnosticSink(context);
@@ -234,7 +235,7 @@ public class JavaBuilder extends Builder{
final Set<File> sourcePath = TEMPORARY_SOURCE_ROOTS_KEY.get(context,Collections.<File>emptySet());
final boolean compiledOk = compileJava(
options, files, classpath, platformCp, sourcePath, outs, context, diagnosticSink, outputSink
files, classpath, platformCp, sourcePath, outs, context, diagnosticSink, outputSink
);
final Map<File, String> chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk, context.isCompilingTests());
@@ -291,12 +292,12 @@ public class JavaBuilder extends Builder{
return exitCode;
}
private boolean compileJava(List<String> options, Collection<File> files, Collection<File> classpath, Collection<File> platformCp, Collection<File> sourcePath, Map<File, Set<File>> outs, CompileContext context, DiagnosticOutputConsumer diagnosticSink, final OutputFileConsumer outputSink) throws Exception {
final boolean useEmbeddedJavac = true; // todo: make configurable
private boolean compileJava(Collection<File> files, Collection<File> classpath, Collection<File> platformCp, Collection<File> sourcePath, Map<File, Set<File>> outs, CompileContext context, DiagnosticOutputConsumer diagnosticSink, final OutputFileConsumer outputSink) throws Exception {
final List<String> options = getCompilationOptions(context);
final ClassProcessingConsumer classesConsumer = new ClassProcessingConsumer(context, outputSink);
try {
final boolean rc;
if (useEmbeddedJavac) {
if (USE_EMBEDDED_JAVAC) {
rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer, context.getCancelStatus());
}
else {
@@ -326,13 +327,12 @@ public class JavaBuilder extends Builder{
return descriptor.client;
}
// start server here
final String javaHome = System.getProperty("java.home");
final String vmExecPath = System.getProperty(GlobalOptions.VM_EXE_PATH_OPTION, System.getProperty("java.home") + "/bin/java");
final String hostString = System.getProperty(GlobalOptions.HOSTNAME_OPTION, "localhost");
final int port = findFreePort();
final int heapSize = getJavacServerHeapSize(context);
final String hostString = "localhost"; // todo: obtain from IDEA
final int port = 9999; // todo: obtain from IDEA
final int heapSize = 512; // todo: make configurable; either obtain from IDEA or calculate
final BaseOSProcessHandler processHandler = JavacServerBootstrap.launchJavacServer(javaHome + "/bin/java", heapSize, port, Paths.getSystemRoot());
final BaseOSProcessHandler processHandler = JavacServerBootstrap.launchJavacServer(vmExecPath, heapSize, port, Paths.getSystemRoot());
final JavacServerClient client = new JavacServerClient();
try {
client.connect(hostString, port);
@@ -345,6 +345,46 @@ public class JavaBuilder extends Builder{
return client;
}
private static int findFreePort() {
try {
final ServerSocket serverSocket = new ServerSocket(0);
try {
return serverSocket.getLocalPort();
}
finally {
//workaround for linux : calling close() immediately after opening socket
//may result that socket is not closed
synchronized(serverSocket) {
try {
serverSocket.wait(1);
}
catch (Throwable ignored) {
}
}
serverSocket.close();
}
}
catch (IOException e) {
e.printStackTrace(System.err);
return JavacServer.DEFAULT_SERVER_PORT;
}
}
private static int getJavacServerHeapSize(CompileContext context) {
int heapSize = 512;
final Project project = context.getProject();
final Map<String, String> javacOpts = project.getCompilerConfiguration().getJavacOptions();
final String hSize = javacOpts.get("MAXIMUM_HEAP_SIZE");
if (hSize != null) {
try {
heapSize = Integer.parseInt(hSize);
}
catch (NumberFormatException ignored) {
}
}
return heapSize;
}
private static ClassLoader createInstrumentationClassLoader(Collection<File> classpath, Collection<File> platformCp, Map<File, String> chunkSourcePath, OutputFilesSink outputSink)
throws MalformedURLException {
final List<URL> urls = new ArrayList<URL>();
@@ -361,7 +401,7 @@ public class JavaBuilder extends Builder{
return new CompiledClassesLoader(outputSink, urls.toArray(new URL[urls.size()]));
}
private static List<String> getCompilationOptions(CompileContext context, ModuleChunk chunk) {
private static List<String> getCompilationOptions(CompileContext context) {
final List<String> options = new ArrayList<String>();
options.add("-verbose");
@@ -10,6 +10,7 @@ import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import org.jetbrains.jps.api.GlobalOptions;
import org.jetbrains.jps.api.JpsRemoteProto;
import org.jetbrains.jps.incremental.Paths;
@@ -27,7 +28,6 @@ public class Server {
private static final int MAX_SIMULTANEOUS_BUILD_SESSIONS = Math.max(2, Runtime.getRuntime().availableProcessors());
public static final String SERVER_SUCCESS_START_MESSAGE = "Compile Server started successfully. Listening on port: ";
public static final String SERVER_ERROR_START_MESSAGE = "Error starting Compile Server: ";
public static final String USE_MEMORY_TEMP_CACHE_OPTION = "use.memory.temp.cache";
private final ChannelGroup myAllOpenChannels = new DefaultChannelGroup("compile-server");
private final ChannelFactory myChannelFactory;
@@ -99,7 +99,7 @@ public class Server {
}
});
ServerState.getInstance().setKeepTempCachesInMemory(System.getProperty(USE_MEMORY_TEMP_CACHE_OPTION) != null);
ServerState.getInstance().setKeepTempCachesInMemory(System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION) != null);
System.out.println("Server classpath: " + System.getProperty("java.class.path"));
System.err.println(SERVER_SUCCESS_START_MESSAGE + port);
@@ -125,12 +125,18 @@ compiler.perform.outputs.refresh.on.start.description=Whether to perform initial
compiler.max.static.constants.searches=10000
compiler.max.static.constants.searches.description=If the number of changed compile time constants exceeds this value, make will start full-project rebuild
compiler.server.heap.size=600
compiler.server.heap.size=300
compiler.server.heap.size.description=Heap size value in MB for the compile server process
compiler.server.use.memory.temp.cache=false
compiler.server.use.memory.temp.cache=true
compiler.server.use.memory.temp.cache.description=Store temporary data in memory for faster compilation; requires larger server heap size
compiler.server.use.external.javac.process=true
compiler.server.use.external.javac.process.description=Run javac compiler in external process (allows to run compile server with smaller heap size)
compiler.server.debug.port=-1
#compiler.server.javac.debug.port=-1
vcs.show.colored.annotations=true
vcs.showConsole=true