JNI注入Jar调用方法时出现NoClassDefFoundError问题求助
问题分析
抛出NoClassDefFoundError的核心原因是注入Jar使用的类加载器无法访问到父进程中net.minecraft.client.Minecraft类的类加载器。Java类加载器遵循双亲委派模型,注入操作常用的自定义类加载器(比如URLClassLoader)默认父加载器是系统类加载器,但Minecraft类通常由游戏专属的类加载器(如LaunchClassLoader)加载,不在系统类加载器的搜索路径范围内,导致自定义加载器无法找到该类。
解决方案
将目标类加载器设为自定义加载器的父加载器
先通过反射获取父进程中加载Minecraft类的类加载器,再以它作为父加载器创建自定义类加载器来加载你的Jar类。示例代码:// 获取Minecraft类对应的类加载器 Class<?> minecraftClass = Class.forName("net.minecraft.client.Minecraft"); ClassLoader minecraftClassLoader = minecraftClass.getClassLoader(); // 基于该类加载器创建自定义加载器,加载注入Jar URL[] jarUrls = new URL[]{new File("your-injected.jar").toURI().toURL()}; URLClassLoader customLoader = new URLClassLoader(jarUrls, minecraftClassLoader); // 加载目标类并调用静态方法 Class<?> yourClass = customLoader.loadClass("your.package.YourClass"); Method method = yourClass.getMethod("doStuffIdk"); method.invoke(null);直接向目标类加载器添加Jar路径
如果有权限操作目标类加载器,可直接将你的Jar路径添加到其搜索路径中,无需创建新加载器。以Minecraft的LaunchClassLoader为例:Class<?> launcherClass = Class.forName("net.minecraft.launchwrapper.LaunchClassLoader"); Method addURLMethod = launcherClass.getDeclaredMethod("addURL", URL.class); addURLMethod.setAccessible(true); // 将Jar路径注入到Minecraft类加载器 addURLMethod.invoke(minecraftClassLoader, new File("your-injected.jar").toURI().toURL()); // 直接用Minecraft类加载器加载你的类并调用方法 Class<?> yourClass = minecraftClassLoader.loadClass("your.package.YourClass"); yourClass.getMethod("doStuffIdk").invoke(null);统一线程上下文类加载器
调用静态方法前,将当前线程的上下文类加载器设置为Minecraft的类加载器,避免部分场景下的类加载路径不一致问题:Thread.currentThread().setContextClassLoader(minecraftClassLoader);
内容的提问来源于stack exchange,提问作者Derek Li
相关产品推荐
相关产品推荐

