[FEATURE][EXPERIMENTAL] Support add javafx in LauncherEngineWrapper

This commit is contained in:
Gravita 2023-11-26 15:07:50 +07:00
parent d678daac7b
commit 2e60d45c63
5 changed files with 65 additions and 32 deletions

View file

@ -105,7 +105,10 @@ public static boolean contains(String[] array, String value) {
public static void main(String... args) throws Throwable { public static void main(String... args) throws Throwable {
JVMHelper.checkStackTrace(LauncherEngineWrapper.class); JVMHelper.checkStackTrace(LauncherEngineWrapper.class);
JVMHelper.verifySystemProperties(Launcher.class, true); JVMHelper.verifySystemProperties(Launcher.class, false);
{
LauncherEngine.checkClass(LauncherEngine.class.getClassLoader().getClass());
}
EnvHelper.checkDangerousParams(); EnvHelper.checkDangerousParams();
//if(!LauncherAgent.isStarted()) throw new SecurityException("JavaAgent not set"); //if(!LauncherAgent.isStarted()) throw new SecurityException("JavaAgent not set");
verifyNoAgent(); verifyNoAgent();

View file

@ -1,8 +1,42 @@
package pro.gravit.launcher; package pro.gravit.launcher;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.launch.LaunchOptions;
import pro.gravit.utils.launch.ModuleLaunch;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@LauncherNetworkAPI @LauncherNetworkAPI
public class LauncherEngineWrapper { public class LauncherEngineWrapper {
private static final List<String> modules = new ArrayList<>();
static {
modules.add("javafx.base");
modules.add("javafx.graphics");
modules.add("javafx.fxml");
modules.add("javafx.controls");
modules.add("javafx.media");
modules.add("javafx.web");
}
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
LauncherEngine.main(args); ModuleLaunch launch = new ModuleLaunch();
LaunchOptions options = new LaunchOptions();
options.disablePackageDelegateSupport = true;
options.moduleConf = new LaunchOptions.ModuleConf();
List<Path> classpath = new ArrayList<>();
classpath.add(IOHelper.getCodeSource(LauncherEngine.class));
var libDirectory = Path.of(System.getProperty("java.home")).resolve("lib");
for(var moduleName : modules) {
var path = libDirectory.resolve(moduleName.concat(".jar"));
if(Files.exists(path)) {
options.moduleConf.modules.add(moduleName);
options.moduleConf.modulePath.add(path.toAbsolutePath().toString());
}
}
var control = launch.init(classpath, null, options);
launch.launch(LauncherEngine.class.getName(), null, List.of(args));
} }
} }

View file

@ -7,6 +7,7 @@
public class LaunchOptions { public class LaunchOptions {
public boolean enableHacks; public boolean enableHacks;
public boolean disablePackageDelegateSupport;
public ModuleConf moduleConf; public ModuleConf moduleConf;

View file

@ -18,10 +18,7 @@
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class ModuleLaunch implements Launch { public class ModuleLaunch implements Launch {
@ -31,8 +28,10 @@ public class ModuleLaunch implements Launch {
private ModuleFinder moduleFinder; private ModuleFinder moduleFinder;
private ModuleLayer layer; private ModuleLayer layer;
private MethodHandles.Lookup hackLookup; private MethodHandles.Lookup hackLookup;
private boolean disablePackageDelegateSupport;
@Override @Override
public ClassLoaderControl init(List<Path> files, String nativePath, LaunchOptions options) { public ClassLoaderControl init(List<Path> files, String nativePath, LaunchOptions options) {
this.disablePackageDelegateSupport = options.disablePackageDelegateSupport;
moduleClassLoader = new ModuleClassLoader(files.stream().map((e) -> { moduleClassLoader = new ModuleClassLoader(files.stream().map((e) -> {
try { try {
return e.toUri().toURL(); return e.toUri().toURL();
@ -122,6 +121,7 @@ public ClassLoaderControl init(List<Path> files, String nativePath, LaunchOption
} }
} }
} }
moduleClassLoader.initializeWithLayer(layer);
} }
return moduleClassLoader.makeControl(); return moduleClassLoader.makeControl();
} }
@ -160,6 +160,7 @@ private class ModuleClassLoader extends URLClassLoader {
private final ClassLoader SYSTEM_CLASS_LOADER = ClassLoader.getSystemClassLoader(); private final ClassLoader SYSTEM_CLASS_LOADER = ClassLoader.getSystemClassLoader();
private final List<ClassLoaderControl.ClassTransformer> transformers = new ArrayList<>(); private final List<ClassLoaderControl.ClassTransformer> transformers = new ArrayList<>();
private final Map<String, Class<?>> classMap = new ConcurrentHashMap<>(); private final Map<String, Class<?>> classMap = new ConcurrentHashMap<>();
private final Map<String, Module> packageToModule = new HashMap<>();
private String nativePath; private String nativePath;
private final List<String> packages = new ArrayList<>(); private final List<String> packages = new ArrayList<>();
@ -169,9 +170,17 @@ public ModuleClassLoader(URL[] urls, ClassLoader parent) {
packages.add("pro.gravit.utils."); packages.add("pro.gravit.utils.");
} }
private void initializeWithLayer(ModuleLayer layer) {
for(var m : layer.modules()) {
for(var p : m.getPackages()) {
packageToModule.put(p, m);
}
}
}
@Override @Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if(name != null) { if(name != null && !disablePackageDelegateSupport) {
for(String pkg : packages) { for(String pkg : packages) {
if(name.startsWith(pkg)) { if(name.startsWith(pkg)) {
return SYSTEM_CLASS_LOADER.loadClass(name); return SYSTEM_CLASS_LOADER.loadClass(name);
@ -220,6 +229,17 @@ protected Class<?> findClass(String moduleName, String name) {
} }
} }
} }
if(clazz == null && layer != null && name != null) {
var pkg = getPackageFromClass(name);
var module = packageToModule.get(pkg);
if(module != null) {
try {
clazz = module.getClassLoader().loadClass(name);
} catch (ClassNotFoundException e) {
return null;
}
}
}
if(clazz == null) { if(clazz == null) {
try { try {
clazz = super.findClass(name); clazz = super.findClass(name);

View file

@ -129,31 +129,6 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
args.add(context.executePath.toAbsolutePath().toString()); args.add(context.executePath.toAbsolutePath().toString());
args.addAll(context.args); args.addAll(context.args);
context.jvmProperties.forEach((key, value) -> args.add(String.format("-D%s=%s", key, value))); 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 = JavaHelper.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 = JavaHelper.tryAddModule(context.javaFXPaths, moduleName, modulesPath);
if (success) {
if (modulesAdd.length() > 0) modulesAdd.append(",");
modulesAdd.append(moduleName);
}
}
if (modulesAdd.length() > 0) {
args.add("--add-modules");
args.add(modulesAdd.toString());
}
if (modulesPath.length() > 0) {
args.add("--module-path");
args.add(modulesPath.toString());
}
}
if (context.memoryLimit != 0) { if (context.memoryLimit != 0) {
args.add(String.format("-Xmx%dM", context.memoryLimit)); args.add(String.format("-Xmx%dM", context.memoryLimit));
} }