30 Jahre Java – Erinnerungen eines alten Sacks

Java hat kürzlich („kürzlich“ im Kontext dieses Blogs zu verstehen, wo Ereignisse gerne mal ein paar Monate bis Jahre später kommentiert werden) sein 30-jähriges Jubiläum gefeiert. Am 23. Mai 1995 erblickte das erste Release das Licht der Welt. Ich weiß noch wie heute, als ich…nein, das ist gelogen. Ich weiß nicht mal mehr, wann ich mein erstes Java-Programm wirklich mit dem JDK compiliert habe, und was es gemacht hat (ich vermute, ein Fenster per AWT geöffnet) – aber es war das JDK Version 1.0.2. Müsste ich noch auf irgendeiner CD rumliegen haben.

Mein erster Eindruck von Java war sehr gemischt. Ich kannte – im Sinne von „seriös benutzt“, nicht nur „mal gesehen“ – damals verschiedene BASIC-Dialekte, Z80- und ARM-Assembler, Smalltalk, C, C++ (CFront-Variante, Stand 1994 oder so), Turbo Pascal (inklusive der OO-Features von TP 5.5), Modula-2, Ada 83 und Ada 9X, Scheme, Lisp und Prolog. An Java gefielen mir die Interfaces, die Idee mit JavaDoc, das AWT als Chance für „write-once-run-anywhere“ auch für Anwendungen mit grafischer Oberfläche, die umfangreiche (was eben damals als umfangreich durchging…) Systembibliothek, und die prinzipielle Idee der JVM als abstrahierende, portierbare Runtime. Und natürlich der Garbage Collector. Auch die Applets, um dem drögen statischen HTML-Content endlich etwas Interaktivität beizubringen erschien als coole Idee. Unicode-out-of-the-box war sicher auch eine bemerkenswerte Idee. Und die integrierten Mechanismen zur Serialisierung von Objekten klangen auch cool. Und die vier Levels der Sichtbarkeit fanden auch mein Gefallen. Reflection schien Potenzial zu haben, auch wenn ich damals noch nicht ahnte, was man damit alles veranstalten kann. Und die Java-Variante der Exceptions fand ich cooler als die Ada-Variante, weil Java den Programmierer zu „throws“-Klauseln zwang, während bei Ada im Prinzip alles RuntimeExceptions waren und separat, also nicht erzwungen im Code, dokumentiert werden mussten – und bekanntlich laufen Code und Doku gerne mal auseinander.

Aber da war auch die andere Seite. Das Multithreading war löblich, aber gegenüber dem Tasking aus Ada doch sehr rudimentär – auf der anderen Seite aber auch ein – wenn auch unnötig kleiner – Fortschritt gegenüber pthreads. Die Basisdatentypen waren zwar Gott sei Dank genau spezifiziert (was in C bezüglich der Portabilität immer zu Schwierigkeiten führte, wenn man nicht höllisch aufpasste), aber sehr leistungsarm gegenüber beispielsweise Ada. Kein Operator Overloading. Records mussten durch Klassen abgebildet werden und hatten keine Kontrolle über die Repräsentation im Speicher. Arrays begannen immer mit Index 0. Keine Syntax für Methode-in-Methode. Kein Datentyp für Aufzählungen. Die merkwürdige Mischung aus „alles ist ein Objekt, außer Basisdatentypen“. Keine Generics wie in Ada oder C++, so dass man wieder auf Runtime-Typechecking statt Compile-Time-Safety angewiesen war. Der Interpreter der JVM ging eher gemächlich zu Sache. Der GC ebenso. Threads waren keine nativen OS-Threads, sondern wurden von der JVM simuliert („green threads“). Startup von Anwendungen war sehr gemächlich. Und das AWT war wirklich „kleinster gemeinsamer Nenner“ und mit dem Java 1.0-Sprachumfang, der bekanntlich weder innere Klassen noch deren anonyme Ausprägung unterstützte, sehr „harzig“ zu benutzen, weil man kein Event-Listener-Konzept hatte mit Callbacks, sondern im Prinzip alles ableitete und die entscheidenden Methoden überschreiben musste.

„Gemischt“ war auch das Stichwort zur Einschätzung der Lage beim damals tobenden Streit „curly-braces vs. begin-end“. Ich fand begin-end nach Pascal- oder Modula-Art nicht so gut, nach Ada-Art aber super. Und das Fehlen von Mehrfachvererbung hat auch sein Für und Wider, die Erfindung der Interfaces schien aber den Mangel ausreichend abzumildern.

Nach diesem ersten durchwachsenen Eindruck legte ich Java erst mal wieder beiseite. Im Endstadium meines Informatik-Studiums hießen die Programmiersprachen der Wahl DEC Pascal (Ada-ähnlich) in der Studienarbeit, C++ (mit dem IBM XLC als Compiler auf AIX, der leider die neuen coolen C++-Features allesamt vermissen ließ) in der Diplomarbeit, und Ada 95 für mein privates Großprojekt CDBurn https://www.hubersn-software.com/products_legacy.html. Die Idee des „Java-NC“ bzw. des ThinClients generell setzte sich nicht durch, obwohl es mit Erscheinen von Java durchaus größere Aktivitäten von großen Softwarehäusern gab, relevante Softwarepakete nach Java zu überführen. Ich nenne mal Corel Office als prominentes Beispiel. Es war schon beeindruckend zu sehen, dass WordPerfect plötzlich auf dem RISC OS-Desktop lief, und das alles bloß aufgrund der Verfügbarkeit einer Java-Runtime. Aber genau wie der Java-Prozessor von Sun und CPU-Features wie Jazelle von ARM für die beschleunigte Ausführung von Bytecode setzte sich das nicht durch. Die Zeit war noch nicht reif, die CPUs noch nicht schnell genug, die JVM noch zu lahmelig. Zuviele Abstraktionsschichten sind des Performancempfindens‘ Tod. Software als Sanduhr-Anzeige-Programm. Die Älteren fühlten sich bezüglich der fehlenden Schwuppdizität an Emacs erinnert („Eight Megabytes And Constantly Swapping“).

Aber ich hatte weiter ein Auge auf Java und nahm erfreut zur Kenntnis, dass einige wichtige Sprachfeatures in Java 1.1 nachgerüstet wurden – Stichwort innere Klassen und anonyme innere Klassen, die für die neue AWT- und Swing-Event-Listener-Mechanik essentiell waren – und an der Browser-Front Java 1.1 quasi serienmäßig zur Ausführung von Applets eingebaut wurde – HotJava und Internet Explorer waren die Vorreiter, für alle anderen gab es das Java-PlugIn. Dass Netscape dann mit „JavaScript“ etwas Verwirrung stiftete und Microsoft die übliche Embrace-and-extend-Strategie versuchte, waren bemerkenswerte aber letztlich irrelevante Randnotizen der Geschichte. Ende 1997 war auch noch das Release von Java 1.0.2 für RISC OS bemerkenswert (offiziell von Sun lizenziert und von Acorn implementiert), und Chockcino als clean-room-Java-1.1-Implementierung wurde angekündigt – in der damaligen Welt, als viele Homebanking-Lösungen auf Java 1.1-Applets setzten, war es überaus enttäuschend, dass diese Ankündigung niemals wahr wurde. Ein weiterer Sargnagel für RISC OS.

Mit Java 1.1 begann Sun auch endlich, an der Ablösung bzw. Ergänzung des leistungsschwachen AWT zu arbeiten. „Swing“ war in aller Munde, und mit Swing 1.0.2 („com.sun.java.swing“) und erst recht mit Swing 1.1.1 („javax.swing“) konnte man endlich mit einem reichhaltigen, leistungsfähigen Werkzeugkasten plattformübergreifend UIs bauen. Swing wurde damals, wohl um den Zusammenhang zu MFC, den „Microsoft Foundation Classes“, dem damaligen Benchmark für UI-Klassenbibliotheken, „JFC“ genannt – die „Java Foundation Classes“. Genaugenommen umfasste das AWT, Swing und Java2D. Und wir lernten damals, dass „lightweight“ nicht unbedingt in allen Kontexten für „schnell und speicherplatzsparend“ steht.

Ende 1998 dann das Release von Java 1.2, ein echter Meilenstein, und deshalb zurecht „Java 2 Platform“ genannt. Das Collection-Framework war ein riesiger Fortschritt (vorher war entweder „Vector“ oder „Hashtable“ allüberall genutzt), und Swing war nun endlich integrierter Teil des JDK. Allerdings dauerte es ein wenig, bis alles wirklich stabil und gut war – Java 1.2.2 war schließlich die Version der Wahl ab Mitte 1999. RMI wurde nutzbar (wenn auch umständlich mit rmic und stubs und skeletons), JIT und GC wurden performanter, das Plugin etablierte sich als Ausführungsumgebung in allen gängigen Browsern.

Ich will nicht durch alle Java-Meilensteine durchgehen, das dauert Stunden und kann auch von ChatGPT erzeugt werden. Aus der Praxis kann ich noch berichten, dass Java bei meinem ersten Arbeitgeber Anfang 1999 als Mittel der Wahl für die Implementierung eines großen Softwaresystems auserkoren wurde. Eine Entscheidung mit erheblichem Risiko damals. Hauptgründe dafür: die starke Unterstützung von IBM und damit die versprochene Verfügbarkeit von Integrationscode für Großrechner-Technologien wie MQ, CICS und IMS. Und die Cross-Platform-UI-Geschichte, weil die ersten drei interessanten Kunden drei verschiedene Client-Technologien am Start hatten: Windows, OS/2 und Linux (sowohl x86 als auch PowerPC). Im Nachhinein, nachdem die Software nun etwa 25 Jahre in Produktion ist, kann man wohl sagen: es war die richtige Wahl. Die Software lief erfolgreich produktiv auf Servern aller Art, von Windows über Linux und Solaris bis zu AIX. Clientseitig auf Windows, OS/2 und Linux sowohl als FatClient als auch als WebStart-Anwendung und natürlich auch lange als Applet, in einem Fall voll integriert in eine Kunden-Fachanwendung mit speziell gedengeltem Swing-L&F, so dass der „Bruch“ im Browser zwischen den beiden Anwendungen praktisch unsichtbar wurde. Erwähnenswert zum Start der Entwicklung 1999: wichtige Maßgabe am Anfang war die Anforderung eines potenziellen Kunden, dass der Code (zumindest der Client-Code für die UI) auch unter Java 1.1 laufen muss. Ich vermute, dass man deshalb noch in einzelnen Teilen des Sourcecodes einen „Vector“ findet, der Objekte per „addElement“ bekommt.

Ebenfalls erwähnen will ich „IBM VisualAge for Java“ als meine erste IDE. Positiv zu nennen: es war der Grund für den Chef, für die Entwickler-Rechner die damals nahezu als „unendlich“ kategorisierte Menge von 256 MB RAM zu spendieren (AMD K6-II damals als CPU, Windows NT 4 als OS). Und das war auch dringend nötig. Die IDE war schneckenlahm, ein in Smalltalk geschriebenes Monster, und die Idee, den Code nicht im Dateisystem zu haben sondern in einem „Repository“, das im Prinzip eine Datenbank war, und dann nur per Import und Export wieder Dateien draus zu machen – gewöhnungsbedürftig. Genauso wie die Tatsache, dass die Suchfunktion nicht alle Fundstellen tatsächlich gefunden hat. Und der VCE, der „Visual Component Editor“, war mein erster Versuch mit einem GUI-Builder. Er war optimal geeignet, schon damals meine Überzeugung zu befüttern, dass GUI-Code, zumindest wenn das Layout dynamisch per LayoutManager gemacht werden soll, am besten von Hand geschrieben wird. Der eigentliche Grund, VisualAge zu verwenden – das IBM-Versprechen, in der „Enterprise-Edition“ diverse Großrechner-Integrationsbausteine einfacher verwenden zu können – war alsbald als vage Marketing-Idee entlarvt, und die Entwickler entschieden sich für Forte4Java (eine freie Version von NetBeans, damals von Sun entwickelt), JBuilder oder UltraEdit, bis sich dann alle wieder bei Eclipse 2.1 zusammenfinden konnten.

Es gab einige kritische Momente in der Java-Geschichte – die Anwandlungen von Microsoft, einen inkompatiblen Ableger zu schaffen. Die schleppende Weiterentwicklung, auch durch die finanziellen Probleme von Sun. Der beschwerliche Weg in die vollständige Open-Source-JDK-Welt von heute. Die Übernahme durch Oracle und so manche Detailverwirrung bei der Lizenzierung. Undurchschaubare Strategiewechsel bei Oracle. Aber letztlich waren das – allen Unkenrufen, auch von mir, zum Trotz – nur kurzfristige Irritationen.

Interessant in der langen Java-Geschichte finde ich den „ersten Wendepunkt“: von Konstruktion und Features her startete Java ja, obwohl in einer Server-lastigen Firma erfunden, mit starkem Client-Fokus. Fast, als ob die Erfinder dringend Microsoft ans Bein pinkeln wollten. Irgendwann, so ab Java 1.3, drehte sich das dann – auch dank Java EE und Application Servern und der Verfügbarkeit performanter JREs auf allen relevanten Plattformen – nahezu komplett in Richtung Server und Enterprise, während der Client mehr und mehr aufs Abstellgleis geschoben wurde. Und später ironischerweise durch Google mit Android und GWT wiederbelebt wurde. Man könnte sicher interessante historische Abhandlungen drüber schreiben.

Heute würde ich Java als „lebendiger denn je“ bezeichnen. Der Hotspot-JIT erzeugt sehr effizienten Code (wenn er lange genug läuft), die Garbage-Collectors sind effizient auch bei unglaublich großen Heaps und haben inzwischen unglaublich kurze STW-Zeiten, und das Tooling ist generell sehr ausgereift, dazu die Auswahl an zig stabilen und leistungsfähigen Frameworks. Die neue „release cadence“ sorgt für rasche – manchmal für mich fast zu rasche – Weiterentwicklung der Sprache, ohne die so identitätsstiftende Rückwärtskompatibilität aus den Augen zu verlieren. Es ist schon bemerkenswert, dass man heute ohne größere Handstände immer noch Java 8-Code schreiben kann, der auch problemlos noch unter Windows XP lauffähig ist. Sprachen, die Java beerben wollten wie Scala oder Kotlin sind letztlich nur Ergänzungen des JVM-Ökosystems geworden, dank der inzwischen raschen Weiterentwicklung von Java aber aus meiner Sicht maximal als Ideengeber relevant. Und dank neuerer Entwicklungen wie der direkten Ausführbarkeit von Java-Files ohne vorherigen Compile-Schritt und der diversen Vereinfachungen unter dem Schlagwort „simple onramp“ nebst coolem Tooling wie JBang ist Java inzwischen selbst für Aufgaben, die klassischerweise mit dedizierten Skriptsprachen erledigt wurden, eine interessante Alternative. Keine andere Sprache ist ähnlich universell einsetzbar. Manche Sprachen sind in speziellen Bereichen die bessere Wahl, aber keine andere Sprache ist in so vielen Bereichen „good enough“, vom einfachen Skript bis zur Enterprise-Anwendung, vom Microservice bis zur FatClient-Applikation.

Und seit ich regelmäßig Konferenzvorträge von Brian Goetz schaue, habe ich auch großes Vertrauen, dass die Sprache Java weiterhin mit Augenmaß, aber kontinuierlich weiterentwickelt wird.

Wer anderer Leute „trip down the memory lane“ lesen/schauen will: der offizielle Geburtstagslivestream, die JetBrains-Jubiläums-Seite, und interessante Erinnerungsstücke bis zurück in die Gründerzeit von BellSoft-Mitarbeitern.

Gedanken zum Thema KI, leicht aktualisiert

Immer wieder schrieb ich in der Vergangenheit kurze Happen zum Thema KI – hier, hier oder auch hier. Es war 2017, als ich zuletzt zusammenhängend Gedanken zum Thema KI im IT-Kontext formuliert habe. Über 8 Jahre später stelle ich fest, dass meine damals formulierten Wünsche an die KI leider noch nicht zu meiner Zufriedenheit erfüllt wurden. Während das Thema „automatische Übersetzung“ nun zweifellos zumindest zwischen Englisch und Deutsch so einigermaßen akzeptabel – wenn auch noch lange nicht perfekt – funktioniert, ist das Thema „autonomes Fahren Stufe 5“ leider weiterhin Zukunftsmusik. Was Waymo da inzwischen hinkriegt, ist zwar durchaus beeindruckend, aber eben auch noch sehr weit weg von „funktioniert überall, ohne Remote Supervision, ohne Einschränkungen, bei jedem Wetter, auf allen Strecken“. Der Status Quo ist allzu oft „tut so leidlich, aber nicht wirklich gut“. Schon mal eine automatische Übersetzung vom Finnischen ins Deutsche versucht?

Nun kam es ja in den letzten 8 Jahren zum größten Fortschritt der KI in der IT-Historie, die LLM-Revolution, angeführt von ChatGPT. Zeit für eine neue Bestandsaufnahme. Ich bin kein Experte für KI-Innereien, für die neuesten Forschungsergebnisse, für die aktuellsten Trends, für die ganzen verschiedenen Modelle und ihre jeweiligen Stärken und Schwächen. Ich bin nur KI-Anwender und beobachte die zur Verfügung stehende real existierende Qualität.

Bei der Softwareentwicklung hat insbesondere dank der KI-Agenten inzwischen die Unterstützung einen Stand erreicht, den man durchaus als nützlich bezeichnen kann. In diesem Bereich kann KI durchaus Zeit sparen, allerdings verschiebt sich der Aufwand für den erfahrenen Entwickler von recherchieren-und-nachdenken-und-codieren-und-refactorn hin zu reviewen-und-Prompts-umformulieren-und-prüfen-und-verstehen. Ich fand diese Studie sehr erhellend, weil sie meine unsortierten Gedanken zum Thema schön aufnimmt und ordnet: Beschäftigung mit dem Code, drüber nachdenken, auch mal Sackgassen erforschen, testen, debuggen, umbauen, erweitern, scheitern, optimieren – all das baut am hirn-internen Modell eines Stücks Software. Wenn man Teile davon an KI auslagert, verkümmert dieses mentale Modell, was sich nachteilig auf die weitere Entwicklungsgeschwindigkeit auswirken kann. Und man muss auch festhalten, dass KI zur eigenständigen Bearbeitung von wirklich komplexen und umfassenden Aufgabenstellungen – beispielsweise Performance-Optimierungen in großen Systemen oder das Beheben von Heisenbugs – weitgehend untauglich ist. Fast möchte man sagen, dass sich hier der Kreis schließt zum autonomen Fahren: als Assistenz tauglich, als unbeaufsichtigter Fahrer hingegen nicht.

Als enttäuschend empfinde ich nach wie vor, dass KI (oder, wie man genauer sagen muss: die spezifische KI, die ich zu diesem Problem befragt hatte) selbst an einfachen Aufgaben scheitert, vor allem, wenn es auf die Details ankommt. Zuletzt enttäuscht wurde ich bei der Frage nach der neuesten Version eines Maven-Plugins, das noch Java 7-tauglich ist (bitte nicht fragen, was der Hintergrund dieser Frage war…). Die Antwort war eine Versionsnummer, die gar nicht existierte. Auf erneute Nachfrage dann eine falsche Versionsnummer. Oder die Frage nach dem Zeitpunkt des Lizenzwechsels einer Open-Source-Bibliothek, wo nicht nur in der Antwort die Lizenzsituation falsch dargestellt wurde, sondern auch Zeitpunkt und Art des Lizenzwechsels. Und so bleibt für mich im Dunkeln, für welche Aufgaben die KI nun wirklich gut geeignet ist und für welche nicht – man weiß es erst hinterher, aber manchmal nur, wenn man die Antwort vorher schon kennt oder hinterher zeitaufwändig nachrecherchiert. Als Faustregel nehme ich mit: solange KI-Verfechter noch antworten mit „ja, da musst Du ein anderes LLM nehmen“ oder „ja, da musst Du den Prompt anders formulieren“, ist KI eigentlich keine KI, sondern mehr eine Pseudo-Intelligenz-Simulation. Was keinesfalls ausschließt, dass sie nützlich sein kann. Es gibt ja auch nützliche Idioten.

Befremdlich finde ich vor allem, dass jenseits der Chat-Systeme und hochspezialisierten und kostenintensiven professionellen Anwendungen die nützlichen Systeme weiterhin Mangelware sind. OpenAI hat ja nun ChatGPT-5 an den Start gebracht. Während das „Thinking“-/“Reasoning“-Modell wohl wirklich Fortschritte gegenüber dem Vorgänger bringt, scheint die automatische Auswahl des darunterliegenden Modells viel zu häufig in Richtung „billig und schnell“ zu routen – was zu katastrophalen Antwortqualitäten führt. Kein gutes Zeichen, denn erstens bedeutet das, dass OpenAI sparen muss und es sich nicht leisten kann selbst den zahlenden Nutzern stets das beste Modell zur Verfügung zu stellen. Und zweitens ist die „Router-KI“ selbst wohl einfach zu dumm, um die einfachen Fragen von den schwierigen Fragen zu unterscheiden. Die meisten Berichte deuten auch darauf hin, dass gegenüber ChatGPT-4, immerhin vor über 2 Jahren released, die Fortschritte eher iterativ denn revolutionär sind. Und hier denkt der Skeptiker in mir: oh je, wenn schon bei diesem Stand die „law of diminishing returns“ einsetzt, wird es wohl doch nix mit der großen KI-Revolution auf allen Ebenen.

Ganz grundsätzliche finde ich enttäuschend, mit wie viel Wissen derzeitige KI-Modelle trainiert werden müssen, um auch nur halbwegs vernünftige Antworten zu liefern. Das menschliche Hirn ist da um ein paar Größenordnungen genügsamer. Und das ist durchaus ein Problem, denn die verfügbare Menge an qualitativ ausreichend gutem Trainingsmaterial ist ja begrenzt. Wie man hört, mussten schon Transkripte von YouTube-Videos angefertigt werden, damit die Modelle neues Trainingsfutter bekommen konnten. Angesichts der durchschnittlichen Qualität von YouTube-Videos denkt man da unwillkürlich „hoffentlich hat den Schmonz jemand vorher kuratiert“. Und nicht zu vergessen das Kostenproblem: je mehr Trainingsdaten notwendig sind, desto höher die Initialkosten. Und natürlich auch die laufenden Kosten, um das „Modellwissen“ aktuell zu halten. Sehr ernüchternd in diesem Zusammenhang sind ja die Versuche verlaufen, KI-Systeme selbstlernend zu gestalten – die Antwortqualität stürzt recht schnell ins Bodenlose, wenn das Training nicht wohldefiniert und -kontrolliert geschieht.

Auch bedenkenswert: die Frage des Urheberrechts von Trainingsdaten und deren Verwendung ist weitgehend ungeklärt. Was, wenn das LLM urheberrechtlich geschützte Passagen weitgehend unverändert wieder als Antwort ausspuckt? Dieses Problem schwebt wie ein Damoklesschwert über der ganzen Branche, und ich gebe zu bedenken, dass die Urheberrechtsindustrie schon so manches Geschäftsmodell ruiniert hat, bevor es lukrativ und rentabel wurde. Allerdings könnte es sein, dass die KI-Industrie diesmal der Wettbewerber mit der größeren Keule ist.

Ebenfalls enttäuschend: ein seit Stunde 1 bekanntes Phänomen der LLM, das „Halluzinieren“, ist weiterhin nur bestenfalls abgemildert, aber keinesfalls gelöst. Das „Transformer“-Paper die Google-Jungs ist von 2017, GPT-3 (das erste beeindruckende LLM nach meinem Dafürhalten) ist von 2020. 5 Jahre Arbeit der klügsten und hochbezahltesten Köpfen der Welt, und keine Lösung in Sicht.

Ein Grundproblem der LLMs wird uns vermutlich noch viele Jahre begleiten: die Modelle haben keine Ahnung, zu welchem Prozentsatz ihre Antwort denn nun „richtig“ war. Das darf der Benutzer weiterhin selbst rausfinden. Und damit bedarf es einer gewissen Intelligenz des Nutzers, was aber gleichzeitig viele Anwendungsgebiete für diese Art von KI von vornherein ausschließt.

Vielleicht werden die Probleme alle mal gelöst in der näheren oder ferneren Zukunft. Vielleicht finden sich diverse Nischen, wo KI sich fest etablieren kann, gesetzt den Fall, sie wird jemals kosteneffizient einsetzbar sein – denn das ist ein weiterer möglicher Stolperstein: im Moment wird im Bereich KI ja unglaublich viel Geld verbrannt. Es gibt zahlreiche Parallelentwicklungen und Sackgassen, es steht quasi beliebig viel Investorengeld zur Verfügung, so dass man „erst mal machen“ kann, ohne auf die Wirtschaftlichkeit zu achten. Wenn die KI aber dann mal erwachsen wird, erst dann wird sich herausstellen, ob das Erledigen von Aufgaben, sei es selbständig oder unterstützend, wirtschaftlich sinnvoll möglich ist. Ausgehend vom Status Quo (wieviel Rechenleistung ist notwendig, was kostet das Training, was kostet die Berechnung, was waren die Fortschritte in den letzten 5 Jahren) komme ich jedenfalls zum Schluss, dass die „Artificial General Intelligence“, die manche schon länger prophezeien, noch sehr sehr weit entfernt ist. Ich würde sogar sagen: zu meinen Lebzeiten (optimistisch gerechnet: die nächsten 50 Jahre) werden wir das nicht erleben. NVidia wird es egal sein: schon zu Goldgräberzeiten wurden vor allem die Verkäufer der Werkzeuge reich und nur die allerwenigsten Nutzer der Werkzeuge.

So. Endlich mal wieder eine gescheite Vorhersage. Auf Wiedervorlage in 10 Jahren.

Eine neue Definition für KI

KI ist heute überall. Besonders gerne aber dort, wo bisher einfach nur „Software“ drin war, die einen mehr oder weniger intelligenten Eindruck gemacht hat (was auch häufig im Auge des Betrachters lag) – mit anderen Worten: die Begrifflichkeit wird inzwischen inflationär genutzt und es wird dringend eine Neudefinition gebraucht.

Mein Vorschlag: „Die Software enthält mehr als ein if-then-else-Konstrukt.“

Neues aus dem GraalVM-Universum

Lange nichts mehr zu Graal(VM) geschrieben. Eigentlich überflüssig, diese einleitenden Worte zu verwenden, denn so wenig, wie ich hier schreibe, ist es naturgemäß bei und zu praktisch jedem Thema lange her.

Jedenfalls gibt es ein neues Release, quasi passend und synchron zum Erscheinen von Java 21. Viel hat sich getan im Java-Universum – Projekt Loom aka „Virtual Threads“ hat es nun endlich final ins Release geschafft, etwas das Projekt Panama aka „Foreign Memory and Function and Vector API“ leider nicht vergönnt war. Egal, nach dem LTS-Release ist vor dem LTS-Release, machen wir solange halt JNA. Aber ich schweife ab.

Die GraalVM-Release-Notes vermelden neben den fast schon üblichen – teilweise weiterhin dramatischen – Verbesserungen im Bereich Memory Footprint, Startup Time und Throughput zwei aus meiner Sicht ganz wichtige Neuerungen: zum einen ist man das unselige „gu“-Zeugs los geworden. Bedeutet: man hat nicht mehr ein Graal-JDK rumliegen das man per „gu“-Aufruf quasi in situ und systemspezifisch anreichert und updated – z.B. mit Truffle-Sprachen – sondern die ganze polyglotte Geschichte ist nun in „einfache“ Maven-Abhängigkeiten gewandert, d.h. man kann (bzw. sollte können – ich hab’s nicht selbst verifiziert) nun z.B. tatsächlich sinnvoll die Rhino- bzw. Nashorn-Engine tatsächlich in Rente schicken und stattdessen die Javascript-Implementierung von Graal verwenden. Das ganze läuft unter dem Namen „Truffle Unchained“. Schöne Sache, weil dadurch die ganze Geschichte mit der polyglotten Programmierung endlich anständig und erwartungskonform ins Java-Ökosystem integriert wird anstatt eine GraalVM-Insellösung zu bleiben. Man sollte nur darauf achten, die „community“-Varianten als dependency anzuziehen, es sei denn man will sich mal wieder durch eine neue Variante einer Oracle-Lizenz („GFTC“) kämpfen, und gleichzeitig immer auf der Hut sein, dass Oracle nicht mal wieder was Signifikantes daran ändert.

Zweite wichtige Geschichte: Der G1-GC ist jetzt vollständig integriert und optimiert – im Juni-Release war davon ja schon einiges zu sehen, jetzt gibt es vernünftige Ergebnisse. Die GraalVM hatte da ja Nachholbedarf v.a. im Native-Image-Bereich, was für teils erhebliche Laufzeitnachteile gesorgt hat. Nicht zuletzt durch diese Neuerung ist es gelungen, dass AOT jetzt performancetechnisch beim Durchsatz auf demselben Niveau operiert wie „heated up HotSpot JIT“ – lange Zeit war es ja eine Art Tradeoff, ob der Startup-Time-Vorteil von Native Image wichtiger ist oder der Throughput-Vorteil des HotSpot-JIT. Diese Überlegung kann man sich jetzt sparen, wenn die Benchmarks von den Graal-Entwicklern der Wahrheit nahekommen.

Für Mac-Freunde mit ARM-CPU und Linux-on-ARM-Exoten vielleicht auch noch interessant: AArch64 aka ARM 64bit ist nun auch verfügbar. War es wohl schon bei früheren Graal-Releases, ich hab’s nur nicht mitgekriegt. Aber der oben genannte G1-GC hat es wohl jetzt erst in die AArch64-Native-Image-Implementierung geschafft. Warum auch immer…da will ich nicht länger drüber nachdenken.

Technologie, maximal dämlich genutzt

Neulich so in einem fernen Urlaubsland meiner Wahl. Nutzung von werbefinanzierten Streamingdiensten. Ich will nicht ins Detail gehen und nenne sie stellvertretend mal „YouTube“ und „Spotify“. Beide Dienste jedenfalls verfügen über weitergehende Informationen über mich – oder zumindest gehe ich davon aus, man hört ja so viel von der Datensammelwut der Anbieter. Also z.B. Informationen wie „Mailadresse“, „Name“ und „aus welchem Land wurden bisher die Dienste genutzt“ und „in welcher Sprache wurde bisher Content bevorzugt abgerufen“.

Nun sitze ich also hier im Urlaubsland meiner Wahl – ich will es nicht spoilern, aber es ist nicht deutschsprachig – und erfreue mich an Werbeeinsprengseln in einer mir fremden Sprache. Nämlich der des Urlaubslandes. Die fortschrittliche Technologie erlaubt es also, meinen derzeitigen Standort zu erkennen. Und bezieht dieses (in den 80ern hätte man gesagt: erstaunliche) Wissen dämlicherweise in die Entscheidung ein, in welcher Sprache mir Werbung eingespielt wird. Weil ich natürlich, sobald ich eine Landesgrenze überquere, plötzlich die Sprache des Ziellandes bevorzuge.

Es braucht schon fortgeschrittene KI, um die Wirksamkeit von Werbung derart nachhaltig zu torpedieren. Oder sehr dumme Entscheidungen von Produktverantwortlichen.

Sekunden? Minuten? Egal!

Man geht ja als ITler gerne mit der Zeit. Mindestens, um sich dann darüber aufzuregen, dass früher alles besser war.

Neulich habe ich einen neuen Drucker in Betrieb genommen. Geht jetzt per App. Klingt nach einer guten Idee, und war es letztlich auch. Aber zwischendrin dann etwas Schockierendes: bei der Erstbefüllung der Tintentanks kündigte die App an, dass das Befüllen einer Farbe (bei meinem Modell insgesamt 6) nicht weniger als 40 Minuten dauern soll. Gott sei Dank nur eine falsche Einheit in der App, die gedruckte Schnellanleitung sprach dann korrekt von 40s, und genau so war es.

Weiterer kleiner Zwischenfall: während der Drucker dann die Tinteninitialisierung vornimmt, schlägt die App vor, doch gleich mal währenddessen (der Initialisierungsvorgang dauert nicht weniger als 7 Minuten) das WLAN einzurichten. Gute Idee. Dazu braucht man das Admin-Passwort des Druckers. Das steht nur im Innern des Druckers (beim Anheben der kompletten oberen Einheit). Das Anheben ist aber genau das, was man während der Tinteninitialisierung AUF GAR KEINEN FALL machen darf, wie der Drucker auf seinem Display verkündet. Sagt einem die App aber nicht. Aber der erfahrene Installateur elektrischer Geräte hat vorher natürlich alle papiernen Handbuchfetzen (die meisten davon mit völlig überflüssigen Sicherheitshinweisen der Kategorie „Gerät eingesteckt nicht unter Wasser betreiben“ oder „auf Frequenz 2400 MHz wird mit 53 nW gesendet“) akribisch durchgearbeitet und hat deshalb das Passwort schon vorher notiert. Auch merkwürdig in der App: man hat es für notwendig erachtet, eine eigene Tastatur zu implementieren. Die echt komisch aussieht. Und für die Eingabe sicherer Passwörter gar nicht taugt. Aber man kann einfach auf die Standardtastatur zurückschalten. Könnte für den unbedarften Anwender aber schon eine Extrahürde sein, und der Sinn dahinter erschließt sich mehr jetzt nicht so direkt.

Auch eine App löst halt nicht automatisch alle Probleme, vor allem wenn vom Hersteller schlampig gearbeitet wird. Drucken tut er aber gut. Und das ist in diesem Falle wirklich die Hauptsache.

Von Warntagen und Präsidenten

Es war mal wieder Bundeswarntag mit dem ersten vollständigen Probelauf von DE-Alert, der deutschen Implementierung des EU-Standards EU-Alert, der auf SMS-CB basiert. Also das, was seit mehr als 20 Jahren in USA und Japan am Start ist, und in einigen EU-Ländern wie den Niederlanden gerade 10-jähriges Jubiläum feiert.

Der Cell Broadcast hat hier vor Ort gut funktioniert, alle angeschalteten Mobiltelefone haben gewarnt. Anderswo war das wohl nicht so erfolgreich, aber bei einem Probelauf kann im Gegensatz zum Ernstfall ja auch der Fehlschlag als Erfolg gewertet werden. Die Berichte zeigen ein uneinheitliches Muster des Nichtfunktionierens, scheinbar zufällig verteilt über alle Smartphone-Modelle und Betriebssysteme und Netzbetreiber.

An einer Stelle berichtete jemand, dass bei seinem Xiaomi-Smartphone die Meldung mit „MESSAGE FROM THE PRESIDENT“ betitelt war. Für mein nerdiges Ich ist das wie ein großes Schild „Bitte hier graben“. Und ich habe gegraben. Ging sogar recht schnell.

Ergebnis: Die für SMS-CB und EU-Alert relevante EU-Norm ist ETSI TS 102 900. Laut Tabelle 1 in Abschnitt 5.2.1 gibt es die höchste Prio von Warnmeldungen mit der Bezeichnung „EU-Alert Level 1“, die identisch ist mit dem Level „Presidential Alert“ in CMAS (Commercial Mobile Alert System), dem US-Standard, in dem deren PWS (Public Warning System) auf SMS-CB-Basis spezifiziert ist.

Passiert also vermutlich bei älteren Android- und iOS-Versionen, die halt nur den US-Standard aus grauer Vorzeit kennen und nicht den EU-Neuaufguss davon von 2019. Wobei einige EU-Länder wie oben angesprochen auch schon seit 10 Jahren das implementiert haben, also doch eher „schlampig implementierte Software oder Übersetzung“.

Wichtiges Detail am Rande: diese höchste Dringlichkeit ist von der „Opt-Out“-Möglichkeit durch den Benutzer ausgenommen. Denn wer würde schon seinen Präsidenten ignorieren wollen. Gut, damals konnte sich vermutlich niemand Frank-Walter Steinmeier im höchsten Amt vorstellen.

Gängige Passwörter

Eine nicht uninteressante Auswertung der am häufigsten benutzten (und damit höchstwahrscheinlich eher unsicheren) Passwörter ist mir heute über den Weg gelaufen. Nachfolgend einige tiefschürfende Erkenntnisse daraus, nicht nur Passwörter betreffend.

In Deutschland auf Platz 58: „sonnenschein“. Benötigte Zeit zum Passwort-Knacken laut dieser Liste: „3 Jahren“. Zeit, bis der einfache Plural deutscher Wörter korrekt auf originär englischsprachigen Webseiten angekommen ist: voraussichtlich mehrere Jahrzehnte. Zeit, bis in allen Länder-Auswahllisten „Deutschland“ alphabetisch nicht bei „G“ einsortiert wird: unendlich.

OpenJDK Overflow

Früher war die Welt noch einfach. Wenn man Java wollte (und ich rede jetzt nur mal von Java SE, sonst gibt das gleich wieder eine hundertseitige Abhandlung), ging man zu java.sun.com (oder gar zu java.de), hat JDK oder JRE seiner Wahl runtergeladen, und gut war. Klar, eher nicht das JRE, weil Sun irgendwann mal anfing, irgendwelche Ad-Ware damit zu bundeln, und weil es immer Installer-gebunden war und nicht als schnödes nacktes ZIP zur Verfügung stand.

Heute, im Zeitalter von OpenJDK auf der einen Seite und Oracles wöchentlich wechselnden Lizenzbedingen auf der anderen Seite schaut man sich natürlich nach einem passenden „Stamm-Provider“ eines OpenJDK-Pakets an. AdoptOpenJDK war früher mal meine erste Wahl – Auswahl zwischen HotSpot und OpenJ9, sowohl JRE als auch JDK, viele Plattformen unterstützt, sowohl x86 als auch x64. Inzwischen ist das zu „Eclipse Temurin“ von „Adoptium“ gemorphed, die Auswahl zwischen HotSpot und OpenJ9 scheint es nicht mehr zu geben, aber dafür gibt es bei IBM (wider besseren Wissens setze ich jetzt mal einen Link, wohl wissend, dass der in wenigen Monaten auf Nimmerwiedersehen einer Restrukturierung der IBM-Webpräsenz zum Opfer fällt) ein OpenJDK namens „IBM Semeru“, in den Geschmacksrichtungen „Certified Edition“ oder „Open Edition“, für den typischen IBM-Bauchladen (System/390, AIX) aber auch für Windows/Linux/MacOS als OpenJDK-OpenJ9-Bundle. Sinn? Übersichtlichkeit? Keine Ahnung. Derweil notiere ich: für die Top-IBM-Plattformen S/390 und AIX gibt es als neueste Version Java 11. Auf IBM-Plattformen meint „long term“ eben meistens die lange Zeit, bis aktuelle Versionen zur Verfügung stehen. Meine letzte gute Erfahrung mit IBM JDKs war mit Java 1.3, als auf einem linux-basierten ThinClient mit fast nacktem XServer das IBM-Java deutlich besser mit TrueType-Fonts umgehen konnte als die Sun-Konkurrenz. Lange her. Ansonsten zeichnete sich die IBM-Variante oftmals durch höheren Speicherverbrauch aus (ich erinnere mich an die Class-Sharing-Lösung in JDK 1.5, die zwar relativ gesehen pro zusätzlicher JVM-Instanz eine gute Menge Speicher sparte, aber absolut gesehen gegenüber der Sun-Lösung leider deutlich mehr verbrauchte) und dazu kamen noch abstruse Bugs im JIT-Bereich sowie irgendein dubioses Encoding-Problem im XML-Bereich, das mir den Schlaf raubte.

Ich will jetzt nicht alle OpenJDK-Distributionen aufzählen, die Menge ist inzwischen unüberschaubar, Anbieter kommen und gehen, zeichnen sich durch unvollständige Unterstützung diverser Plattformen aus, haben undurchschaubare Eigeninteressen…unterm Strich habe ich mich jetzt auf Bell Software eingeschossen, die bieten eine OpenJDK-Distribution namens „Liberica JDK“ zum Download an. Besonderheit aus meiner Sicht: alle Versionen bis zurück zu Java 8, alle für mich relevante Plattformen, sowohl JRE als auch JDK, sowohl x86 als auch x64, und als besonderen Service auch noch „Full JRE“ und „Full JDK“, ein Bundle bestehend aus Java SE und OpenJFX. Und dazu noch pre-built docker images, z.B. in einer Minimalversion mit Alpine Linux mit musl-Standard-Lib. Seit Längerem verwende ich praktisch nur noch die diversen Bell-Distributionen, alles funktioniert prächtig – ich habe aufgehört, nach besseren Alternativen zu suchen.

Eine interessante, aus meiner Sicht aber noch eher experimentelle Variante: OpenJDK in der GraalVM Community Edition. Mit dem Graal-JIT, der je nach Workload durchaus Vorteile bringen kann. Derzeit downloadbar als Version 22.1 in den Geschmacksrichtungen Java 11 und Java 17. Quasi der Außenseitertipp unter den OpenJDK-Distributionen.

Zum Schluss noch ein typisches „wann ist mir denn das entgangen“ beim Abprüfen, ob noch alle Anbieter an die ich mich erinnere im Rennen sind: was ist eigentlich JITServer? Das habe ich gerade zum ersten Mal gehört bzw. gelesen. Es gibt aber schon seriöse Infos zu diesem Thema von Januar 2020, mit Andeutungen eines existierenden Prototyps namens „JIT-as-a-Service“ schon Mitte 2019. Auch so eine IBM-OpenJ9-voll-das-fancy-Cloud-Zeugs-Geschichte. Dieses Java-Ökosystem kann einen in den Wahnsinn treiben, wenn man da auf dem Laufenden sein und bleiben will. Nächstes Mal zu diesem Thema: warum fängt man mit „Project Leyden“ an, wenn man schon Graal hat? Die Antwort wird wohl eine ähnliche sein wie bei „warum Java Modules, wenn es schon OSGi gibt“. Es kann was Gutes draus werden, aber man weiß es noch nicht, und es ist ein Haufen Arbeit auf einer ganz langen Zeitschiene. Und entlang dieser Zeitschiene liegen jede Menge Leichen aus früheren gut gemeinten Ansätzen.

Fortgeschrittene 2-Faktor-Authentifizierung

Neulich im Dunstkreis von Zahlungsdienstleistungen. Ich wollte bei einem Vertrag meine Mobilfunknummer ändern. Übers Webinterface eingeloggt und die Nummer geändert. Ein Popup informiert mich darüber, dass das leider gar nicht so einfach möglich sei, denn die Mobilfunknummer werde mittels SMS-TAN als zweiter Faktor für Authentifizierung genutzt. Ich hätte die Wahl zwischen Brief-TAN – dann müsse ich aber beim Service-Center anrufen und dies veranlassen – oder könnte die App nutzen, dort die Mobilfunknummer ändern, und bekäme dann eine SMS-TAN.

So weit, so plausibel – natürlich ging ich davon aus, dass ich dazu dann zwei Handys (oder in Zeiten von Dual-SIM: zwei Rufnummern) benötige, einmal die alte hinterlegte Nummer und einmal die neu zu hinterlegende Nummer. Die Frage „warum kann ich nicht einfach mit der alten Nummer und einer SMS-TAN die neue Nummer authentifizieren“ stellte ich mir, beantwortete sie mir aber mit dem naheliegenden „die Software kann das vermutlich nicht, weil einer vergessen hat, diesen Fall zu spezifizieren“.

Also die App auf dem neuen Handy installiert, über die App eingeloggt (gleiche Credentials wie das Webinterface), Mobilfunknummer geändert, und die SMS-TAN auf die neue (!) Mobilfunknummer bekommen. Also auf dasselbe Gerät, auf der die App läuft.

Freunde: so funktioniert das nicht mit der 2-Faktor-Authentifizierung. Das ist einfach nur Bullshit und Pseudo-Security.