diff --git a/LocatorLoader/build.gradle b/LocatorLoader/build.gradle index ba9ac9c..3f5fe49 100644 --- a/LocatorLoader/build.gradle +++ b/LocatorLoader/build.gradle @@ -40,7 +40,8 @@ dependencies { implementation("org.ow2.asm:asm:9.3") implementation("org.ow2.asm:asm-tree:9.3") implementation("org.ow2.asm:asm-commons:9.3") - implementation "cpw.mods:modlauncher:2.1.+" + implementation "cpw.mods:modlauncher:8.1.3" + implementation "cpw.mods:securejarhandler:2.1.6" implementation 'org.jetbrains:annotations:23.1.0' implementation "org.apache.logging.log4j:log4j-api:2.19.0" } diff --git a/LocatorLoader/src/main/java/me/xfl03/morecrashinfo/modlauncher/ClasspathHelper.java b/LocatorLoader/src/main/java/me/xfl03/morecrashinfo/modlauncher/ClasspathHelper.java index 1ec6725..3dff488 100644 --- a/LocatorLoader/src/main/java/me/xfl03/morecrashinfo/modlauncher/ClasspathHelper.java +++ b/LocatorLoader/src/main/java/me/xfl03/morecrashinfo/modlauncher/ClasspathHelper.java @@ -1,13 +1,17 @@ package me.xfl03.morecrashinfo.modlauncher; +import cpw.mods.cl.JarModuleFinder; +import cpw.mods.jarhandling.SecureJar; import sun.misc.Unsafe; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; +import java.util.*; public class ClasspathHelper { public static void add(ClassLoader classLoader, Path file) throws Throwable { @@ -17,6 +21,7 @@ public static void add(ClassLoader classLoader, Path file) throws Throwable { Method addURLMethod = classLoaderClass.getDeclaredMethod("addURL", URL.class); addURLMethod.setAccessible(true); addURLMethod.invoke(classLoader, file.toUri().toURL()); + TransformerService.logger.info("Added {} to {}", file, classLoader); return; } } catch (ClassNotFoundException ignored) { @@ -30,14 +35,36 @@ public static void add(ClassLoader classLoader, Path file) throws Throwable { Unsafe unsafe = (Unsafe) unsafeField.get(null); Field ucpField = findDeclaredField(classLoaderClass, "ucp"); long ucpFieldOffset = unsafe.objectFieldOffset(ucpField); +// System.out.println("1 " + classLoader + ucpFieldOffset); Object ucpObject = unsafe.getObject(classLoader, ucpFieldOffset); + if (ucpObject == null) { + //PlatformClassLoader + //Get IMPL_LOOKUP + Field implLookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); + MethodHandles.Lookup lookup = (MethodHandles.Lookup) + unsafe.getObject(unsafe.staticFieldBase(implLookupField), + unsafe.staticFieldOffset(implLookupField)); + + //Invoke loadModule + Class moduleReferenceClass = Class.forName("java.lang.module.ModuleReference"); + MethodHandle mh = lookup.findVirtual(classLoaderClass, "loadModule", + MethodType.methodType(void.class, moduleReferenceClass)); +// mh.bindTo(classLoader); + JarModuleFinder finder = JarModuleFinder.of(SecureJar.from(file)); + finder.findAll().forEach(it -> tryInvoke(mh, Arrays.asList(classLoader, it))); + TransformerService.logger.info("Added {} to {}", file, classLoader); + return; +// throw new IllegalStateException("ucp is null"); + } Class classPathClass = Class.forName("jdk.internal.loader.URLClassPath"); Field pathField = classPathClass.getDeclaredField("path"); long pathFieldOffset = unsafe.objectFieldOffset(pathField); +// System.out.println("2 " + ucpObject + pathFieldOffset); // noinspection ALL ArrayList path = (ArrayList) unsafe.getObject(ucpObject, pathFieldOffset); Field urlsField = findDeclaredField(classPathClass, "urls", "unopenedUrls"); long urlsFieldOffset = unsafe.objectFieldOffset(urlsField); +// System.out.println("3 " + ucpObject + urlsFieldOffset); // noinspection ALL Collection urls = (Collection) unsafe.getObject(ucpObject, urlsFieldOffset); // noinspection ALL @@ -47,6 +74,7 @@ public static void add(ClassLoader classLoader, Path file) throws Throwable { path.add(file.toUri().toURL()); } } + TransformerService.logger.info("Added {} to {}", file, classLoader); return; } } catch (ClassNotFoundException ignored) { @@ -69,4 +97,12 @@ private static Field findDeclaredField(Class type, String... names) throws No } throw new NoSuchFieldException(String.join(", ", names)); } + + private static void tryInvoke(MethodHandle method, List args) { + try { + method.invokeWithArguments(args); + } catch (Throwable e) { + TransformerService.logger.warn("Error invoke method: {}", e.toString()); + } + } } \ No newline at end of file diff --git a/LocatorLoader/src/main/java/me/xfl03/morecrashinfo/modlauncher/TransformerService.java b/LocatorLoader/src/main/java/me/xfl03/morecrashinfo/modlauncher/TransformerService.java index 26f174d..0916905 100644 --- a/LocatorLoader/src/main/java/me/xfl03/morecrashinfo/modlauncher/TransformerService.java +++ b/LocatorLoader/src/main/java/me/xfl03/morecrashinfo/modlauncher/TransformerService.java @@ -61,19 +61,23 @@ public void initialize(IEnvironment environment) { String.format("tmp/MoreCrashInfo-Locator-%s.jar", VersionUtil.getMinecraftVersion())); JarRemapper remapper = new JarRemapper(); remapper.processJar(modPath, mapped); - try { - ClasspathHelper.add(Launcher.class.getClassLoader(), mapped); - return; - } catch (Throwable e) { - logger.warn("Error while appendToClassPath {}", Launcher.class.getClassLoader()); - logger.warn(e); - } - try { - Method method = ClassLoader.class.getMethod("getPlatformClassLoader"); - ClasspathHelper.add((ClassLoader) method.invoke(null), mapped); - } catch (Throwable e) { - logger.warn("Error while appendToClassPath getPlatformClassLoader"); - logger.warn(e); + if (VersionUtil.getMinecraftMajorVersion() < 17) { + //Before 1.17, we can add jar to AppClassLoader + try { + ClasspathHelper.add(Launcher.class.getClassLoader(), mapped); + } catch (Throwable e) { + logger.warn("Error while appendToClassPath {}", Launcher.class.getClassLoader()); + logger.warn(e); + } + } else { + //After 1.17, we need to add jar as module to PlatformClassLoader + try { + Method method = ClassLoader.class.getMethod("getPlatformClassLoader"); + ClasspathHelper.add((ClassLoader) method.invoke(null), mapped); + } catch (Throwable e) { + logger.warn("Error while appendToClassPath getPlatformClassLoader"); + logger.warn(e); + } } } } diff --git a/LocatorLoader/src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator b/LocatorLoader/src/main/resources/META-INF/services/unused.net.minecraftforge.forgespi.locating.IModLocator similarity index 100% rename from LocatorLoader/src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator rename to LocatorLoader/src/main/resources/META-INF/services/unused.net.minecraftforge.forgespi.locating.IModLocator