The method java.lang.Long.compare(x, y) exists in Java 7 but not Java 6. So obviously this causes a NoSuchMethodException if code using this method is deployed to a server running Java 6.
However, either Maven nor Eclipse were picking up the error despite having set the source-compliance level to 1.6 in eclipse and the maven compiler source & target to 1.6.
Is there a way to enforce full Java 6 compliance in Eclipse, apart from downgrading my JRE to 6?
This is exactly why the animalsniffer-maven-plugin was introduced:
Animal Sniffer provides tools to assist verifying that classes compiled with a newer JDK/API are compatible with an older JDK/API.
This is what I put in my POM.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
...
<properties>
<java-version>1.6</java-version>
</properties>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
</project>
Once I have that defined in my POM I right click the project and go to Maven > Update project. This will apply any settings in the pom to the eclipse project which ensures the two are in sync.
In terms of JDK I use the latest JDK but compiled to the lower release. We're currently using JDK 7 but compile to 6. This gives you the best of both worlds in that the compiler will still make use of any optimizations that were introduced with 7 that are compatible with version 6.
There is a way to cross-compile Java source code, but the easiest way is to use the min. required JDK version when creating your artifacts (JARs etc.)/ during development.
-> use JDK 6 during development and releasing.
Note however that Oracle's JDK 6 reached End of Life and it is strongly recommended to upgrade to Java 7 if you don't have special support contracts with Oracle (or using a JDK from a different vendor).
Note: the source-level only makes sure you're using syntax constructs supported by that version and the target-level only makes sure the resulting class file is bytecode compliant to the specified version.
Related
I am using Java 14 as the default Java platform for Netbeans 11.3 (netbeans_jdkhome is set to my Java 14 JDK) and trying to use a preview feature in a simple Java application. I set the source level to 14 and set --enable-preview as a compiler argument. The code compiles without errors.
However, when I try to run it within Netbeans, it complains that the major version of the .class files is 57 while the runtime only plays well with 58 files and preview features. Here's the error:
java.lang.UnsupportedClassVersionError: javaapplicationtest14/JavaApplicationTest14 (class file version 57.65535) was compiled with preview features that are unsupported. This version of the Java Runtime only recognizes preview features for class file version 58.65535
I checked the major version of the .class files and they are indeed 57. Any ideas why my project won't compile into Java 14 level? I am using an Ant build.
As well as setting --enable-preview as a compiler option, it should also be set as a VM Option when running the code:
However, that doesn't fix the problem, and unfortunately this looks like a NetBeans 11.3 bug. I reproduced your problem with a Java with Ant project, and created Bug Report NETBEANS-4049 UnsupportedClassVersionError when running JDK14 code with --enable-preview.
There are a couple of workarounds if you need to use preview features with JDK 14 in NetBeans:
Run your application from the command line (with --enable-preview as an option) instead of within NetBeans. The same code which fails with the UnsupportedClassVersionError in NetBeans runs fine in that environment, which strongly suggests that NetBeans is ignoring the --enable-preview run time option.
Create a Java with Maven project instead of a Java with Ant project. You can then run your code which uses preview features within NetBeans.
Update your question with more details if you still have problems.
Netbeans Project Configuration (Java 14)
Java 14
Netbeans >= 11 (Current: 12.0 LTS)
Optional:
Can use sdkman or set default java path:
/opt/<jdk-install-dir>
C:\Program Files\<jdk-install-dir>
Project 'Run' Configuration
Java Platform
pom.xml
Notes
Check maven.compiler.source / maven.compiler.target
Check build->plugins->plugin->...-> compilerArgs -> arg
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>Demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<compilerArgs>
<arg>--enable-preview</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
nb-javac should not be installed (it appears in the plugins).
If it is installed in 11.3, it seems to create classfiles with version 57 not 58, which the runtime then objects to, as above.
I'm trying this with Netbeans 15. I want to use the foreign linker API, and code completion is saying:
MemoryAddress is a preview API and is disabled by default. (use
--enable-preview to enable preview APIs)
This is with both JDK 19 and JDK 20 preview. I put the --enable-preview option in the pom.xml and it doesn't change anything. If I go to project properties / Build / Compile, there are options to choose which JDK but no way to enter JDK options. It seems like --enable-preview is recommended by NetBeans hints but there's no way to actually do it. Is this a bug in NB or am I missing something? Very frustrating because I would like to use some of these features and I'm spending my time trying to get my code editor to work. I think this did work in previous versions of NB.
I have a requirement to compile an app for use under JRE 6.
Initially the app was compiled for use under JRE 8.
So I added:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
to pom.xml
After fixing all the errors caused by unavaiable diamond operator, string in switch statement etc. I ran the app under JRE 6 and got the error.
Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: java/nio/file/Paths
Ok. This class is available only since Java 7. But the question arises: what does the above maven setting exactly? Does it only check the syntax? If so, then it's not quite useful.
What needs to be done to configure maven so that it notifies me about missing classes in particular Java version too?
java.nio.file.Paths was introduced in Java 7. You will have to change the implementation of your code to only use classes available in Java 6.
And yes, the Maven property only tells javac to use Java 6 syntax. That's very useful. Maven will not magically change your code for you. javac started by mvn package will tell you about unresolveable imports.
The purpose is to instruct maven to pass the -source and -target to the javac compile executable. It makes sure you only use language features that are available in the given JRE (the diamond operator is a great example), but it does not prevent use of APIs that only came along later.
Have a read of this
In particular the part at the bottom of the page:
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...
I think it's unfair to say the parameters are not useful they certainly are. But they are not magical tools that know which libraries may be available at runtime.
The Animal Sniffer plugin for maven verifies that classes compiled with a newer JDK/API are compatible with an older JDK/API.
https://www.mojohaus.org/animal-sniffer/
Ok. I figured out how to do it.
You don't have to install the target JDK or JRE. All you need is rt.jar from that JRE.
Then you have to set the path to the jar file in bootclasspath in pom.xml.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<compilerArguments>
<verbose />
<bootclasspath>C:/data/tmp/rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
We have a Java 7 project which uses a plugin built with Java 8. Is it possible to use the Java 8 plugin in Java 7 pom by setting the compiler version to use only for the plugin?
I just found that on the internet :
http://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html
You should just add a configuration section specifying the jdk wanted as
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.4</source>
<target>1.4</target>
</configuration>
</plugin>
I hope it helps !
It is only possible, if the plugin forks into a new JVM process and allows you to configure the JVM which it uses to execute. Otherwise it will use the JVM, which the whole build uses. You would then have to run the build with a JRE/JDK 8 (which shouldn't be a problem when you set the source and target version appropriately, like in the answer from Juan Wolf (just set 1.7 instead of 1.4)
This question already has an answer here:
Maven - use -source 5 or higher to enable... while building the project
(1 answer)
Closed 8 years ago.
Whenever I deploy a Jenkins build with Maven, it says that I have the 1.3 JDK, even though I have 1.7 installed.
Here is a picture of the error log I get when using an enhanced for loop:
http://gyazo.com/d1c7e297199dbf8a8b6ba23efa5733ba.png
However, I clearly have 1.7 JDK installed.
http://gyazo.com/27b85ba9ea25579aa714b0e2586fd618.png
If anyone knows why this issue occurs and how to fix it, please post below.
Sorry I don't have a ton of formatted information, but I have no idea why this could possibly be happening as I do not have such an outdated JDK and have the most recent updates from Oracle. Maven and Jenkins are also updated completely.
Thanks.
The complaint of maven is not about your jdk version, but about the -source parameter of the compiler. Older Maven versions use a version of the maven-compiler-plugin, which uses -source and -target 1.3 by default.
So, what you need to do is configure you project to use higher source and target levels in order to use your for each loop:
(taken from https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html)
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
Note that simply setting the version of the maven-compiler-plugin would actually be sufficient, since for version 3.1 the default is 1.5, however it is good style to explicitly include the source and target version in your master pom.
You have the project set to compile with the default jdk according to your stack trace. Your default is your %JAVA_HOME% environment variable on the server which is probably set to an older jdk. In order to compile with the 1.7 jdk you have to specify this in your project config. Change jdk : (Default) to your 1.7 name.. which is jdk.
Or you can just go to the maven jdk and change it from (inherit from project) to jdk.
There is already an issue ticket open with jenkins related to this: https://issues.jenkins-ci.org/browse/JENKINS-755
In one of the classes I have this code:
str.isEmpty()
which compiles fine until I add this element to the POM:
<parent>
<artifactId>teevra.platform.parent</artifactId>
<groupId>com.hs.fusion</groupId>
<version>2.0.0</version>
</parent>
And then immediately the eclipse starts giving an error saying "The method isEmpty() is undefined for the type String". I obviously need this parent to access classes/interfaces needed for this child project.
I wonder what is causing the shift from Java Version 1.6 to 1.4 and how can it be prevented? Even more baffling is the fact that from command prompt, the project builds fine but not in Eclipse Juno.
Any help would be greatly appreciated,
G.
You need to specify the specific version of java to use. your problem is probably that your eclipse default is different from the maven default, so as soon as you add the dependency, m2e regenerates the project settings using the maven default (1.5)
Just specify the required java version explicitly. Something like this in your plugins section
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
To ensure that no invalid JRE calls leak into your project, you should use http://mojo.codehaus.org/animal-sniffer/ It seems like your parent lowered the source/target of the maven-compiler-plugin