aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authornea <nea@nea.moe>2023-11-01 18:50:11 +0100
committernea <nea@nea.moe>2023-11-01 18:50:11 +0100
commit297cb01f220a617dd08096467978b2fccbc27695 (patch)
treed467f358313ce3648063da41b66361a840fa7864 /src/main
parentd5253dc5c3ae7b2cc1fcb96780e43b929a449eb4 (diff)
downloadModernJavaLauncher-297cb01f220a617dd08096467978b2fccbc27695.tar.gz
ModernJavaLauncher-297cb01f220a617dd08096467978b2fccbc27695.tar.bz2
ModernJavaLauncher-297cb01f220a617dd08096467978b2fccbc27695.zip
Add documentation
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/moe/nea/modernjava/launch/FCPEntryPoint.java18
-rw-r--r--src/main/java/moe/nea/modernjava/launch/live/FCPFixTweaker.java (renamed from src/main/java/moe/nea/modernjava/launch/FCPMixinAwareTweaker.java)8
-rw-r--r--src/main/java/moe/nea/modernjava/launch/relaunch/FCPRelauncher.java (renamed from src/main/java/moe/nea/modernjava/launch/FCPRelauncher.java)52
-rw-r--r--src/main/java/moe/nea/modernjava/launch/util/ClassLoaderManipulations.java10
-rw-r--r--src/main/java/moe/nea/modernjava/launch/util/ObjectHolderRefCompanion.java (renamed from src/main/java/moe/nea/modernjava/launch/util/ReflectionUtils.java)13
-rw-r--r--src/main/java/moe/nea/modernjava/launch/util/PropertyNames.java16
-rw-r--r--src/main/java/moe/nea/modernjava/launch/util/TextIoUtils.java22
-rw-r--r--src/main/java/moe/nea/modernjava/launch/util/WellKnownBlackboard.java (renamed from src/main/java/moe/nea/modernjava/launch/WellKnownBlackboard.java)12
-rw-r--r--src/main/java/net/minecraftforge/fml/nea/moe/modernjava/IAMFML.java9
-rw-r--r--src/main/kotlin/moe/nea/modernjava/launch/transform/TransObjectHolderRef.kt18
10 files changed, 143 insertions, 35 deletions
diff --git a/src/main/java/moe/nea/modernjava/launch/FCPEntryPoint.java b/src/main/java/moe/nea/modernjava/launch/FCPEntryPoint.java
index 3c32931..f7431ad 100644
--- a/src/main/java/moe/nea/modernjava/launch/FCPEntryPoint.java
+++ b/src/main/java/moe/nea/modernjava/launch/FCPEntryPoint.java
@@ -1,16 +1,25 @@
package moe.nea.modernjava.launch;
+import moe.nea.modernjava.launch.live.FCPFixTweaker;
import moe.nea.modernjava.launch.util.ClassLoaderManipulations;
+import moe.nea.modernjava.launch.util.WellKnownBlackboard;
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
import java.net.URI;
import java.util.List;
import java.util.Map;
+import static moe.nea.modernjava.launch.util.PropertyNames.HAS_RELAUNCHED;
+/**
+ * Global entrypoint for both the FML part of the relaunched (live) and the relaunching (relaunch) runs. Execution
+ * begins during static initialization to be as early as possible. There aren't any security implications, but especially
+ * on Windows it can be problematic if two processes try to open up the same file, so we try to avoid these conflicts.
+ * Also, it's just a faster launch.
+ */
@IFMLLoadingPlugin.Name("ModernJavaRelauncher")
public class FCPEntryPoint implements IFMLLoadingPlugin {
- static URI fileUri;
+ public static URI fileUri;
static {
try {
@@ -18,9 +27,10 @@ public class FCPEntryPoint implements IFMLLoadingPlugin {
} catch (Exception e) {
throw new RuntimeException(e);
}
- if (System.getProperty("modernjava.hasrelaunched") == null) {
+ if (System.getProperty(HAS_RELAUNCHED) == null) {
try {
- Class.forName("moe.nea.modernjava.launch.FCPRelauncher").getMethod("relaunch").invoke(null);
+ Class.forName("moe.nea.modernjava.launch.relaunch.FCPRelauncher")
+ .getMethod("relaunch").invoke(null);
} catch (Throwable t) {
System.out.println("Failed to relaunch");
t.printStackTrace();
@@ -32,7 +42,7 @@ public class FCPEntryPoint implements IFMLLoadingPlugin {
throw new RuntimeException(e);
}
List<String> tweakClasses = WellKnownBlackboard.tweakerNames();
- tweakClasses.add(FCPMixinAwareTweaker.class.getName());
+ tweakClasses.add(FCPFixTweaker.class.getName());
}
}
diff --git a/src/main/java/moe/nea/modernjava/launch/FCPMixinAwareTweaker.java b/src/main/java/moe/nea/modernjava/launch/live/FCPFixTweaker.java
index 585e943..a5bf648 100644
--- a/src/main/java/moe/nea/modernjava/launch/FCPMixinAwareTweaker.java
+++ b/src/main/java/moe/nea/modernjava/launch/live/FCPFixTweaker.java
@@ -1,12 +1,16 @@
-package moe.nea.modernjava.launch;
+package moe.nea.modernjava.launch.live;
+import moe.nea.modernjava.launch.transform.TransObjectHolderRef;
import net.minecraft.launchwrapper.ITweaker;
import net.minecraft.launchwrapper.LaunchClassLoader;
import java.io.File;
import java.util.List;
-public class FCPMixinAwareTweaker implements ITweaker {
+/**
+ * Tweaker class to inject {@link TransObjectHolderRef}
+ */
+public class FCPFixTweaker implements ITweaker {
@Override
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
}
diff --git a/src/main/java/moe/nea/modernjava/launch/FCPRelauncher.java b/src/main/java/moe/nea/modernjava/launch/relaunch/FCPRelauncher.java
index ec27694..04fb0ea 100644
--- a/src/main/java/moe/nea/modernjava/launch/FCPRelauncher.java
+++ b/src/main/java/moe/nea/modernjava/launch/relaunch/FCPRelauncher.java
@@ -1,12 +1,12 @@
-package moe.nea.modernjava.launch;
+package moe.nea.modernjava.launch.relaunch;
-import net.minecraft.launchwrapper.Launch;
+import moe.nea.modernjava.launch.util.PropertyNames;
+import moe.nea.modernjava.launch.util.TextIoUtils;
+import moe.nea.modernjava.launch.util.WellKnownBlackboard;
import net.minecraftforge.fml.common.launcher.FMLTweaker;
import net.minecraftforge.fml.nea.moe.modernjava.IAMFML;
import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
@@ -14,14 +14,17 @@ import java.util.List;
import java.util.Map;
public class FCPRelauncher {
- public static void relaunch() {
+ /**
+ * @return the original arguments, as passed to the main method.
+ */
+ public static List<String> getOriginalArguments() {
List<String> originalArgs = new ArrayList<>();
// Provided by FML
// This is highly processed so there might be some arguments that become lost, but almost everything should be in here.
// Namely non -- arguments get lost. I don't know any of these arguments that the vanilla launcher uses, so it should be fine?
- // Also some tweakers are missing. But we can fix this.
+ // Also, some tweakers are missing. But we can fix this.
Map<String, String> launchArgs = WellKnownBlackboard.launchArgs();
if ("UnknownFMLProfile".equals(launchArgs.get("--version"))) {
launchArgs.remove("--version");
@@ -34,15 +37,23 @@ public class FCPRelauncher {
originalArgs.add("--tweakClass");
originalArgs.add(FMLTweaker.class.getName());
-
System.out.println("Reconstructed original minecraft arguments: " + originalArgs);
+ return originalArgs;
+ }
+
+ public static File findJavaLauncher() {
+ return new File("/home/nea/.sdkman/candidates/java/16.0.2-tem/bin/java")
+ }
+
+ public static void relaunch() {
+
+ List<String> originalArgs = getOriginalArguments();
- String modernJavaPath = "/home/nea/.sdkman/candidates/java/16.0.2-tem/bin/java";
+ File modernJavaPath = findJavaLauncher();
- String thisJarFile = FCPEntryPoint.class.getProtectionDomain().getCodeSource().getLocation().getFile();
- thisJarFile = "/home/nea/src/ModernJavaLauncher/target/build/libs/target.jar";
- System.out.println("Found modern java jar at: " + thisJarFile);
+ File agentFile;
+ agentFile = new File("/home/nea/src/ModernJavaLauncher/target/build/libs/target.jar");
System.out.println("Located modern minecraft at: " + modernJavaPath);
@@ -58,19 +69,20 @@ public class FCPRelauncher {
List<String> fullCommandLine = new ArrayList<>();
- fullCommandLine.add(modernJavaPath);
+ fullCommandLine.add(modernJavaPath.getAbsolutePath());
fullCommandLine.addAll(ManagementFactory.getRuntimeMXBean().getInputArguments());
- fullCommandLine.add("-Dmodernjava.hasrelaunched=true");
- fullCommandLine.add("-Dmodernjava.relaunchclasspath=" + thisJarFile + File.pathSeparator + ManagementFactory.getRuntimeMXBean().getClassPath());
+ fullCommandLine.add("-D" + PropertyNames.HAS_RELAUNCHED + "=true");
+ fullCommandLine.add("-D" + PropertyNames.RELAUNCH_CLASSPATH + "=" + agentFile.getAbsolutePath() + File.pathSeparator + ManagementFactory.getRuntimeMXBean().getClassPath());
fullCommandLine.add("--illegal-access=permit");
for (String open : moduleOpens) {
fullCommandLine.add("--add-opens");
fullCommandLine.add(open);
}
- fullCommandLine.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005");
- fullCommandLine.add("-javaagent:" + thisJarFile);
+ if (System.getProperty(PropertyNames.DEBUG_PORT) != null)
+ fullCommandLine.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:" + System.getProperty(PropertyNames.DEBUG_PORT));
+ fullCommandLine.add("-javaagent:" + agentFile);
fullCommandLine.add("--add-modules=ALL-MODULE-PATH,ALL-SYSTEM,ALL-DEFAULT,java.sql");
- fullCommandLine.add("-Xbootclasspath/a:" + thisJarFile);
+ fullCommandLine.add("-Xbootclasspath/a:" + agentFile);
fullCommandLine.add("moe.nea.modernjava.target.RelaunchEntryPoint");
fullCommandLine.addAll(originalArgs);
@@ -84,11 +96,7 @@ public class FCPRelauncher {
Process process = processBuilder.start();
exitCode = process.waitFor();
} finally {
- try {
- new FileOutputStream(FileDescriptor.out).flush();
- new FileOutputStream(FileDescriptor.err).flush();
- } catch (IOException ignored) {
- }
+ TextIoUtils.flushStdIO();
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException("Failed to relaunch with old java version", e);
diff --git a/src/main/java/moe/nea/modernjava/launch/util/ClassLoaderManipulations.java b/src/main/java/moe/nea/modernjava/launch/util/ClassLoaderManipulations.java
index 09f2368..6cc21e9 100644
--- a/src/main/java/moe/nea/modernjava/launch/util/ClassLoaderManipulations.java
+++ b/src/main/java/moe/nea/modernjava/launch/util/ClassLoaderManipulations.java
@@ -1,6 +1,7 @@
package moe.nea.modernjava.launch.util;
import net.minecraft.launchwrapper.Launch;
+import net.minecraft.launchwrapper.LaunchClassLoader;
import java.io.File;
import java.lang.reflect.Method;
@@ -8,7 +9,10 @@ import java.net.MalformedURLException;
import java.net.URL;
public class ClassLoaderManipulations {
-
+ /**
+ * Adds a File to the parent class loader of the launch class loader. Necessary if you want to/have to use
+ * {@link LaunchClassLoader#addClassLoaderExclusion(String)}.
+ */
public static void addToParentClassLoader(File file) {
try {
addToParentClassLoader(file.toURI().toURL());
@@ -17,6 +21,10 @@ public class ClassLoaderManipulations {
}
}
+ /**
+ * Adds a URL to the parent class loader of the launch class loader. Necessary if you want to/have to use
+ * {@link LaunchClassLoader#addClassLoaderExclusion(String)}.
+ */
public static void addToParentClassLoader(URL file) {
try {
Launch.classLoader.addURL(file);
diff --git a/src/main/java/moe/nea/modernjava/launch/util/ReflectionUtils.java b/src/main/java/moe/nea/modernjava/launch/util/ObjectHolderRefCompanion.java
index abc2364..15f9450 100644
--- a/src/main/java/moe/nea/modernjava/launch/util/ReflectionUtils.java
+++ b/src/main/java/moe/nea/modernjava/launch/util/ObjectHolderRefCompanion.java
@@ -1,10 +1,15 @@
package moe.nea.modernjava.launch.util;
+import moe.nea.modernjava.launch.transform.TransObjectHolderRef;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
-public class ReflectionUtils {
+/**
+ * A companion to my transformations from {@link TransObjectHolderRef} to avoid
+ * having to write all of this out in bytecode.
+ */
+public class ObjectHolderRefCompanion {
private static Unsafe unsafe;
static {
@@ -17,10 +22,16 @@ public class ReflectionUtils {
}
}
+ /**
+ * A noop to have a jump target for the reflection factories.
+ */
public static void makeFieldWritable(Field f) {
String s = "Doing nothing. We will use unsafe to set the value instead, if possible";
}
+ /**
+ * Write a value to a static final field.
+ */
public static void doFieldWrite(Field field, Object object) throws IllegalAccessException {
if (unsafe == null) {
field.set(null, object);
diff --git a/src/main/java/moe/nea/modernjava/launch/util/PropertyNames.java b/src/main/java/moe/nea/modernjava/launch/util/PropertyNames.java
new file mode 100644
index 0000000..8540dde
--- /dev/null
+++ b/src/main/java/moe/nea/modernjava/launch/util/PropertyNames.java
@@ -0,0 +1,16 @@
+package moe.nea.modernjava.launch.util;
+
+public class PropertyNames {
+ /**
+ * Property set to indicate whether the java process was launched on the new java version.
+ */
+ public static final String HAS_RELAUNCHED = "modernjava.hasrelaunched";
+ /**
+ * Classpath to load after reloading.
+ */
+ public static final String RELAUNCH_CLASSPATH = "modernjava.relaunchclasspath";
+ /**
+ * Starts a debugger on the given port if present.
+ */
+ public static final String DEBUG_PORT = "modernjava.debugport";
+}
diff --git a/src/main/java/moe/nea/modernjava/launch/util/TextIoUtils.java b/src/main/java/moe/nea/modernjava/launch/util/TextIoUtils.java
new file mode 100644
index 0000000..b7f82c0
--- /dev/null
+++ b/src/main/java/moe/nea/modernjava/launch/util/TextIoUtils.java
@@ -0,0 +1,22 @@
+package moe.nea.modernjava.launch.util;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class TextIoUtils {
+ /**
+ * Flush out the standard IO, without closing it. Works even after {@link System#setOut(PrintStream)} or similar has been called
+ */
+ public static void flushStdIO() {
+ try {
+ // These streams should not be closed. We just want to flush them out
+ //noinspection resource
+ new FileOutputStream(FileDescriptor.out).flush();
+ //noinspection resource
+ new FileOutputStream(FileDescriptor.err).flush();
+ } catch (IOException ignored) {
+ }
+ }
+}
diff --git a/src/main/java/moe/nea/modernjava/launch/WellKnownBlackboard.java b/src/main/java/moe/nea/modernjava/launch/util/WellKnownBlackboard.java
index ee60b2a..967f531 100644
--- a/src/main/java/moe/nea/modernjava/launch/WellKnownBlackboard.java
+++ b/src/main/java/moe/nea/modernjava/launch/util/WellKnownBlackboard.java
@@ -1,16 +1,26 @@
-package moe.nea.modernjava.launch;
+package moe.nea.modernjava.launch.util;
import net.minecraft.launchwrapper.Launch;
import java.util.List;
import java.util.Map;
+/**
+ * Contains references to the {@link Launch#blackboard black board} in one central spot to avoid misspelling.
+ */
@SuppressWarnings("unchecked")
public class WellKnownBlackboard {
+ /**
+ * A list of tweaker class names yet to be executed. This does not include tweaker class names present in the current
+ * round of tweaking.
+ */
public static List<String> tweakerNames() {
return (List<String>) Launch.blackboard.get("TweakClasses");
}
+ /**
+ * A map of arguments in the form of --prefixedKey to value.
+ */
public static Map<String, String> launchArgs() {
return (Map<String, String>) Launch.blackboard.get("launchArgs");
}
diff --git a/src/main/java/net/minecraftforge/fml/nea/moe/modernjava/IAMFML.java b/src/main/java/net/minecraftforge/fml/nea/moe/modernjava/IAMFML.java
index 99ee7b0..d4d2844 100644
--- a/src/main/java/net/minecraftforge/fml/nea/moe/modernjava/IAMFML.java
+++ b/src/main/java/net/minecraftforge/fml/nea/moe/modernjava/IAMFML.java
@@ -1,7 +1,16 @@
package net.minecraftforge.fml.nea.moe.modernjava;
+import net.minecraftforge.fml.relauncher.FMLSecurityManager;
+
+/**
+ * Class in a package starting with {@code net.minecraftforge.fml} in order to easily bypass the {@link FMLSecurityManager}
+ * which disallows calling {@link System#exit(int)}.
+ */
public class IAMFML {
+ /**
+ * Calls {@link System#exit(int)}
+ */
public static void shutdown(int code) {
System.exit(code);
}
diff --git a/src/main/kotlin/moe/nea/modernjava/launch/transform/TransObjectHolderRef.kt b/src/main/kotlin/moe/nea/modernjava/launch/transform/TransObjectHolderRef.kt
index 2fb4d04..2687dfc 100644
--- a/src/main/kotlin/moe/nea/modernjava/launch/transform/TransObjectHolderRef.kt
+++ b/src/main/kotlin/moe/nea/modernjava/launch/transform/TransObjectHolderRef.kt
@@ -5,14 +5,22 @@ import dev.falsehonesty.asmhelper.dsl.instructions.InsnListBuilder
import dev.falsehonesty.asmhelper.dsl.instructions.InvokeType
import dev.falsehonesty.asmhelper.dsl.modify
import dev.falsehonesty.asmhelper.dsl.overwrite
+import moe.nea.modernjava.launch.util.ObjectHolderRefCompanion
import net.minecraft.launchwrapper.Launch
import net.minecraft.launchwrapper.LaunchClassLoader
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.AbstractInsnNode
import org.objectweb.asm.tree.FieldInsnNode
+/**
+ * Transform [net.minecraftforge.fml.common.registry.ObjectHolderRef] such that it does not make references to outdated
+ * Java Reflection Tools anymore
+ */
class TransObjectHolderRef : BaseClassTransformer() {
override fun makeTransformers() {
+ /**
+ * Redirect the makeWritable call to [ObjectHolderRefCompanion]
+ */
overwrite {
className = "net.minecraftforge.fml.common.registry.ObjectHolderRef"
methodName = "makeWritable"
@@ -22,13 +30,16 @@ class TransObjectHolderRef : BaseClassTransformer() {
aload(0/* arg0 */)
invoke(
InvokeType.STATIC,
- "moe/nea/modernjava/launch/util/ReflectionUtils",
+ "moe/nea/modernjava/launch/util/ObjectHolderRefCompanion",
"makeFieldWritable",
"(Ljava/lang/reflect/Field;)V"
)
methodReturn()
}
}
+ /**
+ * Redirect the reflection calls to write a value to a static field in apply to [ObjectHolderRefCompanion]
+ */
modify("net/minecraftforge/fml/common/registry/ObjectHolderRef") {
var end: AbstractInsnNode? = null
var start: AbstractInsnNode? = null
@@ -56,7 +67,7 @@ class TransObjectHolderRef : BaseClassTransformer() {
getField("net/minecraftforge/fml/common/registry/ObjectHolderRef", "field", "Ljava/lang/reflect/Field;")
aload(1 /*thing*/)
invokeStatic(
- "moe/nea/modernjava/launch/util/ReflectionUtils",
+ "moe/nea/modernjava/launch/util/ObjectHolderRefCompanion",
"doFieldWrite",
"(Ljava/lang/reflect/Field;Ljava/lang/Object;)V"
)
@@ -86,8 +97,7 @@ class TransObjectHolderRef : BaseClassTransformer() {
val classLoader: LaunchClassLoader = Launch.classLoader
classLoader.addTransformerExclusion("kotlin.")
- classLoader.addTransformerExclusion("dev.falsehonesty.asmhelper.")
- classLoader.addTransformerExclusion("org.objenesis.")
+ classLoader.addTransformerExclusion("moe.nea.modernjava.dep.asmhelper.")
classLoader.addTransformerExclusion(this.javaClass.name)
setup(classLoader)