For some time I tried to understand, but I still don't get exactly what "compiler compliance level" for a project in Eclipse means. I looked all over this site and Google and couldn't find an answer I could understand.
Let's say I want my program to be able to run on JRE 6.
I can do: Project > Preferences > Java Build Path > Libraries, and set the JRE library I use to JRE 6.
Why isn't this enough?
I never understood why I also need to set the compiler compliance setting to JRE 6.
I'd like to understand the difference between using JRE 6 in a project, and setting the project's compiler compliance setting to JRE 6.
What exactly does compiler compliance level mean?
The compiler compliance setting tells the compiler to pretend it's a different version of Java.
The Java 8 compiler will produce class files in the Java 8 version of the class file format, and accept Java 8 source files. JRE 6 can't load this version, because it was created after JRE 6 was.
If you set the compliance level to "JRE 6", it will instead compile Java 6 source files into Java 6 class files.
It's like saving a Word document as "Word 97-2003 format" - so that Word 97-2003 can read your document. You're saving the class files in Java 6 format so that Java 6 can read them.
It tells you what version of the JDK you are adhering to; specifically, which JRE are you targeting with your build.
It is the MINIMUM JRE needed to run your code
The Java compiler can compile code that will run on prior versions of the JVM. Even if you have JDK 6 installed, you could be writing code targeted for people that use JDK 5. The Compiler Compliance level tells Eclipse to use appropriate settings when compiling your project to ensure you code will work on the target JVM you specify. By default, if I recall, Eclipse picks Java 5 Compliance. If you want to use code features specific to Java 6 or Java 7, you will have to change the compliance level.
The simplest way to describe the "Java compiler compliance" setting is that it determines which Java Virtual Machine instructions may be used in the "compiled" Java code ... and which library class versions are to be used. Each release of the JVM (and its libraries) may introduce new instructions (the VM) or adjust the class libraries that are delivered along with the JVM.
You should set the setting to the lowest level of JVM that you expect your product to be run on.
Related
For some reason I cannot use the keyword var despite being on language level 13.
Settings -> Build, Execution, Deployment -> Compiler -> Java Compiler
Is set to 13.
I am using gradle with the JVM language targets set to 1.8
I checked and tried:
problem in compile time when using "var" in jdk 11
How to avoid IntelliJ to reset language level?
You didn't say what IDE you are using, but I am guessing IntelliJ. You also didn't show the Gradle configuration in IntelliJ, so I am assuming you are going by the default settings and that its a relatively new version.
You can chose between having IntelliJ compile your source code, or let Gradle do it. The default is Gradle, so it doesn't matter what how you configure the IntelliJ compiler as it isn't used.
If you don't fork the Gradle compilation, it will use the same JDK for compilation as for running Gradle. In IntelliJ, this is configured in the Gradle JVM setting under Build Tools -> Gradle (or JAVA_HOME if you are running it from the CLI).
Now back to your question. The reason you can't use the var keyword is exactly because you have configured it to target Java 8. That means the source also have to be compatible with Java 8. If you think about it, newer language features usually require newer versions of the byte code. So if you need your final binary to be compatible with Java 8, you need the source to be compatible with Java 8 as well.
You can still use Java 13 to compile to Java 8 byte code (as long as you program against a Java 8 API and syntax). But instead of just the "target" version, you should use the --release flag as this will also configure the bootclasspath correctly, which I am guessing you didn't do (this ensures that you use the correct API). For instance:
compileJava {
options.compilerArgs.addAll(['--release', '8'])
}
I have now a little experience in Java, so I wanted to take the next step to an IDE, so I installed the Eclipse IDE. (If it matters, I am using mac.)
But this does not seem to work right, as soon as I create a new class, the error occurs:
The project was not built due to "release 6 is not found in the
system". Fix the problem, then try refreshing this project and
building it since it may be inconsistent HelloWorld
I already tried to change some of the properties in the class or selecting different settings, right now I use the execution environment JRE: J2SE-1.5.
Thank you for taking your time!
Well it is basically telling you that you don't have the right version of Java JDK installed. THIS page seems to imply the current version of eclipse needs 1.8 - not the 1.6 you're talking about. I am unsure though how you could have specified one that isn't installed. Maybe you only have the JRE (java runtime environment). You will definitely need the JDK (java development kit) because that is what has the java compiler in it.
It's been a long time since I used eclipse but when you created the project you should have been prompted to specify the java version. Now try right clicking on the project and choose Build Path... Configure Build Path. On the Java Compiler tab (left side) you should be able to change the configured Java to whatever you have installed.
I got this error when the selected version under Preferences > Java > Compiler > Compiler compliance level was higher than the selected version under Preferences > Java > JREs > Installed JREs. There was a small (very small) warning at the top of the JREs page warning me that there was an incompatibility with the compiler compliance level.
The options for compiler compliance level includes all versions up to the version that Eclipse itself is using, even if you don't have a specific JDK with that version, so you can get warnings for JDK releases that you definitely don't have.
I updated the compiler compliance level to be the correct version for my project and that got rid of the problem.
The target system, on which my application is supposed to run, uses Java 6. On my development machine, I have Java 7. Can I do the development, without downloading Java 6?
I found on http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html one example for cross compilation:
javac -source 1.6 -target 1.6 -bootclasspath C:\jdk1.6.0\lib\rt.jar -extdirs "" OldCode.java
However, this too requires the existence of a rt.jar, which belongs to Java 6. Is there a simpler way?
New Java versions generally change both the Java Language (source and class file format) and the Java API.
The Java compiler can emit class files in the old format, even if the source is in a new format (these versions are specified by -target and -source, respectively). Therefore, you don't need the old compiler to target an old JVM.
However, the changes to the Java API are somewhat harder to account for. The easiest is to compile using the API of the Java version you target (-bootclasspath). Of course, you may feel confident that you are not using newer APIs, and skip this step, but the only way to make sure is actually compiling against, and testing on, the old runtime library.
In short, while cross compilation is helpful in that the same source can be used with different Java versions, you should compile and test against the actual Java version you intend to use, which does require the old JRE (or JDK).
BTW, all of these settings are also available in Java IDEs. For instance, in eclipse, one would set the compliance level in the project's compiler settings, and add the appropriate "JRE System Library" to the project's "Build Path":
The below command should suffice to meet your requirement.
'javac -source 1.6 -target 1.6 OldCode.java'
With this command you are telling that the compiler should generate class file that is compatible with java 6. Any java 7 specific will result in compilation error. Regarding rt.jar, you don't need to have java6 specific version. As mentioned the above command automatically ensures output is java6 compatible.
UPDATE/CORRECTION:
After going through the following link http://www.javaworld.com/article/2077388/core-java/what-version-is-your-java-code.html it is clear why it is recommended and is important to use -bootstrap flag along with -source and/or -target flags.
On our hadoop cluster my Pig UDF fails complaining
[main] ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1069: Problem resolving class version numbers for class <classname>
I read writing a udf in pig kind of like tutorial and the problem seams to be clear, but unfortunately I cant solve it. My manifest does not contain a version (is this necessary?) and javap reports major version 52, representing java 1.8, although I compiled it with 1.7. So how can I solve this?
My manifest does not contain a version (is this necessary?)
The version manifest entry is not relevant to this. The classloader pays no attention to the version manifest entry.
and javap reports major version 52, representing java 1.8,
That is the relevant fact.
although I compiled it with 1.7.
This all boils down to how you compiled your code, and I think you are incorrect when you say that you compiled with Java 1.7.
Why do I say that? Because the Java 1.7 java compiler is not capable of creating a ".class" file with the Java 1.8 version numbers. It simply doesn't understand the Java 8 syntax extensions, and the corresponding enhancements to the classfile format.
So how can I solve this?
The way to resolve this is to look carefully at your build process and figure out how and why the offending class got compiled using a Java 1.8 compiler. Because there can be no doubt that that is what has happened.
If you are building by hand (e.g. by running "javac" and "jar" from the command line, or by clicking buttons in your IDE) then now would be a good time to learn about build tools like Maven, Ant and Gradle.
FOLLOWUP
That not true. My setting proofs this, but I guess I found the issue: .settings/org.eclipse.jdt.core.prefs contain several 1.8. entries. This may be due to the fact that at the time of the project creation I had 1.8. installed.
Actually, it doesn't "prove" anything ...
What this is telling me is that you are probably compiling with the Eclipse Java compiler, not the Java compiler from your JDK.
In fact, your Eclipse compiler is (or was) compiling for a Java 1.8 target ... because that is what your Eclipse settings say that the Eclipse Java compiler should do. If you are using the Eclipse compiler to compile your code, the version of your JDK or JRE install doesn't determine the classfile version number.
Once again, I strongly recommend that you learn to use a Maven, Ant or Gradle so that you build process is more repeatable and less error prone.
I guess Stephen C's is the most general answer.
In my special case the problem was, that the project specific compiler compliance settings were wrong, because I used JDK 1.8 locally when I created the project and installed 1.7 later, when I got the error on the cluster.
The option is quite hidden and can be found here:
Window > Preferences > Java > Compiler > "Configure project specific settings" > [projectname] > "Compiler compliance level"
I have jre7 installed on my pc.
In Eclipse Kepler I created a project with compiler compliance level 1.5.
The source compatibility setting is 1.5 too. But this setting not works.
I can wirte code which using methods that were declared in 1.6 or later. For example:
String s = "aaa";
boolean b = s.isEmpty();
The method isEmpty() in java.lang.String is since 1.6.
Of course, when running the generated class file with a real jre 1.5 enviroment, i got a NoSuchMethodError exception.
Here is my source and settings:
How can I fix this? Or is it an Eclipse bug?
The settings are releated to the -source and -target flags for the javac compiler which enables backwards compatibility (for an explanation, see for example this SO question and answer).
This is mostly a technical option and not a feature, i.e. these settings in Eclipse were never intended to free you of the burden of knowing what is and is not available in an old JRE. But Eclipse does provide you the option to make it so and even shows you a warning message at the bottom of the Java Compiler options screen on how to make it so (and yes, that does involve downloading and installing the old (target) version of the JRE - there is no way around that).
Whether or not a method from Java 6 is available depends on the JRE library that you are using.
Go to "Java Build Path", into the "Libraries" tab, remove the "JRE System Library" of Java 7. Then, click "Add library..." and go though the dialogs for adding a Java 5 JRE Library. (Of course, a Java 5 JRE has to be installed for that...).
(Note: There is also a message about this in the right screenshot, at the bottom...)