:toc: macro toc::[] = Java Development Kit The https://en.wikipedia.org/wiki/Java_Development_Kit[Java Development Kit] is an implementation of the Java platform. It provides the https://en.wikipedia.org/wiki/Java_virtual_machine[Java Virtual Machine] (JVM) and the Java Runtime Environment (JRE). == Editions The JDK exists in different editions: * https://openjdk.java.net/[OpenJDK] is a free and open-source edition of the JDK. * https://www.oracle.com/technetwork/java/javase/overview/index.html[OracleJDK] is a commercial edition of the JDK. * https://en.wikipedia.org/wiki/List_of_Java_virtual_machines[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 https://bugs.openjdk.java.net/browse/JDK-8212233[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 https://adoptium.net/[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 https://github.com/devonfw/ide[devonfw-ide]. == Garbage Collection 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 https://www.baeldung.com/java-gc-logging-to-file[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 https://github.com/chewiebug/GCViewer[GCViewer]. If you are already using https://github.com/devonfw/ide[devonfw-ide], that integrates all cool developer tools you may need, you can just call this command: ``` devon gcviewer ``` In the UI of GCViewer, simply open your GC logfile and you will get a visualization of the heap activity over time. For more details see https://sematext.com/blog/java-garbage-collection-logs/[here]. == Thread Dump Sometimes you may face concurrency issues or even deadlocks where threads block each other. In such case you should https://www.baeldung.com/java-thread-dump[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. == Upgrading 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). === Runtime Changes This section describes required changes to your software in order to make it run also with versions newer than Java 8. ==== Classes removed from JDK 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 ``` As Java 9 introduced a module system with https://www.baeldung.com/project-jigsaw-java-modularity[Jigsaw], the JDK that has been a monolithic mess is now a well-defined set of structured modules. Some of the classes that used to come with the JDK moved to modules that where not available by default in Java 9 and have even been removed entirely in later versions of Java. Therefore you should simply treat such code just like any other 3rd party component that you can add as a (maven) dependency. The following table gives you the required hints to make your software work even with such classes / modules removed from the JDK (please note that the specified version is just a suggestion that worked, feel free to pick a more recent or more appropriate version): .Dependencies for classes removed from Java 8 since 9+ [options="header"] |============================================= |*Class* |*GroupId* |*ArtifactId* |*Version* |`javax.xml.bind.*` |`javax.xml.bind` |`jaxb-api` |`2.3.1` |`com.sun.xml.bind.*` |`org.glassfish.jaxb`|`jaxb-runtime` |`2.3.1` |`java.activation.*` |`javax.activation` |`javax.activation-api` |`1.2.0` |`java.transaction.*` |`javax.transaction` |`javax.transaction-api`|`1.2` |`java.xml.ws.*` |`javax.xml.ws` |`jaxws-api` |`2.3.1` |`javax.jws.*` |`javax.jws` |`javax.jws-api` |`1.1` |`javax.annotation.*` |`javax.annotation` |`javax.annotation-api` |`1.3.2` |============================================= ==== 3rd Party Updates 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) ``` Therefore the following table gives an overview of common 3rd party libraries that have been affected by such breaking changes and need to be updated to at least the specified version: .Minimum recommended versions of common 3rd party for Java 9+ [options="header"] |============================================= |*GroupId* |*ArtifactId* |*Version*|*Issue* |`org.apache.commons`|`commons-lang3`|`3.7`|https://issues.apache.org/jira/browse/LANG-1365[LANG-1365] |`cglib`|`cglib`|`3.2.9`|https://github.com/cglib/cglib/issues/102[102], https://github.com/cglib/cglib/issues/93[93], https://github.com/cglib/cglib/issues/133[133] |`org.ow2.asm`|`asm`|`7.1`|https://github.com/eclipse/jetty.project/issues/2941[2941] |`org.javassist`|`javassist`|`3.25.0-GA`|https://github.com/jboss-javassist/javassist/issues/194[194], https://github.com/jboss-javassist/javassist/issues/228[228], https://github.com/jboss-javassist/javassist/issues/246[246], https://github.com/jboss-javassist/javassist/issues/171[171] |============================================= ==== ResourceBundles 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 https://docs.oracle.com/javase/9/docs/api/java/util/ResourceBundle.html#bundleprovider[JavaDoc of ResourceBundle]. However, instead of using https://docs.oracle.com/javase/9/docs/api/java/util/spi/ResourceBundleProvider.html[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 https://github.com/m-m-m/nls#mmm-nls[mmm-nls]. === Buildtime Changes 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 Findbugs does not work with Java 9+ and is actually a dead project. The new findbugs is https://spotbugs.github.io/[SpotBugs]. For maven the new solution is https://spotbugs.github.io/spotbugs-maven-plugin/[spotbugs-maven-plugin]: ``` com.github.spotbugs spotbugs-maven-plugin 3.1.11 ``` ==== Test Frameworks .Minimum recommended versions of common 3rd party test frameworks for Java 9+ [options="header"] |============================================= |*GroupId* |*ArtifactId* |*Version*|*Issue* |`org.mockito`|`mockito-core`|`2.23.4`|https://github.com/mockito/mockito/issues/1419[1419], https://github.com/mockito/mockito/issues/1696[1696], https://github.com/mockito/mockito/issues/1607[1607], https://github.com/mockito/mockito/issues/1594[1594], https://github.com/mockito/mockito/issues/1577[1577], https://github.com/mockito/mockito/issues/1482[1482] |============================================= ==== Maven Plugins .Minimum recommended versions of common maven plugins for Java 9+ [options="header"] |============================================= |*GroupId* |*ArtifactId* |*(min.) Version*|*Issue* |`org.apache.maven.plugins`|`maven-compiler-plugin`|`3.8.1`|x |`org.apache.maven.plugins`|`maven-surefire-plugin`|`2.22.2`|https://issues.apache.org/jira/browse/SUREFIRE-1439[SUREFIRE-1439] |`org.apache.maven.plugins`|`maven-surefire-report-plugin`|`2.22.2`|https://issues.apache.org/jira/browse/SUREFIRE-1439[SUREFIRE-1439] |`org.apache.maven.plugins`|`maven-archetype-plugin`|`3.1.0`|x |`org.apache.maven.plugins`|`maven-javadoc-plugin`|`3.1.0`|x |`org.jacoco`|`jacoco-maven-plugin`|`0.8.3`|https://github.com/jacoco/jacoco/issues/663[663] |============================================= ==== Maven Usage 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 ``` == Sources and Links We want to give credits and say thanks to the following articles that have been there before and helped us on our way: * https://blog.codefx.org/java/java-9-migration-guide/[Java 9 Migration Guide: The Seven Most Common Challenges] * https://medium.com/criciumadev/its-time-migrating-to-java-11-5eb3868354f9[It’s time! Migrating to Java 11] * https://winterbe.com/posts/2018/08/29/migrate-maven-projects-to-java-11-jigsaw/[Migrate Maven Projects to Java 11] * https://www.jesperdj.com/2018/09/30/jaxb-on-java-9-10-11-and-beyond/[JAXB on Java 9, 10, 11 and beyond] * https://stackoverflow.com/questions/26413431/which-artifacts-should-i-use-for-jaxb-ri-in-my-maven-project[JAXB Artifacts]