最近我正在创建一些必须动态加载/卸载外部jar包的东西。我现在尝试使用 URLClassLoader
执行此操作,但在尝试创建新实例时不断收到 NoClassDefFoundError
。
从执行构造函数中的代码来看,外部类加载成功,但是仍然抛出ClassNotFoundException
和NoClassDefFoundError
。
我制作了一个小包来重现错误,代码如下:
下面的代码位于 ExternalObject.class
中,它被放在一个 .jar 文件中,我正在尝试动态加载:
package test.outside;
import test.inside.InternalObject;
public class ExternalObject
{
private final String str;
public ExternalObject()
{
this.str = "Creating an ExternalObject with nothing.";
this.print();
}
public ExternalObject(InternalObject inObj)
{
this.str = inObj.getString();
this.print();
}
public void print()
{
System.out.println(this.str);
}
}
下面的代码位于InternalObject.class
中:
package test.inside;
public class InternalObject
{
private final String str;
public InternalObject(String s)
{
this.str = s;
}
public String getString()
{
return this.str;
}
}
我使用下面的 Main.class
测试了该文件:
package test.inside;
import java.io.File;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
import test.outside.ExternalObject;
public class Main
{
public static void main(String[] args)
{
try
{
File externalJar = new File("F:\\Dev\\ext.jar");
URLClassLoader uclTest = new URLClassLoader(new URL[]{externalJar.toURI().toURL()});
Class<?> clazz = uclTest.loadClass("test.outside.ExternalObject");
InternalObject inObj = new InternalObject("Creating an ExternalObject with an InternalObject.");
try
{
System.out.println("Test 1: Attempt to create an instance of the ExternalObject.class with an InternalObject in the constructor.");
Constructor<?> conTest = clazz.getConstructor(InternalObject.class);
ExternalObject extObj = (ExternalObject)conTest.newInstance(inObj);
}
catch(Throwable t)
{
System.out.println("Test 1 has failed. :(");
t.printStackTrace();
}
System.out.println();
try
{
System.out.println("Test 2: Attempt to create an instance of the ExternalObject.class with a void constructor.");
Constructor<?> conTest = clazz.getConstructor();
ExternalObject extObj = (ExternalObject)conTest.newInstance();
}
catch(Throwable t)
{
System.out.println("Test 2 has failed. :(");
t.printStackTrace();
}
uclTest.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
InternalObject.class
和 Main.class
都位于 jar 包中,启动时包含在类路径中。
我在控制台中得到了这个:
Console output screenshot
当 ExternalObject.class
的两个构造函数中的代码 this.print()
被执行时,我真的不知道出了什么问题。帮助! :(
更新:谢谢你!!!但我实际上想创建一个 ExternalObject
实例以供进一步使用,例如从其他类访问其中的方法。有什么方法可以将创建的实例作为 ExternalObject
返回吗?或者我必须使用 getMethod()
和 invoke()
来访问方法?
真诚的, 泽文
最佳答案
您的 Main
类引用 ExternalObject
,因此编译后的 Main.class
依赖于 ExternalObject
。
现在,当您运行 Main
时,ExternalObject
仅在 ext.jar
中可用,但在用于运行 Main 的类路径中不可用
发生以下情况:
uclTest
类加载器成功从 ext.jar
加载 ExternalObject
。创建也成功(可以通过构造函数中的 print 语句看到)。
但是失败的是对局部变量ExternalObject extObj
的赋值。
Main
无法使用加载的类 ExternalObject
,因为它是由不同的类加载器加载的。 Main
的类路径中也没有 ExternalObject
,并且您会收到 NoClassDefFoundError
。
当您删除两个赋值 ExternalObject extObj = (ExternalObject)
时,您的测试应该可以正常运行。
关于java - 使用 URLClassLoader 加载类时不断收到 NoClassDefFoundError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34493230/