繁体   English   中英

javassist 从 jar 加载外部类时抛出 ClassNotFoundException

[英]javassist throws ClassNotFoundException when loading external classes from jar

我正在尝试使用 javassist 加载外部 jar 文件并在运行时调用其 main 方法,但是当我尝试使用以下代码执行此操作时:

    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文件的main方法)

这让我相信我在 javassist 中做错了什么(特别是 jar 文件类的加载)。 有人可以向我解释它是什么吗? 我应该提到 jar 文件只包含 2 个类:MainClass.class 和 OtherClass.Class。 两者都驻留在名为 TestPackage 的包中。 似乎该错误与 MainClass 类在 javassist 加载时无法找到 OtherClass 类有关。

问题是,当我调用ct.toClass() ,它只将类本身暴露给我的运行时类加载器(而不是整个类池的类路径)。 当我稍后尝试调用这个类的 main 方法时,我的运行时类加载器尝试执行加载另一个类的部分,它显然不知道,因此抛出ClassNotFoundException

解决方案是使用 javassist 提供的类加载器 (javassist.Loader),它将类池作为构造函数中的参数,然后能够正确加载和解析类池类路径中的类。

这是我试图实现的工作代码示例:

    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}); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM