java - 使用 URLClassLoader 加载类时不断收到 NoClassDefFoundError

标签 java classnotfoundexception urlclassloader

最近我正在创建一些必须动态加载/卸载外部jar包的东西。我现在尝试使用 URLClassLoader 执行此操作,但在尝试创建新实例时不断收到 NoClassDefFoundError

从执行构造函数中的代码来看,外部类加载成功,但是仍然抛出ClassNotFoundExceptionNoClassDefFoundError

我制作了一个小包来重现错误,代码如下:

下面的代码位于 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.classMain.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/

相关文章:

java - Log4j 为每个附加程序设置不同的日志记录级别

java - Web 应用程序在集群环境中工作的要求是什么

java - ELKI:如何从java中的多个文件创建数据库

android - 自 sdk 更新以来 Google Play 控制台中的 NoClassDefFoundError ClassNotFoundException 错误

java - Netbeans调试报错java.lang.ClassNotFoundException : org. apache.xerces.xni.XNIException

java - 自定义 URLClassLoader,运行时出现 NoClassDefFoundError

java - 如何在 onDestroy 函数中取消通知

java - IntelliJ IDEA : ClassNotFoundException if run Debug, 执行/运行确实有效

Java ClassLoader - 强制重新加载已经加载的类