问题
NOTE: This appears to be a limit in the "javac" program.
I have Java 6 code that needs to be built for a Java 5 JVM. My previous work with the javac ant target (both with the JDK compiler and with ecj) led me to believe that it would simply be a matter of setting source and target for javac. Hence this pom.xml fragment:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.5</target>
</configuration>
</plugin>
which works as expected from within Eclipse 3.7 with Maven support. Unfortunately, running Maven directly from the command line give me
javac: source release 1.6 requires target release 1.6
which is the same as generated by javac -source 1.6 -target 1.5
. To clarify, this is the official OpenJDK 6 for Ubuntu
x@JENKINS:~$ javac -version
javac 1.6.0_20
x@JENKINS:~$ javac -source 1.6 -target 1.5
javac: source release 1.6 requires target release 1.6
x@JENKINS:~$
The official Oracle Java 7 JDK for Windows show the same behavior.
Note: I do not want to build against Java 5 libraries or anything. Just that the active javac generates Java 5 compatible bytecode.
How do I get what I want while still being compatible with the Eclipse Maven plugin?
(EDIT: In addition to the @Override I also want to compile against the JAX-WS libraries in Java 6 when used, but still generated Java 5 byte code - I can then add the JAX-WS libraries deliberately in the web container when deploying to a Java 5 installation)
EDIT: It turns out that maven-compiler-plugin can be told to use another compiler, and the Eclipse compiler can do this:
<plugin>
<!-- Using the eclipse compiler allows for different source and target,
which is a good thing (outweighing that this is a rarely used combination,
and most people use javac) This should also allow us to run maven builds
on a JRE and not a JDK. -->
<!-- Note that initial experiments with an earlier version of maven-compiler-plugin
showed that the eclipse compiler bundled with that gave incorrect lines in
the debug information. By using a newer version of the plexus-compiler-eclipse
plugin this is hopefully less of an issue. If not we must also bundle a newer
version of the eclipse compiler itself. -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.6</source>
<target>1.5</target>
<debug>true</debug>
<optimize>false</optimize>
<fork>true</fork>
<compilerId>eclipse</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.1</version>
</dependency>
</dependencies>
</plugin>
which compiles the class to Java 1.5 bytecode without complaints. This is also supported "out of the box" for m2e for Eclipse Java EE 4.2.2.
EDIT: I found that of all things the javadoc tool dislikes the output from the Eclipse compiler.
EDIT 2015-06-28: I did a quick test recently and the latest ecj (corresponding to Eclipse 4.4) worked fine with javadoc.
回答1:
The limitation is in javac. The solution is to tell maven to use another compiler. See question for details.
回答2:
It seems if you want to do cross compilation you need to supply a couple of extra arguments -bootclasspath and -extdirs, although I believe you only need the first. For using Javac and example can be found here with an explanation of the additional options here (Cross-Compilation Options section).
You would then need to configure these options for your maven-compiler-plugin. From what I understand you need to set to plugin to fork so that it will use the compiler arguments rather than the built in compiler. You can find a listing of all the options here
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.5</target>
<fork>true</fork>
<compilerArguments>
<bootclasspath>${1.5.0jdk}\lib\rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
....
</plugins>
</build>
回答3:
I believe you need to set -bootclasspath
as well so that javac
compiles against JDK 1.5 bootstrap classes.
Try:
javac -source 1.6 -target 1.5 -bootclasspath /path/to/jdk1.5/lib/rt.jar -extdirs "" Foo.java
UPDATE:
Try removing the -source
option, but keep the -target
option.
I just tested it out:
# no source, only target => COMPILES to 1.5
$ javac -target 1.5 Foo.java
$ javap -v Foo | grep version
minor version: 0
major version: 49
# no source, no target => COMPILES to 1.6
$ javac Foo.java
$ javap -v Foo | grep version
minor version: 0
major version: 50
# both source and target => ERROR
$ javac -source 1.6 -target 1.5 Foo.java
javac: source release 1.6 requires target release 1.6
$ javac -version
javac 1.6.0_21
回答4:
What Java 6 language features are you using that are not present in Java 5? As far as I can tell, the only "feature" that's been added to the language is the use of the @Override
annotation in interface
s. Otherwise, Java 6 and Java 5 are source-compatible. What happens when you use:
<source>1.5</source>
<target>1.5</target>
in your Maven build file?
回答5:
I had the same error when I upgraded my IntelliJ IDE, it was fixed with the replacement of 1.5 with 1.6 as below.
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
回答6:
The real question is thus to use @Override
in source files that need to be compiled in Java 1.5 class files.
javac -source 1.5 -target 1.5 aFileWithOverride.java
will do just that. In jdk 7, this will lead to a warning
[options] bootstrap class path not set in conjunction with -source 1.5
which is absent in jdk 6.
To get rid of this warning a special boot class jar can be created by adding the java 6 (or higher) java.lang.annotation
package to a java 5 rt.jar
.
来源:https://stackoverflow.com/questions/8970920/maven-javac-source-release-1-6-requires-target-release-1-6