[FEATURE] ClientLauncherWrapper reworked

This commit is contained in:
Gravita 2021-04-15 22:02:30 +07:00
parent 92e2a6c86d
commit 5bff221e7e
3 changed files with 111 additions and 52 deletions

View file

@ -10,11 +10,10 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.*;
public class ClientLauncherWrapper {
public static final String MAGIC_ARG = "-Djdk.attach.allowAttachSelf";
@ -51,66 +50,84 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
if (LogHelper.isDebugEnabled()) waitProcess = true;
}
LogHelper.info("Restart Launcher with JavaAgent...");
ProcessBuilder processBuilder = new ProcessBuilder();
if (waitProcess) processBuilder.inheritIO();
ClientLauncherWrapperContext context = new ClientLauncherWrapperContext();
context.processBuilder = new ProcessBuilder();
if (waitProcess) context.processBuilder.inheritIO();
JavaVersion javaVersion = null;
context.javaVersion = null;
try {
if (!noJavaCheck) javaVersion = findJava();
if (!noJavaCheck) context.javaVersion = findJava();
} catch (Throwable e) {
LogHelper.error(e);
}
if (javaVersion == null) {
javaVersion = JavaVersion.getCurrentJavaVersion();
if (context.javaVersion == null) {
context.javaVersion = JavaVersion.getCurrentJavaVersion();
}
Path javaBin = IOHelper.resolveJavaBin(javaVersion.jvmDir);
List<String> args = new LinkedList<>();
args.add(javaBin.toString());
context.executePath = IOHelper.resolveJavaBin(context.javaVersion.jvmDir);
//List<String> args = new LinkedList<>();
//args.add(javaBin.toString());
String pathLauncher = IOHelper.getCodeSource(LauncherEngine.class).toString();
args.add(JVMHelper.jvmProperty(LogHelper.DEBUG_PROPERTY, Boolean.toString(LogHelper.isDebugEnabled())));
args.add(JVMHelper.jvmProperty(LogHelper.STACKTRACE_PROPERTY, Boolean.toString(LogHelper.isStacktraceEnabled())));
args.add(JVMHelper.jvmProperty(LogHelper.DEV_PROPERTY, Boolean.toString(LogHelper.isDevEnabled())));
args.add(JVMHelper.jvmProperty("launcher.noSlf4j", "true")); //TODO: Normal fix
JVMHelper.addSystemPropertyToArgs(args, DirBridge.CUSTOMDIR_PROPERTY);
JVMHelper.addSystemPropertyToArgs(args, DirBridge.USE_CUSTOMDIR_PROPERTY);
JVMHelper.addSystemPropertyToArgs(args, DirBridge.USE_OPTDIR_PROPERTY);
JVMHelper.addSystemPropertyToArgs(args, DirWatcher.IGN_OVERFLOW);
if (javaVersion.version >= 9) {
LogHelper.debug("Found Java 9+ ( %s )", System.getProperty("java.version"));
String pathToFx = System.getenv("PATH_TO_FX");
Path fxPath = pathToFx == null ? null : Paths.get(pathToFx);
StringBuilder builder = new StringBuilder();
Path[] findPath = new Path[]{javaVersion.jvmDir, javaVersion.jvmDir.resolve("jre"), fxPath};
tryAddModule(findPath, "javafx.base", builder);
tryAddModule(findPath, "javafx.graphics", builder);
tryAddModule(findPath, "javafx.fxml", builder);
tryAddModule(findPath, "javafx.controls", builder);
boolean useSwing = tryAddModule(findPath, "javafx.swing", builder);
String modulePath = builder.toString();
if (!modulePath.isEmpty()) {
context.mainClass = LauncherEngine.class.getName();
context.memoryLimit = launcherMemoryLimit;
context.classpath.add(pathLauncher);
context.jvmProperties.put(LogHelper.DEBUG_PROPERTY, Boolean.toString(LogHelper.isDebugEnabled()));
context.jvmProperties.put(LogHelper.STACKTRACE_PROPERTY, Boolean.toString(LogHelper.isStacktraceEnabled()));
context.jvmProperties.put(LogHelper.DEV_PROPERTY, Boolean.toString(LogHelper.isDevEnabled()));
context.jvmProperties.put("launcher.noSlf4j", "true"); //TODO: Normal fix
context.addSystemProperty(DirBridge.CUSTOMDIR_PROPERTY);
context.addSystemProperty(DirBridge.USE_CUSTOMDIR_PROPERTY);
context.addSystemProperty(DirBridge.USE_OPTDIR_PROPERTY);
context.addSystemProperty(DirWatcher.IGN_OVERFLOW);
context.jvmModules.add("javafx.base");
context.jvmModules.add("javafx.graphics");
context.jvmModules.add("javafx.fxml");
context.jvmModules.add("javafx.controls");
context.jvmModules.add("javafx.swing");
context.args.add(MAGIC_ARG);
context.args.add("-XX:+DisableAttachMechanism");
EnvHelper.addEnv(context.processBuilder);
LauncherEngine.modulesManager.callWrapper(context);
// ---------
List<String> args = new ArrayList<>(16);
args.add(context.executePath.toAbsolutePath().toString());
args.addAll(context.args);
context.jvmProperties.forEach((key,value) -> args.add(String.format("-D%s=%s", key, value)));
if(context.javaVersion.version >= 9) {
context.javaFXPaths.add(context.javaVersion.jvmDir);
context.javaFXPaths.add(context.javaVersion.jvmDir.resolve("jre"));
Path openjfxPath = tryGetOpenJFXPath(context.javaVersion.jvmDir);
if(openjfxPath != null) {
context.javaFXPaths.add(openjfxPath);
}
StringBuilder modulesPath = new StringBuilder();
StringBuilder modulesAdd = new StringBuilder();
for(String moduleName : context.jvmModules) {
boolean success = tryAddModule(context.javaFXPaths, moduleName, modulesPath);
if(success) {
if(modulesAdd.length() > 0) modulesAdd.append(",");
modulesAdd.append(moduleName);
}
}
if(modulesAdd.length() > 0) {
args.add("--add-modules");
String javaModules = "javafx.base,javafx.fxml,javafx.controls,jdk.unsupported";
if (useSwing) javaModules = javaModules.concat(",javafx.swing");
args.add(javaModules);
args.add(modulesAdd.toString());
}
if(modulesPath.length() > 0) {
args.add("--module-path");
args.add(modulePath);
args.add(modulesPath.toString());
}
}
args.add(MAGIC_ARG);
args.add("-XX:+DisableAttachMechanism");
if (launcherMemoryLimit != 0) {
args.add(String.format("-Xmx%dM", launcherMemoryLimit));
if (context.memoryLimit != 0) {
args.add(String.format("-Xmx%dM", context.memoryLimit));
}
//Collections.addAll(args, "-javaagent:".concat(pathLauncher));
args.add("-cp");
args.add(pathLauncher);
args.add(LauncherEngine.class.getName());
LauncherEngine.modulesManager.callWrapper(processBuilder, args);
EnvHelper.addEnv(processBuilder);
args.add(String.join(IOHelper.PLATFORM_SEPARATOR, context.classpath));
args.add(context.mainClass);
args.addAll(context.clientArgs);
LogHelper.debug("Commandline: " + args);
processBuilder.command(args);
Process process = processBuilder.start();
context.processBuilder.command(args);
Process process = context.processBuilder.start();
if (!waitProcess) {
Thread.sleep(3000);
if (!process.isAlive()) {
@ -127,6 +144,27 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
}
}
public static Path tryGetOpenJFXPath(Path jvmDir) {
String dirName = jvmDir.getFileName().toString();
Path parent = jvmDir.getParent();
if(parent == null) return null;
Path archJFXPath = parent.resolve(dirName.replace("openjdk", "openjfx"));
if(Files.isDirectory(archJFXPath)) {
return archJFXPath;
}
Path arch2JFXPath = parent.resolve(dirName.replace("jdk", "openjfx"));
if(Files.isDirectory(arch2JFXPath)) {
return arch2JFXPath;
}
if(JVMHelper.OS_TYPE == JVMHelper.OS.LINUX) {
Path debianJfxPath = Paths.get("/usr/share/openjfx");
if(Files.isDirectory(debianJfxPath)) {
return debianJfxPath;
}
}
return null;
}
public static Path tryFindModule(Path path, String moduleName) {
Path result = path.resolve(moduleName.concat(".jar"));
LogHelper.dev("Try resolve %s", result.toString());
@ -138,7 +176,7 @@ public static Path tryFindModule(Path path, String moduleName) {
else return result;
}
public static boolean tryAddModule(Path[] paths, String moduleName, StringBuilder args) {
public static boolean tryAddModule(List<Path> paths, String moduleName, StringBuilder args) {
for (Path path : paths) {
if (path == null) continue;
Path result = tryFindModule(path, moduleName);
@ -248,4 +286,22 @@ public static boolean isExistExtJavaLibrary(Path jvmDir, String name) {
return IOHelper.isFile(jrePath) || IOHelper.isFile(jdkPath);
}
}
public static class ClientLauncherWrapperContext {
public JavaVersion javaVersion;
public Path executePath;
public String mainClass;
public int memoryLimit;
public ProcessBuilder processBuilder;
public List<String> args = new ArrayList<>(8);
public Map<String, String> jvmProperties = new HashMap<>();
public List<String> classpath = new ArrayList<>();
public List<String> jvmModules = new ArrayList<>();
public List<String> clientArgs = new ArrayList<>();
public List<Path> javaFXPaths = new ArrayList<>();
public void addSystemProperty(String name) {
String property = System.getProperty(name);
if (property != null)
jvmProperties.put(name, property);
}
}
}

View file

@ -1,5 +1,6 @@
package pro.gravit.launcher.client;
import pro.gravit.launcher.ClientLauncherWrapper;
import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.LauncherTrustManager;
import pro.gravit.launcher.modules.LauncherModule;
@ -33,10 +34,10 @@ public final boolean verifyClassCheckResult(LauncherTrustManager.CheckClassResul
return result.type == LauncherTrustManager.CheckClassResultType.SUCCESS;
}
public void callWrapper(ProcessBuilder processBuilder, Collection<String> jvmArgs) {
public void callWrapper(ClientLauncherWrapper.ClientLauncherWrapperContext context) {
for (LauncherModule module : modules) {
if (module instanceof ClientWrapperModule) {
((ClientWrapperModule) module).wrapperPhase(processBuilder, jvmArgs);
((ClientWrapperModule) module).wrapperPhase(context);
}
}
}

View file

@ -1,7 +1,9 @@
package pro.gravit.launcher.client;
import pro.gravit.launcher.ClientLauncherWrapper;
import java.util.Collection;
public interface ClientWrapperModule {
void wrapperPhase(ProcessBuilder processBuilder, Collection<String> jvmArgs);
void wrapperPhase(ClientLauncherWrapper.ClientLauncherWrapperContext context);
}