Skip to content

Commit

Permalink
Update: ClassLoader.getPlatformClassLoader().loadModule()
Browse files Browse the repository at this point in the history
  • Loading branch information
xfl03 committed Jan 17, 2023
1 parent b21903f commit c076217
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 16 deletions.
3 changes: 2 additions & 1 deletion LocatorLoader/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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) {
Expand All @@ -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<URL> path = (ArrayList<URL>) unsafe.getObject(ucpObject, pathFieldOffset);
Field urlsField = findDeclaredField(classPathClass, "urls", "unopenedUrls");
long urlsFieldOffset = unsafe.objectFieldOffset(urlsField);
// System.out.println("3 " + ucpObject + urlsFieldOffset);
// noinspection ALL
Collection<URL> urls = (Collection<URL>) unsafe.getObject(ucpObject, urlsFieldOffset);
// noinspection ALL
Expand 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) {
Expand All @@ -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<Object> args) {
try {
method.invokeWithArguments(args);
} catch (Throwable e) {
TransformerService.logger.warn("Error invoke method: {}", e.toString());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
Expand Down

0 comments on commit c076217

Please sign in to comment.