Can we use a JDK 1.8 compiler to compile source code whose sourceCompatibility option is set to 1.7.
ModuleA has this set to 1.7 and ModuleB and ModuleC has this set to 1.8. What compiler should I use for compiling all the above modules. I am assuming it should be JDK 1.7.
You can run into problems when compiling 1.7 code with an 1.8 compiler.
Merely setting -source and target to 1.7 is not sufficient and you should get a warning during compilation that complains about the bootstrap class path.
If you accidentally use a class or method introduced with 1.8 - e.g. this one, the compiler won't catch it. Running your code on a 1.7 runtime will fail then with NoSuchMethodError.
So, if you intend to run on your code on a 1.7 runtime, you should either compile with an 1.7 compiler or set the bootclasspath.
I assume you have two questions:
Use jdk8 to compile a program written for java7: Yes, java is famous for its backward-compatibility.
Use what jdk to compile a project with modules written with different source compatability: Use the lastest version. In your case, jdk8. If something went wrong, install and use multiple jdks.
EDIT: It's true that problems may come if you compile a java 7 prog with jdk8, but in my 200+ local builds and 400+ CI builds, nothing went wrong. The problem rate is so low that I merely take it into account. If you consider it INSANELY important, ALWAYS install and use the matching jdks.
I agree with Frank, you may face runtime issues. An actual one we found by using newer JDK to compile code that should run on older JRE.
Related
Does Gradle requires JDK to compile Java source files?
or it is using its own internal compiler?
Thanks in advance
Short version: JRE for installing and running, Groovy build script compiled by Gradle own compiler, JDK for Java source code compilation.
Long version: There are multiple points of interest:
1) Installing & running
In order to install Gradle and run Gradle build you need a JDK or JRE which version is at least 7.
Gradle uses mainly Groovy as a language but it comes with its own library and ignores any other Groovy library that is installed. Therefore the compiler is the Groovy compiler of the Groovy library that Gradle comes with.
As a side note, you can also use Kotlin for scripting builds as described here. Which of course involves a Kotlin compiler.
You can check the JVM version by running gradle -v.
This means that during installation the runtime configured in JAVA_HOME will be used.
Also the same happens for running a build, unless you are explicitly overriding JAVA_HOME in gradle.properties using the following property org.gradle.java.home. This property and others are defined here.
JAVA_HOME can point to a JDK or JRE. In this case does suffice to have only a JRE installation.
2) Source Code Compilation
To remove any confusion, source code, means that you have your project sources, written in a language, which need to be compiled into bytecode. At previous point the code being written is the actual build script code which is a separate thing, compiled and handled by Gradle.
Source code is being compiled using Gradle plugins, being it java, groovy, kotlin, or anything else.
You can compile your JAVA source code by using the java plugin or the newer java-library plugin. The two are similar.
The JDK being used will be the one configured in JAVA_HOME or can be explicitly defined in gradle.properties using the following property org.gradle.java.home.
JAVA_HOME needs to point to the JDK not a JRE for this case.
As stated above, Gradle can only run on Java 7 or higher. But it can be configured to compile, run, test, javadoc for Java 6 by following these steps. Therefore this advanced customization can be used to handle some corner cases which may not have a resolution in simply changing gradle.properties.
The two plugins provide also two properties:
sourceCompatibility - Java version compatibility to use when compiling Java source
targetCompatibility - Java version to generate classes for.
These are related to the source language version used as input and the target bytecode version to be generated.
In a conversation with someone else, they claimed that the version of JDK being used to compile the code does not matter vs. the JVM version being used to run the compiled code.
That seems strange to me - are there never instances where the JDK version matters? Is functionality always only dependent on the JVM the code is running on, and not on how the code is being compiled?
https://stackoverflow.com/a/19554706/2687324 talks about backwards compatibility. Is Java code also forwards compatible?
No, you can't necessarily run code compiled with a new JDK on an old JRE. Compiled classes contain a version number for the class file format; if this is newer than the runtime expects, it will refuse to load the class.
Most Java compilers support an option to target an older JRE, generating an older class file format than the compiler was built for. However, you can still run into trouble if you don't also compile against an older version of the Java runtime library. Your code might use new API that isn't in the older version of Java. The compiler, with its current version of the API, won't catch this even when you specify an older target.
For the standard javac compiler in OpenJDK, these options are -target and -bootclasspath. You might also want to set the -source option to catch usage of newer language features that require support the older class files don't provide.
I have java program compiled with java 1.7 and I need use this compiled file in another machine which contains java 1.6.
When I am running 1.7 java compiled file with java 1.6 "unsupported class version exception" getting.
Is their any backward compatibility to execute java 7 compiled file in java 1.6.
Sorry, as far as I know, this is not possible. You can compile 1.6 compatible class files on JDK7, but you cannot run JDK7 class files on older virtual machines.
If it was compiled with -target >= 1.7 then you would have a problem.
That is because the compiler was instructed to generate bytecode to run
on a JVM with version >= 1.7. But then you ran it on JVM 1.6.
If it was compiled with -target <= 1.6 then you should have no problem.
It will always fail when trying to check version number. Check your requirements and talk to your operators. If your only option is to run in a box with 1.6, then you should recompile and make sure you have all the information on your execution environment before running into any more problems when going real (for example, make sure you know about JDK provider, production machine dependent paths...)
There are some reason for exception.If you use library and it is not in jdk 1.6 it's problem for compile code in 1.6 because 1.6 does not contain libraries which is in 1.7
I have an Eclipse workspace with several Java projects (in Maven); these have dependencies on each other. Recently I started changing just some of the projects to target Java 1.7, and other than resolving some new warnings, nothing is different when compiling.
However, it feels like something might go wrong when I try to run everything. How are class files loaded, and are there any issues, in the following situations?
Is there a problem when a Java 1.6 project depends on a Java 1.7 project? Will the 1.6 VM just refuse to run any 1.7-generated bytecode, or does something weird happen in order to get it to run?
Is there a problem when the reverse happens?
When you have java 1.6 project depends on a Java 1.7 project or java 1.7 project depends on a Java 1.6 project, you should always run your program on the higher version of JVM, which is java 1.7 in this case. In a nutshell, in most cases, class files built with the Java SE 6 compiler will run correctly in Java SE 7. But there are some exceptions. Please see Incompatibilities between Java SE 7 and Java SE 6 for a list of incompatibilities between Java 6 and Java 7.
You can build a project with JDK 1.6 that has some libraries that where generated with 1.7
HOWEVER if some of the code from the project 1.7 needs some JDK 1.7 feature (for example, it uses the new Swing combobox with generics) it won't run on a 1.6 JVM.
So this is something to be very careful about, as you can run into compile time trouble (which is at least not silent) but also runtime trouble. If you can avoid this, it might be better for you.
I have also faced a similar problem and as per my knowledge i don't think that 1.6 VM can run any 1.7-generated bytecode but i think the reverse is possible as 1.7 is a upgraded version of 1.6VM.
I created a Jar with Java 6. Now I'm creating a release document and recording the dependencies. How can I find the earliest version of Java that can successfully run the Jar, and the earliest version of Java that can successfully compile the source into a Jar?
I only know a manuel solution: try it out. There are, however, two things to consider.
For which version is the code language compatible?
For which JRE will it execute?
The first you can do with your current JDK, just iterate over the -source and -target arguments which you pass to your javac compiler. This will, however, not prevent you from using classes and methods from the JDK you are using. If you do, the code will not execute for a lower JRE, if you are using classes or methods that where not present back then.
The savest way would be to install all different JDKs along and try to compile the code with each of their compilers.
If you created the jar with java 6 and did not specify a different version of output bytecode, the generated class files will require Java 6 or greater. You can experiment to see what versions of bytecode you can generate with your source with the -target command line option if you're compiling manually, if you're using eclipse or some other IDE, most have settings that control the generated bytecode version in project options or somewhere similar.
A related post about determining the bytecode versions of class files: What version of javac built my jar?