从 jar 加载外部 类 时,javassist 抛出 ClassNotFoundException
javassist throws ClassNotFoundException when loading external classes from jar
我正在尝试使用 javassist 加载外部 jar 文件并在运行时调用其主要方法,但是当我尝试使用以下代码执行此操作时:
File file = new File("C:\Users\MainPC\Desktop\test.jar");
ClassPool cp = ClassPool.getDefault();
cp.insertClassPath(file.getAbsolutePath());
Class<?> MainClass = cp.get("TestPackage.MainClass").toClass();
MainClass.getMethod("main", String[].class).invoke(null, new Object[] {args});
它抛出以下异常:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at ReflectionTests.main(ReflectionTests.java:99)
Caused by: java.lang.NoClassDefFoundError: TestPackage/OtherClass
at TestPackage.MainClass.main(Unknown Source)
... 5 more
Caused by: java.lang.ClassNotFoundException: TestPackage.OtherClass
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 6 more
当我仅使用内置 java 反射 api 尝试同样的事情时,它没有问题:
File file = new File("C:\Users\MainPC\Desktop\test.jar");
URLClassLoader cl = new URLClassLoader(new URL[] {new URL("jar:file:"+file.getAbsoluteFile()+"!/")});
Class<?> clazz = cl.loadClass("TestPackage.MainClass");
clazz.getMethod("main", String[].class).invoke(null, new Object[] {args});
(上面没有抛出异常并按预期调用 jar 文件的主要方法)
这让我相信我在 javassist 中做错了什么(特别是在加载 jar 文件 classes 时)。有人可以向我解释它是什么吗?
我应该提到 jar 文件只包含 2 classes:MainClass.class & OtherClass.Class。两者都位于一个名为 TestPackage 的包中。该错误似乎与 MainClass class 在 javassist 加载它时无法找到 OtherClass class 有关。
问题是,当我调用 ct.toClass()
时,它只将 class 本身暴露给我的运行时 classloader(而不是整个 classpool 的 class小路)。当我稍后尝试调用此 class 的主要方法时,我的运行时 classloader 尝试执行加载它显然不知道的另一个 class 的部分,所以抛出 ClassNotFoundException.
解决方案是使用 javassist 提供的 classloader (javassist.Loader),它将 classpool 作为构造函数中的参数,然后能够加载和解析 classes 来自 class 池 class 路径正确。
这是我试图实现的工作代码示例:
File file = new File("C:\Users\MainPC\Desktop\test.jar");
ClassPool cp = ClassPool.getDefault();
cp.insertClassPath(file.getAbsolutePath());
Loader loader = new Loader(cp);
Class<?> MainClass = loader.loadClass("TestPackage.MainClass");
MainClass.getMethod("main", String[].class).invoke(null, new Object[] {args});
我正在尝试使用 javassist 加载外部 jar 文件并在运行时调用其主要方法,但是当我尝试使用以下代码执行此操作时:
File file = new File("C:\Users\MainPC\Desktop\test.jar");
ClassPool cp = ClassPool.getDefault();
cp.insertClassPath(file.getAbsolutePath());
Class<?> MainClass = cp.get("TestPackage.MainClass").toClass();
MainClass.getMethod("main", String[].class).invoke(null, new Object[] {args});
它抛出以下异常:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at ReflectionTests.main(ReflectionTests.java:99)
Caused by: java.lang.NoClassDefFoundError: TestPackage/OtherClass
at TestPackage.MainClass.main(Unknown Source)
... 5 more
Caused by: java.lang.ClassNotFoundException: TestPackage.OtherClass
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 6 more
当我仅使用内置 java 反射 api 尝试同样的事情时,它没有问题:
File file = new File("C:\Users\MainPC\Desktop\test.jar");
URLClassLoader cl = new URLClassLoader(new URL[] {new URL("jar:file:"+file.getAbsoluteFile()+"!/")});
Class<?> clazz = cl.loadClass("TestPackage.MainClass");
clazz.getMethod("main", String[].class).invoke(null, new Object[] {args});
(上面没有抛出异常并按预期调用 jar 文件的主要方法)
这让我相信我在 javassist 中做错了什么(特别是在加载 jar 文件 classes 时)。有人可以向我解释它是什么吗? 我应该提到 jar 文件只包含 2 classes:MainClass.class & OtherClass.Class。两者都位于一个名为 TestPackage 的包中。该错误似乎与 MainClass class 在 javassist 加载它时无法找到 OtherClass class 有关。
问题是,当我调用 ct.toClass()
时,它只将 class 本身暴露给我的运行时 classloader(而不是整个 classpool 的 class小路)。当我稍后尝试调用此 class 的主要方法时,我的运行时 classloader 尝试执行加载它显然不知道的另一个 class 的部分,所以抛出 ClassNotFoundException.
解决方案是使用 javassist 提供的 classloader (javassist.Loader),它将 classpool 作为构造函数中的参数,然后能够加载和解析 classes 来自 class 池 class 路径正确。
这是我试图实现的工作代码示例:
File file = new File("C:\Users\MainPC\Desktop\test.jar");
ClassPool cp = ClassPool.getDefault();
cp.insertClassPath(file.getAbsolutePath());
Loader loader = new Loader(cp);
Class<?> MainClass = loader.loadClass("TestPackage.MainClass");
MainClass.getMethod("main", String[].class).invoke(null, new Object[] {args});