I am new to Java and am a bit confused about how this is working/how I should be working. I am using intellij and a project that I am working on its pom.xml has:
<java.version>11</java.version>
<maven.compiler.source>$(java.version)</maven.compiler.source>
<maven.compiler.target>$(java.version)</maven.compiler.target>
When I go into the project structure on intellij the module is using language level 11.
on my computer I just downloaded the newest JDK (17)?
Does this cause issues working like this? Should I only be using a JDK that is associated with the version I am working?
I have not had any issues... but I am afraid my dependencies might be different than the ones I should be using...or the the build will be different if someone else is using another jdk.
The JDK version specified in the pom.xml specifies what source and target version is passed to javac. This specifies what system libraries and language features can be used.
The language level from IntelliJ matches this.
The installed JDK is the program (or set of programs) used for compiling and running the application.
Java allows to use a newer JDK to compile programs for older (source/target/release) versions.
The produced class files (bytecode) should be the same no matter what JDK version you use as long as the target/release version (specified in the pom.xml/language level in IntelliJ) is the same.
Furthermore, Java is (almost completely) backwards compatible. When writing code for an old Java version, it will likely also work in newer Java versions.
Related
I regularly use MALLET for topic modeling in the classes that I teach. Running MALLET requires users to have the Java Development Kit installed. I currently have JDK 8 update 241 installed on my main computer, and I know that MALLET works properly in this environment. That said, JDK is now up to v14.
Which version(s) of JDK does MALLET support?
I'm not altogether sure that you do need the JDK. They never say that on the website. The tarfile that I downloaded already includes compiled classes - you aren't expected to build it from source - so the JRE should be enough.
Strangely enough, the compiled classes in the class directory are targeted at 1.7 (bytecode version 51) whereas the pom indicates that it's supposed to target Java 1.6. So it's quite probable that by rebuilding it you could support an older version of Java.
In any case, the JDK is backwards compatible by design. Any version from 7 onwards will be able to run it (6+ if you were to rebuild it).
Running it on a newer version will benefit from the new features of the JDK, such as improvements to the garbage collector, so you may see some performance improvement there. If you are not concerned about that then it doesn't matter.
Recently, a teammate used the following function in our Java 8 code: Matcher.replaceAll​(Function replacer).
The function was introduced in Java 9, but because he is using a newer compiler, the API function was simply found in the JDK's rt.jar and nobody noticed this won't work under real Java 8 environments.
The compatibility settings are correctly set, and the gradle subproject has the following settings:
sourceCompatibility = 1.8
targetCompatibility = 1.8
I had very similar issues at the time when I first used the Java 6 function String.isEmpty in Java 5 code - the code made it into the release and crashed there.
What can I do to enforce the usage of the correct API. As it is a shared library, do I have to use (and install, maintain..) a different JDK for this gradle subproject, or is there some kind of compatibility scanner which runs through a built jar and checks all rt references?
As you've noticed, the two compatibility configurations does not consider the APIs of older versions - only the syntax, semantics and the resulting byte code.
There are two options you can take. One is to have JDK 8 installed on your computer, and the configure Gradle to use it when compiling your project. It looks like this:
tasks.withType(JavaCompile) {
options.fork = true
options.forkOptions.executable = "$java8Home/bin/javac"
options.bootstrapClasspath = files("$java8Home/jre/lib/rt.jar")
}
The disadvantage here is that you will need to have JDK 8 installed in the first place, and as it will probably be installed in different locations, you will need probably want to configure it with an environment variable or property (I've called it java8Home here).
However, since Java 9, the JDK now knows about the documented APIs of previous versions, and you can select which one to use with a new --release flag. This is not going to work if you use undocumented APIs, but it means you can compile your project with any versions of Java and still make the resulting classes compatible with Java 8. You can do it like this:
tasks.withType(JavaCompile) {
if (JavaVersion.current() > JavaVersion.VERSION_1_8) {
options.compilerArgs.addAll(['--release', '8'])
}
}
Note that the 'if' statement is only there in case you still need to support running Gradle with Java 8 (through your JAVA_HOME variable). If you are only using later versions, it can be removed so you always set the 'compilerArgs'.
For some versions of Java, it is possible build Java code on a newer JDK to run on an older JDK / JRE. You have already discovered the --source and --target options for javac and the corresponding Gradle settings. The other thing you can do is to use --bootclasspath to tell javac to compile against the runtime libraries for an older version of Java.
Since you are using Gradle, check out "gradle-java-cross-compile-plugin" (https://github.com/nebula-plugins/gradle-java-cross-compile-plugin). I can't find any documentation for it, but it apparently deals with --target and --bootclasspath.
Having said that, I don't think cross-compiling Java is a good solution.
I would actually recommend that you set up a Continuous Integration (CI) server (e.g. Jenkins) with JDK installations for all of the Java versions you are interested in supporting. Then set up jobs to build your code and run your unit tests for each Java versions.
Note that simply compiling your code against the older Java libraries is not sufficient to verify backwards compatibility. Sometimes the behavior of libraries changes. You need to run your tests, and your tests need to cover the cases where compatibility issues may exist.
I'm new to java programming and I haven't used any java IDE,
I intalled Java JDK 8 on my computer and been doing some coding through Notepad++ and compiling it via cmd commands.
Since now that i'm comfortable coding manually, I wanna try to use IDE and decided to get the latest "Eclipse IDE for Java Developers". what I got is actually a .zip file no installation or something which is odd.
My question is does the eclipse uses the JDK I installed on my computer or it has it's own? if so how would I know which version of java does my eclipse run?
and if does use the JDK on my computer, if I want to update the JDK intalled on my computer do I have to uninstall the old one or I can just overwrite it with the new JDK build??
Thanks,
CC
Eclipse uses externally installed JDKs to run itself (it's written in Java, after all) and to provide the core libraries for the code you write (such as the java.* packages). By default, Eclipse will use its own compiler, ECJ, that has deep integrations with the IDE to provide features such as detailed error reporting and sometimes even partial compilation of invalid classes.
It's possible to override the compiler via some plugin (for example, you can explicitly specify a compiler in a POM via m2eclipse, though the default there still uses ECJ), but that's uncommon if you're still compiling Java code.
Eclipse has support for using multiple JDKs, for example for different versions (maybe you have backwards compatibility with 1.6) or different vendors. Depending on how your OS is set up, if your main JAVA_HOME is set through a symlink, you may not need to update Eclipse at all if you perform a minor upgrade. In the case of a major upgrade, though, you will probably need to go to "Installed JREs" and add or modify an entry.
1.the jdk you installed in your computor is global situation. it can effect anywhere if you have configured the environment variables.
2.configured the environment variables,run cmd like this,the java version will be show,enter image description here
3.generally, one JDK , one computor is enough.if you want to update jdk, just download new jdk and override the old jdk .
I started a new project that is just a hello world that has the Commons IO v2.4 Apache Library that uses JDK 1.6 but is unable to run after I build the jar. I added it to the Libraries and Modules just fine, and it executes the methods that I took from the libraries fine on Compile time, but I am using JRE 1.7. I took of the methods to prove that it is just the fact that it is interacting with this library. I did nothing else to this new project.
The JDK for the library is 1.6 but is demanding 1.8 JRE. Is there somethign that I'm missing here? I want to let users run my jar with their minimum JRE being 1.6 so I can target more users, but this is throwign an error.
The actual Error that is being thrown is the major.min error of 52.0, which means that it needs to run it at 1.8 JRE to run a simple hello world.
Try manually selecting language level for your project.
Right click project > Open Module Settings:
On right side under sources tab, change language level to required JDK.
Then click on Project tab on left and make sure both JDK version and language version are at correct version.
I need to ensure one thing before doing it, so I have not yet tested the solution I'll propose.
I have a Jenkins on which one project compiles with a JDK 7 with target Java 7. I have a new project written in Java 8, and I'd like to add it to my Jenkinsfor it to build it too.
As a consequence, I need to install a JDK 8 on the machine. I know we can specify the java compiler version in the pom of each project, but I'm fearing this: once I have installed JDK 8, will my Java 7 project still be able to compile with that JDK 8? Should I have the two JDK installed on the machine, and have a configuration for each project to be able to locate its own JDK? Or will my Java 7 project be able to compile in Java 7 using the JDK 8 ?
Thanks for any help.
As stated in comments, it is possible to install multiple JDKs on Jenkins machine (see this answer as an example) and to configure each job to use a specific one.
Besides, you could perfectly compile your Java7 project using Java8 JDK. However, I advise you not to do that. indeed, if backwards compatibility is enforced at language level, you may find some APIs in which bugs you were unaware of, but the libs you use already knew, have been fixed, creating some weird behaviours. As a consequence, your Java7 application would compile using Java8 JDK, but expose bugs at runtime. And it would be the hell of a nightmare to solve those bugs (believe me, my friend, I've met that kind of horrors in a previous common company).
You can use multiple jdk on your machine, but remember to use specific jdk for specific project. Configure POM file of your project carefully if you have installed multiple jdk. Compiling Source Using Maven
Or you can change JAVA_HOME in the Build Environment section of the job configuration you can set environment variables for the job. Although, you can use multiple JDKs but its not a good practice to in CI/CD. Use specific machines with specific configurations.