-
Notifications
You must be signed in to change notification settings - Fork 87
guide jdk
The Java Development Kit is an implementation of the Java platform. It provides the Java Virtual Machine (JVM) and the Java Runtime Environment (JRE).
The JDK exists in different editions:
-
OpenJDK is a free and open-source edition of the JDK.
-
OracleJDK is a commercial edition of the JDK.
-
Various alternative JDK editions either commercial (e.g. IBM’s JVM) or open-source.
As Java is evolving and also complex maintaining a JVM requires a lot of energy. Therefore many alternative JDK editions are unable to cope with this and support latest Java versions and according compatibility. Unfortunately OpenJDK only maintains a specific version of Java for a relative short period of time before moving to the next major version. In the end, this technically means that OpenJDK is continuous beta and can not be used in production for reasonable software projects. As OracleJDK changed its licensing model and can not be used for commercial usage even during development, things can get tricky. You may want to use OpenJDK for development and OracleJDK only in production. However, e.g. OpenJDK 11 never released a version that is stable enough for reasonable development (e.g. javadoc tool is broken and fixes are not available of OpenJDK 11 - fixed in 11.0.3 what is only available as OracleJDK 11 or you need to go to OpenJDK 12+, what has other bugs) so in the end there is no working release of OpenJDK 11. This more or less forces you to use OracleJDK what requires you to buy a subscription so you can use it for commercial development. However, there is Adoptium that provides forked releases of OpenJDK with bug-fixes what might be an option.
The easiest way to get all this setup for developers is using devonfw-ide.
A key feature of Java is automatic garbage collection (GC).
Over time different garbage collectors have been implemented within the JVM.
The good news is that usually you do not have to care about all this.
However, at some point you might get an OutOfMemoryError
or other effects related to GC and heap issues.
You should also be aware that when a lot of heap is consumed, a full GC may pause the JVM for some time causing other issues like performance problems or even connection timeouts.
Therefore, we strongly recommend you to do continous logging of your GC activity in your environments up to production.
These GC logging does not cause relevant overhead so it can be enabled 7x24.
Whenever you might have heap issues or a memory leak, you can simply analyze these GC logs.
Simply transfer the logs from the environment server to your local machine.
As the GC logs do not contain data that is sensitive to your app (regarding GPDR, customer data, etc.) this should be relatively easy to arrange.
To analyze these GC logs, we recommend GCViewer.
If you are already using devonfw-ide, that integrates all cool developer tools you may need, you can just call this command:
devon gcviewer
Sometimes you may face concurrency issues or even deadlocks where threads block each other. In such case you should create a thread-dump. We even recommend you to create a series of e.g. 3-5 thread-dumps with a short delay of e.g. a minute bettwen each of them. This will help you to trace down problems of waiting or blocked threads.
Until Java 8 compatibility was one of the key aspects for Java version updates (after the mess on the Swing updates with Java2 many years ago). However, Java 9 introduced a lot of breaking changes. This documentation wants to share the experience we collected in devonfw when upgrading from Java 8 to newer versions. First of all we separate runtime changes that you need if you want to build your software with JDK 8 but such that it can also run on newer versions (e.g. JRE 11) from changes required to also build your software with more recent JDKs (e.g. JDK 11 or 12).
This section describes required changes to your software in order to make it run also with versions newer than Java 8.
The first thing that most users hit when running their software with newer Java versions is a ClassNotFoundException
like this:
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
Class | GroupId | ArtifactId | Version |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Further, internal and inofficial APIs (e.g. sun.misc.Unsafe
) have been removed.
These are typically not used by your software directly but by low-level 3rd party libraries like asm
that need to be updated.
Also simple things like the Java version have changed (from 1.8.x
to 9.x
, 10.x
, 11.x
, 12.x
, etc.).
Some 3rd party libraries were parsing the Java version in a very naive way making them unable to be used with Java 9+:
Caused by: java.lang.NullPointerException
at org.apache.maven.surefire.shade.org.apache.commons.lang3.SystemUtils.isJavaVersionAtLeast (SystemUtils.java:1626)
GroupId | ArtifactId | Version | Issue |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For internationalization (i18n) and localization (l10n) ResourceBundle
is used for language and country specific texts and configurations as properties (e.g. MyResourceBundle_de.properties
). With Java modules there are changes and impacts you need to know to get things working. The most important change is documented in the JavaDoc of ResourceBundle. However, instead of using ResourceBundleProvider and refactoring your entire code causing incompatibilities, you can simply put the resource bundles in a regular JAR on the classpath rather than a named module (or into the lauching app).
If you want to implement (new) Java modules with i18n support, you can have a look at mmm-nls.
If you also want to change your build to work with a recent JDK you also need to ensure that test frameworks and maven plugins properly support this.
Findbugs does not work with Java 9+ and is actually a dead project. The new findbugs is SpotBugs. For maven the new solution is spotbugs-maven-plugin:
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>3.1.11</version>
</plugin>
GroupId | ArtifactId | Version | Issue |
---|---|---|---|
|
|
|
GroupId | ArtifactId | (min.) Version | Issue |
---|---|---|---|
|
|
|
x |
|
|
|
|
|
|
|
|
|
|
|
x |
|
|
|
x |
|
|
|
With Java modules you can not run Javadoc standalone anymore or you will get this error when running mvn javadoc:javadoc
:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:3.1.1:javadoc (default-cli) on project mmm-base: An error has occurred in Javadoc report generation:
[ERROR] Exit code: 1 - error: module not found: io.github.mmm.base
[ERROR]
[ERROR] Command line was: /projects/mmm/software/java/bin/javadoc @options @packages @argfile
As a solution or workaround you need to include the compile
goal into your build lifecycle so the module-path is properly configured:
mvn compile javadoc:javadoc
We want to give credits and say thanks to the following articles that have been there before and helped us on our way:
This documentation is licensed under the Creative Commons License (Attribution-NoDerivatives 4.0 International).