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.
Related
I'm learning how to use Gradle to build projects in IntelliJ. I want to build a project involving OpenJFX. However, I encounter this error.
java.lang.UnsupportedClassVersionError: org/openjfx/gradle/JavaFXPlugin has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
> org/openjfx/gradle/JavaFXPlugin has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
From what I can figure out, Gradle is using Java 8 to run a Java 11 plugin. However, I put this in gradle.properties:
org.gradle.java.home=/C:/Users/<my user>/.jdks/openjdk-14.0.1
The reason it's in .jdks is because IntelliJ downloaded it earlier. The thing is, I told Gradle to use Java 14, yet it gives me an error as if it's being run by Java 8. What's wrong here?
According to the docs org.gradle.java.home property…
…specifies the Java home for the Gradle build process. The value can be set to either a jdk or jre location, however, depending on what your build does, using a JDK is safer. A reasonable default is derived from your environment (JAVA_HOME or the path to java) if the setting is unspecified. This does not affect the version of Java used to launch the Gradle client VM
So, this value is only used for build process (like compiling or running app or tests). Gradle spins up a child process for that, so the VM that performs tasks and the VM that runs the build script may not be the same.
It looks like you're using a Gradle plugin compiled with Java 11 (55.0), but your Gradle VM is Java 8 (52.0), so it cannot load and use plugin's class. You must use Java 11+ for Gradle VM itself.
Try running you build like JAVA_HOME=C:/Users/<my user>/.jdks/openjdk-14.0.1 gradlew.bat clean run.
I found out how to change Gradle's JVM. In IntelliJ, go to Preferences (Ctrl-Alt-S); then Build, Execution, Deployment; then Build Tools > Gradle. There's a little menu that lets you choose between the JVMs it recognizes.
Can you define anywhere in your Java Project which JRE/JDK version should it pick up?
In eclipse when I choose the project >> right click >> Java Compiler and check the "Compiler compliance level" I see a certain version marked (1.7,1.6 etc). How is this chosen?
Or is this entirely just dependent on what JDK/JRE runtime version your server (tomcat) is using?
Thanks
Short answer:
No, you can not identify the version of java that will be "picked up" at runtime.
More of an Answer:
There are three Java versions that come into play when building and running something using Java.
The source version. This is the version of Java to which the source of the project complies. When compiling, you can pass a "source" (try google search for "set java source level") parameter to identify this version. In practice, I don't know the value of this.
The target version. This is the version of Java to which the compiled result will comply. As with "source version" you can pass this as a parameter to the compiler.
Runtime version. This is the version of java that is actually installed on the host that is running the compiled java (the byte codes). You can never configure this at compile time since this is the thing that is installed on the runtime host.
There are some caveats.
The source and target version numbers must be equal to or less than the version of the java compiler that is actually compiling the java source. For example, you can choose target version 1.7 if you are compiling using a version 1.8 java compiler. You may not choose target version 1.8 if you are compiling using version a 1.7 java compiler.
It is possible to install multiple versions of java on a host. It is not possible to choose which version of java tomcat will use to execute your application since the version of java that will be used by tomcat is the version of java that is running tomcat.
It is chosen in that drop down menu, you can set it to whatever you'd like. However, you must have that version installed on your system/server in order for the project to function correctly. If you go to Window->Preferences->Java->Installed JREs, you can see which JREs you have installed. When you create a new server element in eclipse, you can also set the JRE of the runtime, and just make sure it matches the version of your project.
I am running into an issue with my gradle build script, build.gradle, for my java project. In this script I need to compile the application with Java 6 in order to comply with the application specifications. However, I am also using a gradle plugin that performs code analysis that needs to be run under a Java 8 JVM. What do I need to do in build.gradle or other gradle settings in order to get this plugin to use a separate Java JVM?
I need to do something like this as gradle tasks fail because the plugin is reporting a Unsupported major.minor version 52.0 Error.
Research
I have done some invesitigation and I did see the following mentioned:
options.fork = true
options.forkOptions.executable = System.getenv('OTHER_JAVA')
Where OTHER_JAVA is an environment variable to the other version of Java. However, I have not been able to get this to work for the plug-in and after some more research, it looks like this may be more limited to compiling with a separate version of java, not executing.
See: How do I tell Gradle to use specific JDK version?
You've pretty much answered your question yourself:
it looks like this may be more limited to compiling with a separate version of java, not executing
Run Gradle under the Java 8 (that would mean specifying your JAVA_HOME as JDK 8), and fork the compiler for your app with Java 6 (as per your research).
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.
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?