There are difference between `maven.compiler.release` and `maven.compiler.target` during compiling projects which use ```sun.misc.Unsafe``` with JDK17+
Affected version
3.14.0, 3.14.1
Bug description
There are import sun.misc.Unsafe; in our codes, we want the target class bytecode version is java 8 for the sake of compatibility.
During runing mvn compile with jdk17+,
- we will encounter
Cannot compile: java: package sun.misc does not existERROR and the compilation process will be terminated with failure if we setmaven.compiler.releaseto 8
<properties>
<maven.compiler.release>8</maven.compiler.release>
</properties>
or configure release of maven-compiler-plugin to 8 at the pom.xml like this,
<profile>
<id>jdk9-compile</id>
<activation>
<jdk>[1.9,)</jdk>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>8</release>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Unsafe is internal proprietary API and may be removed in a future releaseWarning will appear and the compilation process will continue if we setmaven.compiler.targetto 1.8 at the pom.xml (deletejdk9-compileprofile configuration) like this,
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
Hi @zrlw - could you confirm you understand there are two options --target and --release for javac that serve different purpose and act differently?
Hi @zrlw - could you confirm you understand there are two options
--targetand--releaseforjavacthat serve different purpose and act differently?
- https://github.com/apache/maven-compiler-plugin/blob/master/src/site/markdown/examples/set-compiler-release.md?plain=1#L20
Starting with JDK 9, the javac executable can accept the --release option
to specify against which Java SE release you want to build the project.
For example, you have JDK 17 installed and used by Maven,
but you want to build the project against Java 11.
The --release option ensures that the code is compiled following
the rules of the programming language of the specified release,
and that generated classes target the release as well as the public API of that release.
This means that, unlike the old --source and --target options,
the compiler will detect and generate an error when using APIs that don't exist in previous releases of Java SE.
- https://docs.oracle.com/en/java/javase/25/docs/specs/man/javac.html#option-target
--target release or -target release Generates class files suitable for the specified Java SE release. The supported values of release are the current Java SE release and a limited number of previous releases, detailed in the command-line help. Note: The target release must be equal to or higher than the source release. (See [--source
- https://docs.oracle.com/en/java/javase/25/docs/specs/man/javac.html#option-release
--release release Compiles source code according to the rules of the Java programming language for the specified Java SE release, generating class files which target that release. Source code is compiled against the combined Java SE and JDK API for the specified release.
The supported values of release are the current Java SE release and a limited number of previous releases, detailed in the command-line help.
For the current release, the Java SE API consists of the java., javax., and org.* packages that are exported by the Java SE modules in the release; the JDK API consists of the com.* and jdk.* packages that are exported by the JDK modules in the release, plus the javax.* packages that are exported by standard, but non-Java SE, modules in the release.
For previous releases, the Java SE API and the JDK API are as defined in that release.
Note: When using --release, you cannot also use the --source/-source or --target/-target options.
Note: When using --release to specify a release that supports the Java Platform Module System, the --add-exports option cannot be used to enlarge the set of packages exported by the Java SE, JDK, and standard modules in the specified release.
https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html
Merely setting the target option does not guarantee that your code actually runs on a JRE with the specified version. The pitfall is unintended usage of APIs that only exist in later JREs which would make your code fail at runtime with a linkage error. To avoid this issue, you can either configure the compiler's boot classpath to match the target JRE, or use the Animal Sniffer Maven Plugin to verify your code doesn't use unintended APIs, or better yet use the release option supported since JDK 9. Since plugin version 3.13.0 you can use the release property also on JDK 8. The compiler plugin will convert it to source and target automatically.
unlike the old --source and --target options,
the compiler will detect and generate an error when using APIs that don't exist in previous releases of Java SE.
it seemed that sun.misc.Unsafe will be considered as not-existed API if set maven.compiler.release instead of maven.compiler.target no matter the release version is 8 or not.