-10

我有以下迁移到 Java 16 的遗留代码,但是由于这个新版本引入的强封装,它不起作用:

try {
    Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    method.setAccessible(true);
    method.invoke(new URLClassLoader(
        new URL[] {}),
        new File("C:/external-folder/my.jar").toURI().toURL()
    );
} catch (Exception exc) {
    exc.printStackTrace();
}

有没有办法让它工作?

4

2 回答 2

19

问题不在于反射“不起作用”;正是反射最终强制执行了编译器和运行时一直强制执行的更多可访问性模型。 URLClassLoader::addUrl仅适用于子类;它不打算从实现外部访问,这就是您正在做的事情。随着时间的推移,从 Java 9 开始并在更高版本(包括 17)中继续,访问限制越来越多地被反射识别,并带有警告,使损坏的代码有机会迁移到可支持的东西。

有问题的代码真的只是偶然地工作过;它取决于能够闯入不受支持的界面。使用setAccessible应该是一个线索。当然,你可以通过打破窗户进入锁着的房子,但如果你不得不打破窗户(而且这不是你的房子),你应该知道问题出在哪里。

把它看成半满的;这个意外工作的代码工作了很长时间。但是账单已经到期了;是时候修复你的代码了。

于 2021-09-14T13:41:03.147 回答
8

代码非常奇怪。乍一看,我认为它使用反射来访问URLClassLoader内部以添加myJar现有的类加载器中,但它使用它来将其添加到新的类加载器中。没有理由这样做 - 您可以为此使用构造URLClassLoader函数

它应该看起来像这样(未经测试,因为我远离 IDE):

URL jar = new File("C:/external-folder/my.jar").toURI().toURL();
URL[] urls = { jar };
new URLClassLoader(urls);
于 2021-09-19T09:19:36.267 回答