Sent from Hauptstadt!

ein Blog für den geneigten Leser

JDKs verwalten mit SDKMAN

Tags: , ,

Kategorie Software Engineering | Keine Kommentare »

Ich freue mich immer, wenn ich ein neues Werkzeug entdecke, das mir tatsächlich Arbeit abnimmt. Vor einigen Wochen bin ich über SDKMAN gestolpert. Damit kann ich mehrere JDKs und weitere Java SDKs installieren und verwalten. In der täglichen Entwicklungsarbeit ist das extrem hilfreich.

JDKs manuell wechseln

Aktuell arbeite ich an verschiedenen Java und Kotlin Projekten, die Java 8 und 11 nutzen. Entwickeln tue ich natürlich in IntelliJ, aber trotzdem möchte ich auch auf der Kommandozeile die Projekte mit dem richtigen JDK kompilieren, testen und paketieren können. Je nach Projekt muss ich unterschiedliche JDKs verwenden.

In Linux, und natürlich auch in MacOS und Windows, ist es prinzipiell kein Problem, mehrere JDKs parallel zu installieren. Der Systempfad und die JAVA_HOME Umgebungsvariable kann aber nur auf ein JDK zeigen. Deshalb behelfen sich viele Entwickler mit selbstgestrickten Skripten, um das aktuelle JDK umstellen zu können. Mit SDKMAN habe ich eine bessere Lösung entdeckt.

SDKMAN installieren

SDKMAN ist eine kleine Sammlung von Shell Skripten, um JDKs und andere Java SDKs wie Maven und Gradle zu verwalten. Auch andere JVM Sprachen und Frameworks wie Scala und das Scala Bauwerkzeug Sbt können darüber verwaltet werden.

Die Installation von SDKMAN ist denkbar einfach. Nach dem Download fügt SDKMAN sich zur Shell Umgebung hinzu, indem es sich am Ende der .bashrc bzw. .zshrc Datei selbst lädt. Anschließend kann es über den Befehl sdk angesprochen werden. Ich habe SDKMAN sowohl mit GNU Bash als auch mit ZSH unter Ubuntu erfolgreich getestet.

JDK & Maven mittels SDKMAN installieren

Um ein Java JDK zu installieren, lasse ich mir zunächst die Liste aller in SDKMAN verfügbaren JDKs anzeigen:

sdk list java

Ein kurzer Blick zeigt, die Liste der verfügbaren JDKs ist riesig. Es gibt verschiedene JDK Anbieter wie AdoptOpenJDK, Oracle, Microsoft und SAP, um nur einige zu nennen. Jeder Anbieter stellt seine JDKs in verschiedenen Java Versionen zur Verfügung. Im Fall von AdoptOpenJDK gibt es jede Version sogar noch mit HotSpot und OpenJ9 JVM.

Ausgabe der aktuell von SDKMAN unterstützten AdoptOpenJDK Versionen und Varianten

Die ID in der letzten Spalte ist wichtig, wenn ich ein JDK installieren möchte. Das Java 16 HotSpot JDK von AdoptOpenJDK würde ich folgendermaßen installieren:

sdk install java 16.0.1.hs-adpt

SDKMAN lädt nun das JDK runter und entpackt es in ~/.sdkman/candidates/java/16.0.1.hs-adpt. Schon allein dieser automatisierte Download und Installation ist elegant und für jede Version und Anbieter identisch.

Auf die gleiche Weise kann ich weitere JDKs oder andere SDKs wie Maven und Gradle installieren. Neben den JDKs habe ich noch Maven 3.6 installiert.

sdk install maven 3.6.3

Natürlich prüft SDKMAN immer wieder, ob es neue Versionen gibt. Selbst ein Update von SDKMAN selbst wird mir automatisch angeboten und ich muss dann die Installation nur noch kurz bestätigen.

JDK mit SDKMAN manuell wechseln

Während der Installation fragt SDKMAN, ob er die gerade installierte Version als Standard setzen soll. In meinem Fall habe ich 2 JDKs installiert. Möchte ich in meiner aktuellen Shell Session eine andere Version verwenden, schreibe ich:

sdk use java 16.0.1.hs-adpt

Damit ich nicht die komplizierte ID eintippen muss, kann ich über die Konfigurationsdatei von SDKMAN ~/.sdkman/etc/config die Autovervollständigung aktivieren. Dazu muss ich folgende Konfigvariable auf true setzen:

sdkman_auto_complete=true

Jetzt brauche ich nur noch TAB zu drücken, um die ID vervollständigen zu lassen.

JDK automatisch wechseln

Da ich täglich mit unterschiedlichen JDKs arbeite, wäre es mühsam, das richtige jeweils manuell auszuwählen. Hinzu kommt, die Auswahl gilt immer nur für die aktuelle Shell und nicht für ein zweites Terminal. Glücklicherweise bietet SDKMAN einen eleganten Mechanismus, um automatisch das richtige JDK bzw. SDK auszuwählen.

Dazu klinkt sich SDKMAN in den cd Befehl ein. Das lohnt nur, wenn man täglich mit unterschiedlichen SDKs arbeitet. Auf meinem Arbeitsrechner ist das der Fall, auf meinem privaten Rechner habe ich diese Option hingegen nicht aktiviert.

Das so genannte Auto-Env (automatische Umgebung) Feature aktiviere ich über folgende Konfigvariable:

sdkman_auto_env=true

Wechsel ich in meiner Shell das Verzeichnis mit cd, prüft SDKMAN beim Betreten des neuen Verzeichnis, ob eine .sdkmanrc Datei existiert. In dieser kann ich die gewünschten SDKs angeben, etwa:

java=11.0.11.hs-adpt
maven=3.6.3

Ich erstelle deshalb solche .sdkmanrc Dateien in den Wurzelverzeichnissen meiner Java/Kotlin Projekte. Wenn ich nun im Terminal solch ein Projekt betrete, setzt SDKMAN automatisch alle gewünschten SDKs und ich muss diese nicht mehr manuell auswählen. Das ist extrem komfortabel!

Welche SDKs mit SDKMAN installieren?

Neben den erwähnten JDKs kann ich mit SDKMAN eine Vielzahl weiterer SDKs auf dem JVM Umfeld verwalten. Beispiele:

  • Maven
  • Gradle
  • Spring Boot
  • Tomcat
  • Micronaut

Tatsächlich macht es in den meisten Fällen keinen Sinn, Frameworks wie Spring Boot oder Micronaut über SDKMAN zu verwalten. Solche Abhängigkeiten definiere ich immer über Maven (bzw. Gradle). Das gilt auch für den Kotlin Compiler. Ich will ja nicht eine Datei manuell kompilieren, sondern überlasse den Aufruf des Compilers mit seinen zig Optionen lieber dem Bauwerkzeug (Maven / Gradle).

Schön wäre hingegen, wenn ich über SDKMAN auch SDKs aus anderen Bereichen installieren könnte. So wäre es fantastisch, wenn ich Node.js / NPM ebenfalls über SDKMAN installieren könnte. Spezielle Web Frameworks wie Angular würde ich dann aber wiederum über NPM verwalten.

SDKMAN JDKs in IntelliJ nutzen

Auch in IntelliJ nutze ich ausschließlich die über SDKMAN installierten JDKs. IntelliJ findet die automatisch. Einziger Stolperstein ist das für die Ausführung von Maven verwendete JDK. Hier verwendet IntelliJ standardmäßig das mit IntelliJ ausgelieferte JDK.

Das ist auch solange kein Problem, wie man keine eigenen SSL Root Zertifikate in die von SDKMAN verwalteten JDKs importiert hat. Leider klappt in meinem Fall der Zugriff auf das zentrale Artefakt Repository nur mit einem speziellen SSL Zertifikat. Deshalb muss ich IntelliJ mitteilen, dass es das SDKMAN JDK nutzen muss, wenn es:

  • Maven Abhängigkeiten runterlädt
  • Maven ausführt

Dafür gibt es 2 Einträge in den IntelliJ Einstellungen.

Maven Einstellungen in IntelliJ

Der komplette Pfad lautet „Build, Execution, Deployment“ -> „Build Tools“ -> „Maven“:

  • „Importing“ -> „JDK for importer“
  • „Runner“ -> „JRE“

Ja ja, man kann sich in den Einstellungen von IntelliJ verlieren…

Fazit

Früher habe ich es wochenlang rausgezögert, ein JDK Update zu installieren. Ich habe auch immer versucht, dass möglichst alle Projekte die gleiche Java Version nutzen. Gerade im Microservice Umfeld ist das aber hoffnungslos, da es zu viele Projekte von unterschiedlichen Teams gibt, die alle ihr eigenes Süppchen kochen. Hier ist SDKMAN eine enorme Hilfe im Entwickleralltag.

Schreiben sie ein Kommentar