首页 > 解决方案 > java9 '-release 8' 带有内部包(例如 sun.misc.Unsafe)

问题描述

我正在尝试使用 Maven (3.8.0)创建一个多版本 jar 。我们调用sun.misc.Unsafewhich 在 java8 和 java11 中编译得很好。但是,使用编译java11 --release 8会引发Compilation failure: package sun.misc does not exist.


以下是如何重现错误:

一个简单的类调用Unsafe

public class ChangeableObjects {
    sun.misc.Unsafe unsafe;
}

一个简单的pom:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
            <configuration>
                <release>8</release>
            </configuration>
        </plugin>
    </plugins>
</build>

如果我们注释该<release>8</release>行,它在 java8 和 java11 上运行良好。

如果我们按原样编译代码,java8 会失败;这是正常的,因为它是java9 功能。问题是java11也失败了。


我认为问题是sun.misc包已在 java8 和 java9 之间移动。但是,该release标志的目的仍然是使用 java8 编译良好的代码也应该使用 java11 编译良好。

我是否误解了如何使用release标志?我需要sun.misc手动链接包以使其工作吗?

标签: javamavenmulti-release-jar

解决方案


首先,如评论中所述,不推荐我构建多版本 jar 的方式(按照我提供的链接)。使用 nullpointer 给出的示例,

我更喜欢使用类似https://github.com/meterware/multirelease-parent/blob/master/pom.xml

我使用了Maven 工具链,它可以使用不同的 JDK 进行编译。这样,我的问题就消失了。

其次,为什么我在 jdk11 中编译时出现编译错误的答案--release 8实际上是由指向https://stackoverflow.com/a/43103038/296328的 khmarbaise 给出的:

javac 提供了两个命令行选项,-source 和 -target,可以分别用来选择编译器接受的 Java 语言版本和生成的类文件的版本。然而,默认情况下,javac 针对最新版本的平台 API 进行编译。因此,编译后的程序可能会意外使用仅在当前平台版本中可用的 API。无论传递给 -source 和 `-target 的值如何,此类程序都无法在旧版本的平台上运行。选项。这是一个长期的可用性痛点,因为用户希望通过使用这些选项,他们将获得可以在指定平台版本上运行的类文件。

Nevertheless, it seems there are workarounds: see Maven: javac: source release 1.6 requires target release 1.6 for example.


推荐阅读