Connect with us

Entwicklung & Code

Konsistenz ist eine fachliche Entscheidung


close notice

This article is also available in
English.

It was translated with technical assistance and editorially reviewed before publication.

Im Deutschen hat sich eine Übersetzung eingebürgert, die das Denken über verteilte Systeme in eine falsche Richtung lenkt. „Eventual Consistency“ wird häufig als „eventuell konsistent“ wiedergegeben. Eventuell, also möglicherweise. Eine Datenbank, die möglicherweise konsistent ist, klingt nach einem System, dem man besser nicht vertraut. Kein Wunder, dass viele Entwicklerinnen und Entwickler reflexartig nach stärkeren Garantien greifen, sobald der Begriff fällt.

Weiterlesen nach der Anzeige


the next big thing – Golo Roden

the next big thing – Golo Roden

Golo Roden ist Gründer und CTO von the native web GmbH. Er beschäftigt sich mit der Konzeption und Entwicklung von Web- und Cloud-Anwendungen sowie -APIs, mit einem Schwerpunkt auf Event-getriebenen und Service-basierten verteilten Architekturen. Sein Leitsatz lautet, dass Softwareentwicklung kein Selbstzweck ist, sondern immer einer zugrundeliegenden Fachlichkeit folgen muss.

Die englische Bedeutung von „eventual“ ist jedoch eine andere. Sie meint „letztendlich“ oder „am Ende“. Eventual Consistency bedeutet also nicht, dass Konsistenz vielleicht eintritt. Sie bedeutet, dass Konsistenz verlässlich eintritt, nur nicht sofort. Die Frage ist nicht, ob, sondern wann. Und diese Frage ist keine technische, sondern eine fachliche. Das war sie schon immer.

Ein besseres mentales Modell als „möglicherweise inkonsistent“ ist das der veralteten Daten. In jedem Moment kann irgendein Teil eines Systems auf Daten zugreifen, die den allerletzten Stand nicht widerspiegeln. Die Daten sind nicht falsch. Sie sind nur nicht aktuell. Sie waren vor einem Moment korrekt. Sie werden in einem Moment wieder korrekt sein. Gerade eben sind sie veraltet. Jedes System hat irgendwo veraltete Daten. Die Frage ist nicht, ob Daten veraltet sein können, sondern wie veraltet akzeptabel ist. Millisekunden? Sekunden? Minuten? Stunden? Die Antwort hängt vom Anwendungsfall ab, und sie lautet selten „niemals“.

Es gibt noch etwas, das sich in der Softwareentwicklung hartnäckig hält: Die Behauptung, eine relationale Datenbank sei immer konsistent. Transaktionen garantieren es. ACID garantiert es. Nach dem Commit sind die Daten da, und jeder sieht sie. Das stimmt allerdings nur innerhalb einer einzelnen Datenbankinstanz, für eine einzelne Abfrage, in einem einzelnen Moment. So funktionieren reale Systeme nicht.

Wer Read-Replicas einsetzt, akzeptiert bereits, dass Leseoperationen veraltete Daten liefern können. Wer einen Cache verwendet, akzeptiert, dass die gecachten Daten zum Zeitpunkt des Lesens nicht mehr aktuell sein müssen. Wer eine mobile App betreibt, akzeptiert, dass die Anzeige auf dem Gerät den Stand der letzten Synchronisation zeigt, nicht den aktuellen. Und wer HTML serverseitig rendert, akzeptiert, dass die Seite zum Zeitpunkt der Auslieferung bereits veraltet sein kann.

In dem Moment, in dem Daten die Datenbank verlassen, beginnen sie zu altern. Bis sie den Bildschirm einer Nutzerin oder eines Nutzers erreichen, sind sie bereits ein Schnappschuss der Vergangenheit. Die Kundin sieht „Bestellung bestätigt“, aber das Lagersystem hat den Auftrag noch nicht verarbeitet. Der Kunde sieht „3 Stück auf Lager“, aber jemand anders hat gerade zwei davon in den Warenkorb gelegt. Das ist kein Fehler. Das ist die Funktionsweise verteilter Systeme. Und jedes System mit einer Bedienoberfläche ist ein verteiltes System, denn das Endgerät ist ein eigener Knoten, das Netzwerk ist unzuverlässig, und zwischen Anfrage und Antwort vergeht Zeit.

Weiterlesen nach der Anzeige

Ich begegne in meiner Beratungsarbeit regelmäßig Teams, die überzeugt sind, ihre Systeme seien stark konsistent. Bei genauerem Hinsehen zeigt sich fast immer, dass die Konsistenz an der Datenbankgrenze endet. Dahinter beginnt eine Welt aus Caches, Replikas, Message-Queues und gerenderten Oberflächen, in der Daten bereits veraltet sind, bevor sie ankommen. Das System ist längst eventually consistent. Es gibt nur niemanden, der das ausspricht.

Eventual Consistency ist kein Phänomen, das mit verteilten Softwaresystemen entstanden ist. Sie ist ein Grundproblem der physischen Welt, und Unternehmen haben seit Jahrhunderten Wege gefunden, damit umzugehen.

Man stelle sich eine Firma mit zwei Vertriebsbüros in verschiedenen Städten vor, zu einer Zeit, als das Telefon das schnellste Kommunikationsmittel war. Beide Büros verkaufen aus demselben Lagerbestand. Eine Kundin in München möchte die letzte Einheit eines Produkts kaufen. Ein Kunde in Hamburg möchte dieselbe Einheit kaufen. Keiner der beiden Vertriebsmitarbeiter weiß, was der andere gerade macht.

Wie haben Unternehmen dieses Problem gelöst? Nicht durch perfekte Echtzeitsynchronisation. Sie haben akzeptiert, dass Konflikte auftreten werden, und Prozesse entwickelt, um sie zu behandeln. Sie haben überbucht und sich entschuldigt. Sie haben Sicherheitsbestände geführt. Sie haben im Lager angerufen, bevor sie eine Lieferung zugesagt haben. Sie haben enttäuschte Kundinnen und Kunden kompensiert. Sie haben Risiken gemanagt, nicht Konsistenz.

Das gleiche Produkt, das gleiche Problem, nur mit Stift und Papier statt mit Datenbanken. Keine Technologie der Welt kann diese grundlegende Herausforderung eliminieren: zwei Personen, zwei Orte, eine Ressource, unvollständige Information. Die Naturgesetze garantieren, dass Information Zeit braucht, um sich auszubreiten. Perfekte Synchronisation ist nicht nur schwierig. Sie ist unmöglich.

Das Interessante daran ist, dass diese analogen Prozesse oft erstaunlich gut funktioniert haben. Nicht weil sie Inkonsistenzen verhindert hätten, sondern weil sie Strategien für den Umgang mit ihnen entwickelt hatten. Die Buchhaltung glich am Ende des Tages die Bestände ab. Der Vertrieb rief im Zweifelsfall im Lager an. Und wenn doch einmal zwei Kunden dasselbe Produkt zugesagt bekamen, gab es ein Gespräch, eine Entschuldigung und eine Lösung. Der Geschäftsprozess war auf Konflikte vorbereitet, weil niemand auf die Idee gekommen wäre, sie für unmöglich zu erklären.

Wenn ich mit Teams über Eventual Consistency spreche, hilft dieser historische Blick oft mehr als jedes Architekturdiagramm. Er verschiebt das Problem aus der technischen Ecke in die geschäftliche, wo es hingehört. Die Frage lautet nicht: Wie verhindern wir Inkonsistenz? Sie lautet: Wie gehen wir mit ihr um?

Wenn Entwicklerinnen und Entwickler über Eventual Consistency diskutieren, stellen sie häufig die falsche Frage. Sie fragen: Ist Eventual Consistency hier akzeptabel? Das rahmt Konsistenz als binäre Eigenschaft, als hätte man sie oder hätte sie nicht.

Die richtigen Fragen sind anders: Wie häufig tritt ein Konflikt tatsächlich auf? Wenn zwei Nutzerinnen oder Nutzer gleichzeitig den letzten Artikel kaufen wollen: Passiert das einmal am Tag? Einmal im Monat? Einmal im Jahr? Die Häufigkeit entscheidet darüber, ob ein Konflikt ein reales Problem ist oder eine theoretische Sorge. Was kostet ein Konflikt? Ist die Konsequenz eine enttäuschte Kundin? Eine Rückerstattung? Ein manueller Eingriff? Ein rechtliches Problem? Die Kosten bestimmen, wie viel Aufwand die Vermeidung rechtfertigt. Und was kostet die Vermeidung? Stärkere Konsistenzgarantien sind nicht kostenlos. Sie erfordern Koordination, also Latenz. Sie erfordern Sperren, also geringeren Durchsatz. Sie erfordern Infrastruktur, also Geld.

Das sind betriebswirtschaftliche Fragen, keine Ingenieursfragen. Das Entwicklungsteam kann erklären, was technisch möglich ist und was jede Option kostet. Aber die Entscheidung über das akzeptable Risiko gehört ins Business. Ein Bezahlsystem und ein Social-Media-Feed haben unterschiedliche Toleranzen. Eine Patientenakte und ein Warenkorb haben unterschiedliche Anforderungen. Der Kontext bestimmt die Antwort.

Genau deshalb gehören Diskussionen über Eventual Consistency nicht ausschließlich in Technik-Meetings. Das Team mag starke Meinungen über technische Korrektheit haben, weiß aber vielleicht nicht, dass die Fachabteilung eine Verzögerung von einer Sekunde bereitwillig akzeptieren würde, wenn dafür die Infrastrukturkosten sinken. Oder es weiß nicht, dass ein bestimmter Anwendungsfall regulatorische Anforderungen hat, die stärkere Garantien verlangen. Das Gespräch braucht beide Perspektiven.

Alltagsbeispiele zeigen, wie selbstverständlich Eventual Consistency bereits ist. Paketverfolgung zeigt einen Status, der vor Stunden erfasst wurde. Das Paket wurde gescannt, als es das Sortierzentrum verlassen hat. Seitdem ist es unterwegs, möglicherweise bereits zugestellt. Die angezeigte Information ist veraltet, und das stört niemanden, weil ein ungefährer Überblick über den Fortschritt ausreicht. Bestandsanzeigen in Online-Shops sind ein ähnlicher Fall. „Nur noch 3 auf Lager“ war korrekt, als die Seite gerendert wurde. Inzwischen hat vielleicht jemand eines gekauft. Vielleicht hat jemand eines in den Warenkorb gelegt, ohne zu bestellen. Die Zahl ist ein Hinweis, keine Garantie. Und das ist akzeptabel, weil der Checkout-Prozess den Grenzfall abfängt, in dem der Artikel tatsächlich vergriffen ist.

Besonders aufschlussreich ist das Beispiel der Fluggesellschaften. Airlines überbuchen bewusst, weil sie wissen, dass ein Teil der Passagiere nicht erscheinen wird. Das Buchungssystem akzeptiert mehr Reservierungen, als Sitzplätze vorhanden sind. Wenn doch alle erscheinen, wird das Problem am Gate gelöst: Kompensation, Umbuchung, Upgrade. Das System ist darauf ausgelegt, Konflikte zu akzeptieren und sie nachträglich zu lösen. Das ist kein Versagen der Konsistenz. Es ist eine Geschäftsstrategie, die jedes Jahr Millionen von Flügen mit freien Sitzen füllt, die sonst leer geblieben wären.

All diese Systeme funktionieren. Ihre Nutzerinnen und Nutzer beschweren sich nicht, weil das Konsistenzfenster kurz genug ist oder weil der Geschäftsprozess die Ausnahmen elegant abfängt. Das Ziel war nie perfekte Konsistenz. Das Ziel war ausreichende Konsistenz.

Unter den vielen Beispielen, die ich in Gesprächen über Eventual Consistency verwende, ist eines besonders aufschlussreich, weil es die Perspektive komplett umdreht.

Geldautomaten sind normalerweise online und mit den Systemen der Bank in Echtzeit verbunden. Bei einer Abhebung prüft der Automat den Kontostand, verifiziert die Deckung und gibt das Geld aus. Einfach und konsistent. Doch was passiert, wenn die Netzwerkverbindung ausfällt und der Automat offline geht?

Die meisten Entwicklerinnen und Entwickler, denen ich diese Frage stelle, antworten: „Der Automat muss den Betrieb einstellen. Keine Verbindung bedeutet keine Kontostandsprüfung. Keine Prüfung bedeutet mögliche Überziehungen. Also abschalten, bis die Verbindung wiederhergestellt ist.“ Das ist die naheliegende, die sichere, die technisch korrekte Antwort. Es ist aber auch die falsche.

Man stelle sich einen prominenten Millionär vor, der an einem Geldautomaten steht und 50 Euro abheben möchte, nur um zu erfahren, dass der Automat außer Betrieb ist. Die Schlagzeile am nächsten Tag: „Bank lässt Topkunden wegen Netzwerkproblem im Regen stehen.“ Das ist keine Schlagzeile, die eine Bank gebrauchen kann. Der Reputationsschaden übersteigt jedes Überziehungsrisiko bei einer Kleinbetragabhebung um ein Vielfaches.

Was machen Banken also tatsächlich? Der Automat arbeitet weiter, auch offline. Aber mit intelligentem Risikomanagement. Die meisten Ausfälle sind kurz: Die Verbindung bricht für wenige Minuten ab und stellt sich dann von selbst wieder her. Bis jemand etwas bemerkt, hat sich das Problem bereits gelöst. Die meisten Menschen heben zudem nur Geld ab, wenn sie wissen, dass sie es haben. Niemand möchte die Peinlichkeit erleben, an einem Geldautomaten mit einer Schlange hinter sich abgelehnt zu werden. Diese Selbstselektion reduziert das Überziehungsrisiko erheblich. Und für den Fall, dass die Verbindung länger ausfällt, begrenzt die Bank den maximalen Abhebungsbetrag im Offline-Modus.

Doch der eigentlich interessante Punkt liegt woanders. Wenn jemand im Offline-Modus sein Konto tatsächlich überzieht, hat die Bank zwei Möglichkeiten, die Situation zu rahmen. Erste Variante: „Kunde nutzte Systemschwachstelle während Netzwerkausfall.“ Das klingt nach einem Sicherheitsvorfall. Zweite Variante: „Bank zeigte Flexibilität und half Kunden trotz technischer Schwierigkeiten.“ Das klingt nach exzellentem Kundenservice. Und nebenbei: Die Bank berechnet Überziehungszinsen. Der Kunde, der 50 Euro abgehoben hat, die er nicht hatte, zahlt sie zurück, mit Aufschlag. Die Bank hat eine technische Einschränkung in eine Einnahmequelle verwandelt.

Das ist es, was fachliches Denken über Konsistenz bedeutet. Die Entwicklerin sieht ein Konsistenzproblem und will es um jeden Preis verhindern. Die Geschäftsseite sieht eine Risiko-Ertrags-Rechnung und findet eine Lösung, die besser ist als sowohl „immer konsistent“ als auch „immer verfügbar“. Die beste Antwort lag nicht im Engineering-Meeting. Sie lag im Business-Meeting.

Die Gefahr liegt nicht in Eventual Consistency. Sie liegt darin, so zu tun, als gäbe es sie nicht.

Wer sein System für stark konsistent hält, entwirft keine Kompensationslogik. Wer keine Konflikte erwartet, baut keine Konfliktbehandlung. Wer keine veralteten Daten einplant, gestaltet keine Benutzererfahrung, die damit umgehen kann. Und wenn dann die Race Condition doch eintritt, wenn der Cache im falschen Moment veraltete Daten liefert, wenn die Replica-Verzögerung zu einer sichtbaren Inkonsistenz führt, gibt es keinen Plan. Das System versagt auf eine Weise, die niemand vorhergesehen hat, weil sich niemand die Mühe gemacht hat, sie vorherzusehen.

Wer Eventual Consistency dagegen anerkennt, entwirft dafür. Man denkt darüber nach, was passiert, wenn Daten veraltet sind. Man baut idempotente Operationen, die gefahrlos wiederholt werden können. Man schafft Kompensationsmechanismen für den Fall, dass etwas schiefgeht. Man kommuniziert Unsicherheit gegenüber Nutzerinnen und Nutzern, statt falsche Sicherheit zu vermitteln.

In der Praxis bedeutet das konkrete Entwurfsentscheidungen. Statt „Bestellung erfolgreich“ anzuzeigen, wenn die Bestellung lediglich angenommen wurde, zeigt man „Bestellung wird verarbeitet“ und aktualisiert den Status, sobald die Verarbeitung abgeschlossen ist. Statt eine Schaltfläche nach dem Klick zu deaktivieren und auf Konsistenz zu hoffen, gestaltet man die Operation idempotent, sodass ein doppelter Klick keinen Schaden anrichtet. Statt einen Fehler zu zeigen, wenn ein Artikel zwischen Warenkorb und Checkout vergriffen ist, bietet man eine Alternative an. Das sind keine technischen Notlösungen. Das sind durchdachte Benutzererlebnisse, die auf einer ehrlichen Einschätzung der Systemrealität basieren.

Die deutsche Fehlübersetzung ist dabei versehentlich tiefgründig. „Eventuell konsistent“ klingt bedrohlich, weil Unsicherheit bedrohlich klingt. Aber Unsicherheit ist die Realität verteilter Systeme. Die Wahl besteht nicht zwischen Sicherheit und Unsicherheit. Sie besteht zwischen eingestandener und versteckter Unsicherheit. Das eine führt zu robusten Systemen. Das andere führt zu Überraschungen.

Eventual Consistency ist keine Einschränkung, die es zu überwinden gilt. Sie ist eine Realität, für die es zu entwerfen gilt. Ihre Systeme sind bereits eventually consistent. Die Frage ist, ob Sie für diese Realität entwerfen oder so tun, als existiere sie nicht. Und diese Frage ist keine, die ein Engineering-Team allein beantworten sollte. Sie ist eine fachliche Entscheidung. Das war sie schon immer.


(rme)



Source link

Entwicklung & Code

Neu in .NET 10.0 [19]: Umwandeln von File-based Apps in C#-Projekte


close notice

This article is also available in
English.

It was translated with technical assistance and editorially reviewed before publication.

Das direkte Übersetzen und Starten von C#-Dateien nennt Microsoft File-based Apps. Wenn die Anforderungen höher werden, sind File-based Apps keine Sackgasse.

Weiterlesen nach der Anzeige


Der Dotnet-Doktor – Holger Schwichtenberg

Der Dotnet-Doktor – Holger Schwichtenberg

Dr. Holger Schwichtenberg ist technischer Leiter des Expertennetzwerks www.IT-Visions.de, das mit 53 renommierten Experten zahlreiche mittlere und große Unternehmen durch Beratungen und Schulungen sowie bei der Softwareentwicklung unterstützt. Durch seine Auftritte auf zahlreichen nationalen und internationalen Fachkonferenzen sowie mehr als 90 Fachbücher und mehr als 1500 Fachartikel gehört Holger Schwichtenberg zu den bekanntesten Experten für .NET und Webtechniken in Deutschland.

Entwicklerinnen und Entwickler können per Kommandozeilenbefehl aus einer File-based App ein C#-Projekt mit .csproj-Projektdatei machen:

dotnet project convert .\Dateiname.cs


Screenshot

Screenshot

Umwandeln einer eigenständigen C#-Skriptdatei in ein C#-Projekt (Abb. 1)

Dabei wird ein neuer Ordner angelegt und eine Projektdatei angelegt, die die Präprozessor-Informationen aus der C#-Datei übernimmt.

Sollten die Dateien Dateiname.settings.json und Dateiname.run.json vorhanden sein, werden sie beim Konvertieren allerdings ignoriert.

Weiterlesen nach der Anzeige


Screenshot

Screenshot

Aus der einzelnen C#-Datei entsteht ein C#-Projekt (Abb. 2).


(rme)



Source link

Weiterlesen

Entwicklung & Code

Android 17 Beta 4: Letzte Testversion vor dem finalen Release


close notice

This article is also available in
English.

It was translated with technical assistance and editorially reviewed before publication.

Etwa drei Wochen nach der Android 17 Beta 3 schiebt Google die Beta 4 heraus. Es ist laut der Entwickler die letzte geplante Betaversion, in den nächsten Wochen könnten noch Patches und Bugfixes erscheinen. Die neue Beta enthält neben wenigen Neuerungen eine lange Liste an Fehlerbehebungen – und das Easter-Egg.

Weiterlesen nach der Anzeige

Nach der Beta 3, die allerhand neue nutzergerichtete Funktionen mit sich brachte, wie etwa die App-Bubbles, sind die Neuerungen in der Beta 4 überschaubar. Lediglich die schon in der April-Version von Android Canary gesichtete neue Nachricht nach dem Entfernen sämtlicher Benachrichtigungen: „Du bist auf dem aktuellen Stand“, begleitet von einem Pokal, ist neu. Die neue Anzeige orientiert sich dabei an Wear OS 6 etwa auf der Pixel Watch, sodass sie über das Ökosystem hinweg einheitlicher anmutet.


Screenshots: Info zu abgearbeiteten Benarchrichtigungn in Android 17 Beta 4 und Android 16 QPR3

Screenshots: Info zu abgearbeiteten Benarchrichtigungn in Android 17 Beta 4 und Android 16 QPR3

Kleine Änderung: Statt bisher „Keine Benachrichtigungen“ heißt es in Android 17 künftig „Du bist auf dem aktuellen Stand“.

(Bild: Andreas Floemer / heise medien)

Zudem hat die letzte Beta das traditionelle Android-Easter-Egg an Bord: Begibt man sich in die Einstellungen „Über das Smartphone“, tippt auf die Android-Versionsnummer und anschließend dreimal schnell erneut auf die Android-Version, erscheint das Easter-Egg. Hier füllt man mit dem Finger den Kreis vollständig und hält das dann erscheinende Android-17-Logo gedrückt. Nun erscheint das seit einigen Android-Generationen integrierte kleine Space-Game, in dem man ein kleines Raumschiff durchs All manövriert.


Screencast Android 17 Easter Egg

Screencast Android 17 Easter Egg

Das Easter-Egg in der neuen Android-Version.

(Bild: Andreas Floemer / heise medien)

Für Entwickler wichtig: Google führt mit Android 17 Beta 4 Speicherbegrenzungen für Apps ein, „die sich nach dem gesamten RAM-Speicher des Geräts richten, um eine stabilere und deterministische Umgebung für Ihre Anwendungen und Android-Nutzer zu schaffen“, schreibt Google. In der neuen Android-Version seien die Grenzwerte konservativ festgelegt, um Systembasiswerte zu etablieren. „Damit sollen extreme Speicherlecks und andere Ausreißer bekämpft werden, bevor sie systemweite Instabilität auslösen, die zu Rucklern in der Bedienoberfläche, erhöhtem Akkuverbrauch und dem Beenden von Apps führt“, erklärt der Konzern weiter.

Weiterlesen nach der Anzeige

Google empfiehlt Entwicklern, bewährte Verfahren für den Speicherumgang zu befolgen und Speicherlecks zu beheben. Um Entwicklern bei der Suche nach Speicherlecks zu helfen, bietet Android Studio Panda eine „LeakCanary-Integration“ direkt im Android Studio Profiler als eigene Aufgabe an.


Screenshot LeakCanary-Funktion in Android Studio

Screenshot LeakCanary-Funktion in Android Studio

Google führt mit Android 17 „App memory limits“ ein.

(Bild: Google)

Überdies unterstützt der Android-Keystore nun den nach NIST-Standard entwickelten ML-DSA (Module-Lattice-Based Digital Signature Algorithm). Auf unterstützten Geräten können Entwickler ML-DSA-Schlüssel generieren und diese zur Erstellung quantensicherer Signaturen nutzen. Den Schutz vor Angriffen durch Quantencomputer für Android 17 hatte Google Ende März angekündigt.

Behobene Fehler der Beta von Android 17 hat Google in einem umfangreichen Reddit-Beitrag dokumentiert. Unter anderem fixt Google ein Problem, das dazu führte, dass die Ladegeschwindigkeit von Geräten deutlich abnahm, sobald die 80-Prozent-Marke der Akkuladung erreicht wurde. Dieser Bug steckt auch in Android 16 QPR3.

Lesen Sie auch

Wagemutige und Entwickler können die Beta auf kompatiblen Pixel-Geräten installieren. Zu diesen gehören alle Modelle ab dem Pixel 6 und neuer als auch das Pixel Tablet sowie Googles Foldables. Um die Beta zu erhalten, müssen Nutzerinnen und Nutzer ihr Gerät im Android-Betaprogramm registrieren, anschließend wird die Software als Over-the-Air-Update angeboten.

Weitere Neuerungen von Android 17 dürfte Google im Zuge der Entwicklerkonferenz I/O 2026 verraten, die am 19. und 20. Mai stattfindet. Als gesichert gilt, dass Google seinem mobilen Betriebssystem agentische Fähigkeiten verleihen wird, die Nutzern mehrstufige Aufgaben abnehmen sollen. Der Chef des Android-Ökosystems Sameer Samat sagte dazu: „Wir bewegen uns weg von einem Betriebssystem hin zu einem intelligenten System, einer Plattform, die Sie wirklich versteht und für Sie arbeitet.“ Die finale Version von Android 17, zunächst für Pixel-Geräte, wird im Juni erwartet.


(afl)



Source link

Weiterlesen

Entwicklung & Code

C-Libraries in Java nutzen 1: Grundlagen der Foreign Function & Memory API


close notice

This article is also available in
English.

It was translated with technical assistance and editorially reviewed before publication.

Javas Foreign Function & Memory API (FFM) dient dazu, auf Code in einer Shared Library beziehungsweise DLL zuzugreifen, der in einer Programmiersprache wie C oder Rust geschrieben ist. Allerdings muss der Code dazu einige Voraussetzungen erfüllen. Diese dreiteilige Artikelserie zeigt anhand einer in C geschriebenen Demo-Library, wie eine Java-Anwendung die Funktionen der Bibliothek aufruft, welche Vorbereitungen erforderlich sind und welche Regeln zu beachten sind. Der Sammelbegriff „Shared Library“ steht in den Artikeln gleichermaßen für eine Shared Library unter Unix wie für eine Windows-DLL.

Weiterlesen nach der Anzeige




Rudolf Ziegaus ist Software-Entwickler, Java-Trainer und Geschäftsführer der IO Software GmbH. Seine Lieblingsthemen sind PKi, Kryptographie und systemnahe Programmierung.

Der Ausgangspunkt der Arbeit mit FFM war meine Suche nach einem Weg, per Java auf ein Hardware-Sicherheitsmodul (HSM) zuzugreifen. Da aber noch kein physisches HSM vorhanden war, suchte ich nach einer softwaregestützten Umsetzung. Die Applikation SoftHSM2 lässt sich mit PKCS11 ansprechen, aber der Pkcs#11-Treiber von Sun ist veraltet. Da ich keine passende Open-Source-Anwendung gefunden habe, entwickelte ich selbst einen PKCS11-Wrapper für Java auf Basis der FFM-API.

Da das Projekt sehr umfangreich ist, steht für diese dreiteilige Artikelserie eine eigens entwickelte C-Library im Fokus, die dazu dient, die Konzepte der FFM-API zu erläutern. Die kleine Demo-Library ist auf Windows und Linux getestet.

In Java gab es vor dem FFM mit dem Java Native Interface (JNI) seit Langem einen Weg, um auf in C geschriebenen Code zuzugreifen. Das JNI war allerdings sehr kompliziert und fehlerbehaftet.

Daher begannen im JDK 14 (Java Development Kit) die Arbeiten an einer neuen Schnittstelle: Foreign Function & Memory API. Die Java-Community hat sie über einige JDK-Versionen und JEPs hinweg verfeinert und schließlich in JDK 22 finalisiert. Allerdings erschien sie im JDK 24 nochmals in veränderter Form. Wegen einiger Breaking Changes ist die API aus Java 24 nicht zu der in Java 22 kompatibel. Dieser Artikel beschreibt die aktuelle Version aus dem JDK 24.

Weiterlesen nach der Anzeige

Um die FFM-API zu nutzen, gelten folgende Voraussetzungen:

  • Ein JDK ab Version 24 muss installiert sein.
  • Das Betriebssystem muss Windows oder Linux auf x64-Basis sein. Die Demo-App sollte auch unter macOS funktionieren, wozu ich aber keine Tests durchgeführt habe.
  • Eine Windows-DLL oder eine Shared Library für Linux in 64-Bit-Version muss vorhanden sein.
  • Die DLL beziehungsweise Shared Library muss in einer Sprache geschrieben sein, die die C-ABI (Application Binary Interface) unterstützt. Dazu gehören neben C und C++ (mit passend deklarierten Funktionen) auch weitere Sprachen wie Rust und Go.
  • Beim Zugriff auf die Shared Library muss man den Native Access erlauben. Das ist aktuell noch ohne Einschränkungen möglich, was sich in einer späteren Java-Version ändern könnte.

Der Ausgangspunkt für FFM ist immer eine Header-Datei, die in C die Funktionen und gegebenenfalls Typen der Shared Library beschreibt.

Die in C entwickelte Beispiel-Library enthält nur wenige Funktionen und einen Datentyp:


#ifdef _WIN32
  #define EXPORT __declspec(dllexport)
#else
  #define EXPORT
#endif

typedef struct 
{
  double x;
  double y;
} Point;


#define VERSION 1

EXPORT void   initialize(void);
EXPORT int    getVersion(void);
EXPORT void   getVersion2(int *version);
EXPORT long   add(long a, long b);
EXPORT double calcAverage(int *lvalues, int size);
EXPORT double distance(Point *p1, Point *p2);


Es gibt nur eine einzige Typdefinition (Point) und wenige Funktionen. Die Direktive #ifdef im Header-File sorgt dafür, dass sich der Code sowohl unter Linux als auch unter Windows kompilieren lässt.

Das Tool jextract hilft beim Zugriff auf native Funktionen. Ausgangspunkt ist auch hier wieder eine Header-Datei, um die notwendigen Zugriffsmethoden für die Funktionen aus der Shared Library zu erzeugen.

jextract kämpft jedoch mit diversen Schwierigkeiten. Zunächst ist es nicht für jedes JDK verfügbar – nach JDK 22 erst wieder für JDK 25. Für die Demo-Library zum Artikel hat die Version aus JDK 22 zwei Klassen generiert: Point für den Zugriff auf die Datenstruktur und DemoLib_h, um auf die Funktionen zuzugreifen. Die Klasse Point hat einen Umfang von etwa 170 schlecht leserlichen Codezeilen, und die Klasse DemoLib_h hat weitere 390 Zeilen Code, die ebenfalls schwer lesbar sind.

Bei komplexen Header-Files ist der Einsatz von jextract noch schwieriger. Beim Versuch, einen Wrapper für PKCS11 zu erzeugen, brach jextract im Zusammenspiel mit dem JDK 22 ab. Die Header-Datei pkcs11.h lädt zwei weitere Header-Dateien nach. Das führte zum Abbruch mit Fehlermeldungen, dass inkompatible Typ-Redefinitionen vorhanden seien.

jextract ist derzeit nur für kleine Projekte einsatzbereit – und auch das mit Einschränkungen. Aufgrund des schwer lesbaren Codes ist es keine Vorlage für eigenen Code. Daher ist der deutlich bessere Ansatz, den Code selbst zu entwickeln und das entsprechende Know-how aufzubauen, um den Code zu verstehen.



Source link

Weiterlesen

Beliebt