为什么Java 11运行时会忽略我的包含sun.misc类的jar?

时间:2019-05-30 20:58:05

标签: java java-11

我正在尝试将代码库升级到Java11。不幸的是,我的代码依赖于内部使用sun.misc.BASE64EncoderDecoder的第三方库。由于sun.misc软件包已从Java 11 JRE中删除,因此它失败了。该库的所有者尚未替换该依赖项,因此我坚持了一段时间。

如果我可以控制代码,则可以使用java.util.BASE64类,但是正如我所说的那样,这些类是作为另一个库的可传递依赖项而来的,因此我无法更改。

我想我会很聪明,只用这些类创建一个新的jar,但是由于某种原因,该jar被忽略了。

enter image description here

<dependency>
    <groupId>sun.misc</groupId>
    <artifactId>BASE64</artifactId>
    <version>1.8</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/sun.jar</systemPath>
</dependency>

我也尝试将其显式添加到类路径中,但还是没有运气

这是JRE阻止您使用的那些软件包之一,还是我错过了某些模块规范,或者这是一个演出塞子吗?

这是输出

java.lang.NoClassDefFoundError: sun/misc/BASE64Encoder
at com.propsco.util.support.PropsLoader.save(PropsLoader.java:478) ~[props-client-2.2.1.jar:na]

2 个答案:

答案 0 :(得分:2)

在过去的版本中,Sun竭尽全力以确保没有办法像现在尝试的那样篡改运行时(如果这样简单,每个人都可以创建自己的运行时私有变体-当然,您会明白这不是一件好事)。我不知道细节,但它们可能归结为“如果软件包名称是this,that,so这样的东西,那么加载只会从rt.jar中进行”-硬编码在类加载器中。这些强制措施(或类似措施)似乎仍然有效。

取消了我的其余回答,因为我认为您非常了解您的选择,那不是问题。

答案 1 :(得分:2)

此答案是使用

编写的
> java --version
openjdk 11.0.3 2019-04-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.3+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.3+7, mixed mode)

首先,您将创建将具有覆盖的BASE64Encoder的项目。我们称之为sun-misc-override。在src\main\java下,使用sun.misc类创建BASE64Encoder包。

package sun.misc;

public class BASE64Encoder {
    public String encode(byte[] aBuffer) {
        return "Fake it until you make it!";
    }
}

如果尝试对其进行编译,则会出现sun\misc\BASE64Encoder.java:1: error: package exists in another module: jdk.unsupported错误。

这给了我们提示,我们需要patch module jdk.unsupported。这是因为在Java 9中推出模块系统后,随着时间的推移,原始sun.misc包中的类已移至jdk.unsupported模块中(请参见JEP-260)。

使用Maven,您可以按以下方式配置编译器插件:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <release>11</release>
        <compilerArgs>
            <arg>--patch-module</arg>
            <arg>jdk.unsupported=${project.basedir}/src/main/java</arg>
        </compilerArgs>
    </configuration>
</plugin>

构建com.example:sun-misc-override:1.0.0-SNAPSHOT之后,将生成的JAR放入“主”项目中-就像您所做的一样。在lib目录中。我还没有找到一种使它与常规Maven依赖项一起工作的方法。

现在,在“主”项目中配置编译器插件:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <release>11</release>
        <compilerArgs>
            <arg>--patch-module=jdk.unsupported=${project.basedir}/lib/sun-misc-override-1.0.0-SNAPSHOT.jar</arg>
        </compilerArgs>
    </configuration>
</plugin>

(可能是由于https://issues.apache.org/jira/browse/MCOMPILER-311,当我尝试使用

时得到了NPE
<compilerArgs>
    <arg>--patch-module</arg>
    <arg>jdk.unsupported=${project.basedir}/lib/sun-misc-override-1.0.0-SNAPSHOT.jar</arg>
</compilerArgs>

即使该错误应该通过maven-compiler-plugin 3.8.0修复,并且在sun-misc-override的POM中也可以正常工作。)

现在,我的“主要”项目名为j11,并且具有一个类:

package com.example;

import sun.misc.BASE64Encoder;

public class BASE64EncoderTest {
    public static void main(String[] args) {
        System.out.println("Testing - " + new BASE64Encoder().encode(new byte[0]));
    }
}

要运行它,您需要再次指定--patch-module

> java --patch-module=jdk.unsupported=lib\sun-misc-override-1.0.0-SNAPSHOT.jar -cp target\j11-1.0.0-SNAPSHOT.jar com.example.BASE64EncoderTest
Testing - Fake it until you make it!