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

Why is the Java 11 runtime ignoring my jar containing sun.misc classes?

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

如果我能控制代码,我会使用 java.util.BASE64 类,但正如我所说,这些是作为来自另一个库的传递依赖项出现的,我无法更改它。

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

<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]

在过去的版本中,Sun 竭尽全力确保没有办法像您现在尝试的那样篡改运行时(如果像这样简单,每个人都可以创建自己的私有变体运行时 - 你肯定会明白这不是一件好事)。我不知道细节,但它们可能归结为 "if package name is this or that or such or so, then loading will only happen from rt.jar" - 硬编码在类加载器的东西中。这些执法措施(或类似措施)似乎很可能仍然有效。

舍弃了我的其余回答,因为我认为您非常了解您的选择是什么,而这不是问题所在。

这个答案是用

写的
> 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 下使用 BASE64Encoder class 创建 sun.misc 包。

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. This is because classes from the original sun.misc package have been moved to the jdk.unsupported module when the module system was rolled out in Java 9 and then over time removed (see 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 放入您的 "main" 项目中 - 就像您所做的那样。在 lib 目录中。我还没有找到使它与常规 Maven 依赖项一起工作的方法。

现在,在您的 "main" 项目中配置编译器插件:

<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>

(可能是由于 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 中运行良好。)

现在我的 "main" 项目叫做 j11 并且有一个 class:

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!