mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8256308: Send arguments to javac server in a config file
Reviewed-by: erikj, jfranck
This commit is contained in:
parent
8f7caa4353
commit
9e4944f7b6
@ -177,6 +177,12 @@ define SetupJavaCompilationBody
|
||||
$$(error Must specify BIN (in $1))
|
||||
endif
|
||||
|
||||
ifneq ($$($1_MODULE), )
|
||||
$1_MODULE_SUBDIR := /$$($1_MODULE)
|
||||
endif
|
||||
|
||||
$1_SAFE_NAME := $$(strip $$(subst /,_, $1))
|
||||
|
||||
ifeq ($$($1_SMALL_JAVA), )
|
||||
# If unspecified, default to true
|
||||
$1_SMALL_JAVA := true
|
||||
@ -215,18 +221,35 @@ define SetupJavaCompilationBody
|
||||
ifeq ($$(ENABLE_JAVAC_SERVER)+$$($1_CLASSPATH), true+)
|
||||
$1_JAVAC := $$(INTERIM_LANGTOOLS_ARGS) -m jdk.compiler.interim/com.sun.tools.sjavac.Main
|
||||
|
||||
# How to launch the server. This must use JAVA_DETACH, which is the "big" java
|
||||
# with an ability to detach from fixpath (on Windows)
|
||||
# This will be executed by the client, if needed.
|
||||
$1_JAVAC_SERVER_CMD := $$(JAVA_DETACH) $$($1_JAVA_FLAGS) $$($1_JAVAC)
|
||||
$1_ESCAPED_CMD := $$(subst $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_JAVAC_SERVER_CMD))))
|
||||
# Create a configuration file with the needed information for the javac
|
||||
# server to function properly.
|
||||
$1_JAVAC_SERVER_CONFIG := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)-server.conf
|
||||
|
||||
# The port file contains the tcp/ip on which the server listens
|
||||
# The portfile contains the tcp/ip on which the server listens
|
||||
# and the cookie necessary to talk to the server.
|
||||
$1_JAVA_SERVER_FLAGS := --server:portfile=$$(JAVAC_SERVER_DIR)/server.port,sjavac=$$($1_ESCAPED_CMD)
|
||||
$1_JAVAC_PORT_FILE := $$(JAVAC_SERVER_DIR)/server.port
|
||||
|
||||
# Always use small to launch client
|
||||
$1_JAVAC_CMD := $$(JAVA_SMALL) $$($1_JAVA_FLAGS) $$($1_JAVAC) $$($1_JAVA_SERVER_FLAGS)
|
||||
# The servercmd specified how to launch the server. This must use
|
||||
# JAVA_DETACH, which is the "big" java with an ability to detach from
|
||||
# fixpath (on Windows) This will be executed by the client, if needed.
|
||||
$1_JAVAC_SERVER_CMD := $$(JAVA_DETACH) $$($1_JAVA_FLAGS) $$($1_JAVAC)
|
||||
|
||||
$1_CONFIG_VARDEPS := $$($1_JAVAC_PORT_FILE) $$($1_JAVAC_SERVER_CMD)
|
||||
$1_CONFIG_VARDEPS_FILE := $$(call DependOnVariable, $1_CONFIG_VARDEPS, \
|
||||
$$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1.config_vardeps)
|
||||
|
||||
ifeq ($(call isBuildOs, windows), true)
|
||||
$1_ECHO_COMMAND := $(FIXPATH) cmd /c echo
|
||||
else
|
||||
$1_ECHO_COMMAND := $(ECHO)
|
||||
endif
|
||||
$$($1_JAVAC_SERVER_CONFIG): $$($1_CONFIG_VARDEPS_FILE)
|
||||
$$($1_ECHO_COMMAND) portfile=$$($1_JAVAC_PORT_FILE) > $$@
|
||||
$$($1_ECHO_COMMAND) servercmd=$$($1_JAVAC_SERVER_CMD) >> $$@
|
||||
|
||||
# Always use small java to launch client
|
||||
$1_JAVAC_CMD := $$(JAVA_SMALL) $$($1_JAVA_FLAGS) $$($1_JAVAC) \
|
||||
--server:conf=$$($1_JAVAC_SERVER_CONFIG)
|
||||
else
|
||||
# No javac server
|
||||
$1_JAVAC := $$(INTERIM_LANGTOOLS_ARGS) -m jdk.compiler.interim/com.sun.tools.javac.Main
|
||||
@ -263,10 +286,6 @@ define SetupJavaCompilationBody
|
||||
$1_FLAGS += -cp $$(call PathList, $$($1_CLASSPATH))
|
||||
endif
|
||||
|
||||
ifneq ($$($1_MODULE), )
|
||||
$1_MODULE_SUBDIR := /$$($1_MODULE)
|
||||
endif
|
||||
|
||||
# Make sure the dirs exist, or that one of the EXTRA_FILES, that may not
|
||||
# exist yet, is in it.
|
||||
$$(foreach d, $$($1_SRC), \
|
||||
@ -331,9 +350,6 @@ define SetupJavaCompilationBody
|
||||
$$(error No source files found for $1)
|
||||
endif
|
||||
else
|
||||
|
||||
$1_SAFE_NAME := $$(strip $$(subst /,_, $1))
|
||||
|
||||
# All files below META-INF are always copied.
|
||||
$1_ALL_COPIES := $$(filter $$(addsuffix /META-INF%,$$($1_SRC)),$$($1_ALL_SRCS))
|
||||
# Find all files to be copied from source to bin.
|
||||
@ -442,7 +458,7 @@ define SetupJavaCompilationBody
|
||||
|
||||
# Do the actual compilation
|
||||
$$($1_COMPILE_TARGET): $$($1_SRCS) $$($1_FILELIST) $$($1_DEPENDS) \
|
||||
$$($1_VARDEPS_FILE) $$($1_EXTRA_DEPS)
|
||||
$$($1_VARDEPS_FILE) $$($1_EXTRA_DEPS) $$($1_JAVAC_SERVER_CONFIG)
|
||||
$$(call MakeDir, $$(@D))
|
||||
$$(call ExecuteWithLog, $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)_batch, \
|
||||
$$($1_JAVAC_CMD) $$($1_FLAGS) \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -79,15 +79,23 @@ public class Util {
|
||||
return extractStringOption(opName, s, null);
|
||||
}
|
||||
|
||||
public static String extractStringOption(String opName, String s, String deflt) {
|
||||
private static String extractStringOptionWithDelimiter(String opName, String s, String deflt, char delimiter) {
|
||||
int p = s.indexOf(opName+"=");
|
||||
if (p == -1) return deflt;
|
||||
p+=opName.length()+1;
|
||||
int pe = s.indexOf(',', p);
|
||||
int pe = s.indexOf(delimiter, p);
|
||||
if (pe == -1) pe = s.length();
|
||||
return s.substring(p, pe);
|
||||
}
|
||||
|
||||
public static String extractStringOption(String opName, String s, String deflt) {
|
||||
return extractStringOptionWithDelimiter(opName, s, deflt, ',');
|
||||
}
|
||||
|
||||
public static String extractStringOptionLine(String opName, String s, String deflt) {
|
||||
return extractStringOptionWithDelimiter(opName, s, deflt, '\n').strip();
|
||||
}
|
||||
|
||||
public static boolean extractBooleanOption(String opName, String s, boolean deflt) {
|
||||
String str = extractStringOption(opName, s);
|
||||
return "true".equals(str) ? true
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,6 +34,9 @@ import java.io.Reader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -42,15 +45,11 @@ import com.sun.tools.javac.main.Main;
|
||||
import com.sun.tools.javac.main.Main.Result;
|
||||
import com.sun.tools.sjavac.Log;
|
||||
import com.sun.tools.sjavac.Util;
|
||||
import com.sun.tools.sjavac.options.OptionHelper;
|
||||
import com.sun.tools.sjavac.options.Options;
|
||||
import com.sun.tools.sjavac.server.CompilationSubResult;
|
||||
import com.sun.tools.sjavac.server.PortFile;
|
||||
import com.sun.tools.sjavac.server.Sjavac;
|
||||
import com.sun.tools.sjavac.server.SjavacServer;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
/**
|
||||
* Sjavac implementation that delegates requests to a SjavacServer.
|
||||
*
|
||||
@ -61,59 +60,58 @@ import static java.util.stream.Collectors.joining;
|
||||
*/
|
||||
public class SjavacClient implements Sjavac {
|
||||
|
||||
// The id can perhaps be used in the future by the javac server to reuse the
|
||||
// JavaCompiler instance for several compiles using the same id.
|
||||
private final String id;
|
||||
private final PortFile portFile;
|
||||
private PortFile portFile;
|
||||
|
||||
// Default keepalive for server is 120 seconds.
|
||||
// I.e. it will accept 120 seconds of inactivity before quitting.
|
||||
private final int keepalive;
|
||||
private final int poolsize;
|
||||
|
||||
// The sjavac option specifies how the server part of sjavac is spawned.
|
||||
// If you have the experimental sjavac in your path, you are done. If not, you have
|
||||
// to point to a com.sun.tools.sjavac.Main that supports --startserver
|
||||
// for example by setting: sjavac=java%20-jar%20...javac.jar%com.sun.tools.sjavac.Main
|
||||
private final String sjavacForkCmd;
|
||||
// The servercmd option specifies how the server part of sjavac is spawned.
|
||||
// It should point to a com.sun.tools.sjavac.Main that supports --startserver
|
||||
private String serverCommand;
|
||||
|
||||
// Accept 120 seconds of inactivity before quitting.
|
||||
private static final int KEEPALIVE = 120;
|
||||
private static final int POOLSIZE = Runtime.getRuntime().availableProcessors();
|
||||
// Wait 2 seconds for response, before giving up on javac server.
|
||||
static int CONNECTION_TIMEOUT = 2000;
|
||||
static int MAX_CONNECT_ATTEMPTS = 3;
|
||||
static int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000;
|
||||
|
||||
// Store the server conf settings here.
|
||||
private final String settings;
|
||||
private static final int CONNECTION_TIMEOUT = 2000;
|
||||
private static final int MAX_CONNECT_ATTEMPTS = 3;
|
||||
private static final int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000;
|
||||
|
||||
public SjavacClient(Options options) {
|
||||
String tmpServerConf = options.getServerConf();
|
||||
String serverConf = (tmpServerConf!=null)? tmpServerConf : "";
|
||||
String tmpId = Util.extractStringOption("id", serverConf);
|
||||
id = (tmpId!=null) ? tmpId : "id"+(((new java.util.Random()).nextLong())&Long.MAX_VALUE);
|
||||
String defaultPortfile = options.getDestDir()
|
||||
.resolve("javac_server")
|
||||
.toAbsolutePath()
|
||||
.toString();
|
||||
String portfileName = Util.extractStringOption("portfile", serverConf, defaultPortfile);
|
||||
portFile = SjavacServer.getPortFile(portfileName);
|
||||
sjavacForkCmd = Util.extractStringOption("sjavac", serverConf, "sjavac");
|
||||
int poolsize = Util.extractIntOption("poolsize", serverConf);
|
||||
keepalive = Util.extractIntOption("keepalive", serverConf, 120);
|
||||
String serverConf = options.getServerConf();
|
||||
String configFile = Util.extractStringOption("conf", serverConf, "");
|
||||
|
||||
this.poolsize = poolsize > 0 ? poolsize : Runtime.getRuntime().availableProcessors();
|
||||
settings = (serverConf.equals("")) ? "id="+id+",portfile="+portfileName : serverConf;
|
||||
}
|
||||
try {
|
||||
List<String> configFileLines = Files.readAllLines(Path.of(configFile), StandardCharsets.UTF_8);
|
||||
String configFileContent = String.join("\n", configFileLines);
|
||||
|
||||
/**
|
||||
* Hand out the server settings.
|
||||
* @return The server settings, possibly a default value.
|
||||
*/
|
||||
public String serverSettings() {
|
||||
return settings;
|
||||
String portfileName = Util.extractStringOptionLine("portfile", configFileContent, "");
|
||||
if (portfileName.isEmpty()) {
|
||||
Log.error("Configuration file missing value for 'portfile'");
|
||||
portFile = null;
|
||||
} else {
|
||||
portFile = SjavacServer.getPortFile(portfileName);
|
||||
}
|
||||
|
||||
String serverCommandString = Util.extractStringOptionLine("servercmd", configFileContent, "");
|
||||
if (serverCommandString.isEmpty()) {
|
||||
Log.error("Configuration file missing value for 'servercmd'");
|
||||
serverCommand = null;
|
||||
} else {
|
||||
serverCommand = serverCommandString;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.error("Cannot read configuration file " + configFile);
|
||||
Log.debug(e);
|
||||
portFile = null;
|
||||
serverCommand = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result compile(String[] args) {
|
||||
if (portFile == null || serverCommand == null) {
|
||||
Log.error("Incorrect configuration, portfile and/or servercmd missing");
|
||||
return Result.ERROR;
|
||||
}
|
||||
|
||||
Result result = null;
|
||||
try (Socket socket = tryConnect()) {
|
||||
PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
|
||||
@ -176,7 +174,7 @@ public class SjavacClient implements Sjavac {
|
||||
* Makes MAX_CONNECT_ATTEMPTS attempts to connect to server.
|
||||
*/
|
||||
private Socket tryConnect() throws IOException, InterruptedException {
|
||||
makeSureServerIsRunning(portFile);
|
||||
makeSureServerIsRunning();
|
||||
int attempt = 0;
|
||||
while (true) {
|
||||
Log.debug("Trying to connect. Attempt " + (++attempt) + " of " + MAX_CONNECT_ATTEMPTS);
|
||||
@ -206,7 +204,7 @@ public class SjavacClient implements Sjavac {
|
||||
* Will return immediately if a server already seems to be running,
|
||||
* otherwise fork a new server and block until it seems to be running.
|
||||
*/
|
||||
private void makeSureServerIsRunning(PortFile portFile)
|
||||
private void makeSureServerIsRunning()
|
||||
throws IOException, InterruptedException {
|
||||
|
||||
if (portFile.exists()) {
|
||||
@ -221,10 +219,7 @@ public class SjavacClient implements Sjavac {
|
||||
}
|
||||
|
||||
// Fork a new server and wait for it to start
|
||||
SjavacClient.fork(sjavacForkCmd,
|
||||
portFile,
|
||||
poolsize,
|
||||
keepalive);
|
||||
startNewServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -235,14 +230,14 @@ public class SjavacClient implements Sjavac {
|
||||
/*
|
||||
* Fork a server process process and wait for server to come around
|
||||
*/
|
||||
public static void fork(String sjavacCmd, PortFile portFile, int poolsize, int keepalive)
|
||||
public void startNewServer()
|
||||
throws IOException, InterruptedException {
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.addAll(Arrays.asList(OptionHelper.unescapeCmdArg(sjavacCmd).split(" ")));
|
||||
cmd.addAll(Arrays.asList(serverCommand.split(" ")));
|
||||
cmd.add("--startserver:"
|
||||
+ "portfile=" + portFile.getFilename()
|
||||
+ ",poolsize=" + poolsize
|
||||
+ ",keepalive="+ keepalive);
|
||||
+ ",poolsize=" + POOLSIZE
|
||||
+ ",keepalive="+ KEEPALIVE);
|
||||
|
||||
Process serverProcess;
|
||||
Log.debug("Starting server. Command: " + String.join(" ", cmd));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user