Horror Serialisierung

Serialisierung ist das die größte Schwachstelle in Java. Praktisch alle wichtigen Java-APIs und Frameworks verwenden Serialisierung. Wirksamer Schutz ist kaum möglich und vorhandene Alternativen lösen die fundamentalen Probleme nicht. Mit MicroStream gibt es jetzt eine neue Serialisierung für Java, die nicht nur mehr Sicherheit verspricht, sondern zudem fantastische Möglichkeiten bietet.

In objektorientierte Programmiersprachen wie Java arbeiten wir mit Objekten und komplexen Objektgraphen. Um Daten zwischen Java-Anwendungen austauschen zu können, werden diese über Netzwerk übertragen. Dazu müssen die Objekte in eine für die Übertragung geeignete Form umgewandelt werden, und zwar in einen binären Datenstrom (Byte-Stream). Dieser Umwandlungsprozess wird als Serialisierung bezeichnet. Umgekehrt wird das Empfangen des Byte-Stroms und anschließende Erzeugen eines Objekts als Deserialisierung bezeichnet.

Im Juni diesen Jahres hat sich Brian Goetz, Java Language Architekt bei Oracle, mit einem sehr ausführlichen Beitrag[1] zur Java-Serialisierung geäußert. Sinngemäß schreibt er: Es ist paradox, denn auf der einen Seite hat die Serialisierung viel zu dem großen Erfolg von Java beigetragen, insbesondere dem Erfolg von Java-EE. Auf der anderen Seite aber hat man bei der Serialisierung nahezu jeden Fehler gemacht, den man sich vorstellen kann, wodurch die Serialisierung sich wie ständiger Ballast auswirkt, die hohe Sicherheitsrisiken birgt, zu höheren Wartungskosten und letztendlich verlangsamten Entwicklungsfortschritt führt. Die Vielfalt der Sicherheitslücken und die Raffinnesse mit der diese ausgenutzt werden, ist erstaunlich. Gewöhnliche (Anwendungs-)Entwickler sind damit überfordert, denn selbst Sicherheitsexperten würden trotz intensiver Überprüfung vorhandene Schwachstellen übersehen. Es ist einfach viel zu schwierig, die Serialisierung ausreichend abzusichern, da diese größtenteils auf Low-Level-Ebene eingesetzt wird. Damit ist sie für Anwendungsentwickler völlig unsichtbar, die deshalb dem Irrglauben unterliegen, ihre Geschäftslogik wäre sicher, während die Hintertür weit offensteht und auch noch völlig unbewacht ist.

Das Konzept der Serialisierung selbst ist grundsätzlich nicht verkehrt, das große Problem ist jedoch, wie die Serialisierung damals in Java 1.1 umgesetzt wurde.

Auch Mark Reinhold, Chefarchitekt der Java-Plattform bei Oracle, wurde bereits wiederholt in Interviews sogar noch deutlicher, Zitat: „Serialization was a horrable Mistake. About 50 Percent of all Vulnerabilities in Java are linked to Java Serialization.”

Starker Tobak! Wenn sich die beiden führenden, für die Weiterentwicklung von Java verantwortlichen Architekten bei Oracle so deutlich über ein Feature in Java äußern, dann scheint hier etwas gewaltig schief gelaufen zu sein. Grund genug sich einmal näher mit dem Thema auseinanderzusetzen.

 

Serialisierung ist sehr einfach

Der Einsatz von Serialisierung ist sehr einfach und es gibt unzählige Anwendungsfälle, weshalb diese Funktion seit 25 Jahren an allen Ecken und Enden verwendet wird. Um eine Klasse serialisieren zu können, muss diese lediglich das Interface java.io.Serializable implementieren, das der Klasse das Serialisierungsverhalten übermittelt. Für die Umwandlung eines Objektes in einen Byte-Stream ist die Klasse ObjectOutputStream zuständig. Für den Transfer des Datenstroms kann man dann jede beliebige Variante wählen, die in Java zur Verfügung steht, i.d.R. Sockets oder RMI.

 

(Listing 1)

 

Java-Anwendungen, die Daten empfangen möchten, müssen den ankommenden Byte-Stream einlesen und daraus wieder äquivalente Objekte erzeugen (Deserialisierung), was mit der Klasse ObjectInputStream erfolgt.

 

(Listing 2)

 

Daten-Persistierung

Neben der Übertragung von Informationen an eine andere Java-Anwendung ermöglicht die Serialisierung auch das Schreiben (Listing 3) und Lesen (Listing 4) in bzw. aus einer Datei oder Datenbank. Dafür sind die Klassen FileOutputStream und FileInputStream zuständig.

 

(Listing 3)

 

(Listing 4)


 

Was macht Java-Serialisierung zu einem potentiellen Sicherheitsrisiko?

Um auf der Empfängerseite aus dem Datenstrom wieder Objekte erzeugen zu können, werden neben den Daten auch die Klassendefinitionen mit verschickt. Anhand des Namens versucht Java diese Klasse dann im Klassenpfad zu finden und führt automatisch deren readObject Methode aus, um den Byte-Strom zu deserialisieren. Alle Java-Klassen, die sich im Klassenpfad befinden und java.io.Serializable implementieren, werden auf diese Weise vom Empfänger vollautomatisch deserialisiert. Dieses Verhalten kann generisch zur Ausführung von Schadcode ausgenutzt werden. Angreifer, die die Klassendefinition eines serialisierten Objektes kennen, können diese durch Man-in-the-Middle verändern und auf diese Weise Angriffe gegen den Server durchführen, um z.B. Schadcode zu injizieren. Das Problem ist bereits seit vielen Jahren bekannt.

Durch die Schwachstellen in der Java-Serialisierung werden häufig Bugs in Open-Source-Frameworks ausgenutzt, die wir alle täglich bei der Anwendungsentwicklung verwenden. Es ist regelrecht beängstigend, wie leicht es ist, diese Sicherheitslücke auszunutzen. Es gibt dafür sogar Codegeneratoren im Internet wie ysoserial. Das Tool ermöglicht es, angreifbare Klassen zu missbrauchen, sodass sich damit Schadcode ausführen lässt.

 

Wo wird Serialisierung eingesetzt?

In Java wird Serialisierung aber praktisch überall verwendet, selbst da wo sie niemand vermutet, weil sie tief unter der Haube zum Einsatz kommt und nicht sichtbar ist – in allen möglichen Dependencies die wir tagtäglich verwenden, ohne dass wir uns darüber Gedanken machen. Bereits in Java 8 wurde das Interface java.ioSerializable über 5.000 Mal implementiert. U.a. wird Serialisierung verwendet in JPA (Java-Persistence-API) und damit automatisch von jeder einzelnen Datenbankapplikation wir auf Basis des Java-Standards entwickeln. Des Weiteren in CDI (Contexts-and-Dependency-Injection), das praktisch alle großen Java-Frameworks wie Java-EE, Spring, etc. unterstützen. Ebenso in RMI (Remote-Method-Invocation), JMX (Java-Management-Extensions) und sogar in HTTP-Cookies und was besonders interessant ist: auch in REST-Services. Intern wird Serialisierung von allen wichtigen Java-Basistechnologie verwendet, u.a. WebLgoic, JBoss, WebSphere, Jenkins, Struts, Spark usw. Alle darauf aufsetzenden Unternehmensanwendungen erben automatisch die mit Java-Serialisierung verbundenen Sicherheitslücken.

 

Zunehmende Angriffsfläche durch Microservice-Architektur

Die potentielle Angriffsfläche wird sogar immer größer, denn heutzutage muss praktisch jede Java-Anwendung permanent Daten übertrage. Früher wurden Java-Programme noch monolithisch, also in einem Stück konzipiert. Die verschiedenen Anwendungsmodule hingen in einer einzigen JAR zusammen und die gesamte Kommunikation zwischen den Modulen fand intern auf derselben Maschine statt. Nur mit externen Applikationen mussten Daten über Netzwerk ausgetauscht werden. Heute geht der Trend immer stärker weg vom Monolithen hin zu einer Microservice-Architektur. Eine Anwendung setzt sich jetzt aus einer Vielzahl an Kleinstprogrammen zusammen, die nicht nur völlig autark voneinander lauffähig, sondern zudem hochverfügbar sein sollen, sodass jeder einzelne Service auch noch redundant laufen muss. Dazu werden die einzelnen Microservices containerisiert und via Cloud über mehrere Rechenzentren, Regionen und sogar Erdteile verteilt. Folglich erfolgt auch die gesamte interne Kommunikation zwischen den einzelnen Microservices einer Anwendung über das Netzwerk, wodurch die Anzahl potentieller Einfallstore rapide zunimmt.

 

Wie kann man sich schützen

Es gibt mehrere Möglichkeiten wie man sich vor Exploits schützen kann. Black- oder Whitelisting von Klassen wird dabei mit am häufigsten genannt. Blacklisting ist enorm aufwändig und in der Praxis kaum lückenlos realisierbar, da man alle kritischen Klassen berücksichtigen und seine Blacklist permanent Up-to-Date halten muss. Whitelisting, also nur Klassen zulassen, die man tatsächlich verwendet, ist ebenfalls aufwändig, weil man alle serialisierbaren Klassen sämtlicher Dependencies mit in die Whitelist aufnehmen müsste. In der Praxis kommen beide Verfahren deshalb kaum ausreichend zum Einsatz, entweder weil sich die Entwickler der Gefahr gar nicht bewusst sind, der Wartungsaufwand viel zu groß erscheint (und vom Kunden ohnehin nicht bezahlt wird) und weil die meisten Entwickler schlicht und einfach selbst noch nie betroffen waren. Ähnlich wie bei gefährlichen Krankheiten, schätzen die meisten Menschen ein Infektionsrisiko als sehr gering ein, wenn sie vorher selbst noch nie davon betroffen waren. Der berühmt gewordene Fall des US-amerikanischen Finanzdienstleistungsunternehmen Equifax sollte jedoch als Warnung dienen und zeigt was passieren kann, wenn Hacker vorhandenen Schwachstellen ausnutzen. 2017 hatten Hacker eine Sicherheitslücke in dem bereits genannten Open-Source-Framework Apache-Struts ausgenutzt, um die Daten von 143 Millionen Kunden zu erbeuten. Die Entwickler bei Equifax haben es trotz vorliegender Informationen über das Sicherheitsleck in Struts verpasst, den bereits verfügbaren Patch rechtzeitig einzuspielen.

 

Weitere Einschränkungen

Java-Serialisierung hat nicht nur gravierende Sicherheitslücken. Was aus Entwicklersicht sogar noch schwerer wiegt, sind die zahlreiche Einschränkungen der Java-Serialisierung, welche die Entwicklung unnötig komplizierter machen und deshalb teuer sind. Wie bereits erwähnt, müssen Klassen java.io.Serializable implementieren, um serialisierbar zu sein. Das ist dann problematisch, wenn man eine Third-Party-API verwenden möchte, die Klassen enthalten, die das Interface nicht implementieren und folglich nicht serialisierbar sind.

Eine erhebliche Einschränkung ist zudem, dass Objektgraphen immer vollständig serialisiert werden, ohne dass sich einzelne Instanzen als Identitäten ansprechen lassen. Gezielt nur einzelne Objektreferenzen eines Objektgraphen zu serialisieren, falls nicht mehr Informationen übertragen werden müssten, ist nicht möglich. Dadurch entsteht häufig enormer, völlig überflüssiger Overhead, was die Serialisierung sehr ineffizient macht.

Bei der Deserialisierung werden immer neue Objektinstanzen erzeugt, sprich Objektkopien, deren Weiterverarbeitung sehr umständlich ist. Objektgraphen auf der Empfängerseite punktuell upzudaten, ist nicht möglich. Da immer nur ganze Objektgraphen serialisiert werden, führt der mitgeschleifte Overhead auf der Empfängerseite zu vielfach höheren Speicherverbrauch als nötig wäre.

Zur Datenspeicherung ist die Java-Serialisierung daher nur für wenige Anwendungsfälle brauchbar, z.B. wenn es um die Speicherung von Meta- oder Bulkdaten geht. Ohne Update-Funktion ist sie als DBMS-Ersatz dagegen völlig unbrauchbar.

Hinzu kommt, dass es keine Versionierung der verwendeten Klassen gibt, was bei jeder Änderung manuellen Anpassungsaufwand verursacht und zudem eine große potentielle Fehlerquelle darstellt.

 

Welche Alternativen gibt es?

Es existiert eine Vielzahl an Serialisierungs-Libraries, die auch Brian Goetz in seinem Beitrag aufgeführt hat, u.a. Arrow, Avro, Bert, Blixter, Bond, Capn Proto, CBOR, Colfer, Elsa, Externalizor, FlatBuffers, FST, GemFire ​​PDX, GSON, Hessisch, Ion, Jackson, JBoss-Marshalling, JSON.simple, Kryo, Kudu, Blitz, MessagePack, Okapi, ORC, Paranoid, Parcelable, Parkett, POF, Portable, Protokoll Puffer, Protostuff, Quickser, Reflect, Seren, Serial, Simple, Simple Binary Encoding, SnakeYAML, Stephenerialization, Thrift, TinySerializer, Travny, Verjson, Wobly, XSON, XStream, YamlBeans.

Die meisten dieser Libraries zielen jedoch lediglich darauf ab, anstelle des binären Formats der Java-Serialisierung ein anderes Format zu verwenden, z.B. JSON, und dieses effizienter und flexibler verarbeiten zu können. Unter der Haube kommt meist sogar die originale Java-Serialisierung zum Einsatz, sodass die fundamentalen Probleme der Java-Serialisierung, insbesondere die aufgeführten Einschränkungen damit weiterhin ungelöst bleiben und auf Grund ihrer Eigenheiten zum Teil ganz Probleme verursachen.

 

Serialisierung mit REST und JSON

Inzwischen hat sich die Kommunikation via REST und JSON zum de facto Standard entwickelt. Der Vorteil von JSON ist ähnlich wie bei XML vor allem, dass die Datenübertragung damit nicht nur zwischen Java-Anwendungen, sondern programmiersprachenunabhängig zwischen beliebigen Programmen und Diensten erfolgen kann, zum Beispiel mit einem in PHP geschriebenem Webservice.

Der große Nachteil flacher Datenstrukturen wie JSON und XML ist jedoch, dass diese sich nicht für die Abbildung komplexer Objektgraphen eignen – die wir jedoch in Java ständig verwenden – und deshalb nicht zum Objektmodell von Java passen. Selbst simple Zirkelbezüge sind damit nicht abbildbar. Sämtliche Referenzen zwischen den Objekten werden gebrochen. Bei größeren Datenmengen kommt es zu einem enormen Overhead. Auch die Weiterverarbeitung der eingehenden Daten ist sehr aufwändig, da aus dem JSON-Code erst wieder Java-Objekte erzeugt werden müssen. Das Parsen umfangreicher JSON-Strings ist zudem mit Performanceeinbußen verbunden. Die bei der Java-Serialisierung aufgeführten Einschränkungen treffen bei der Serialisierung mit JSON analog zu.

 

Was plant Oracle?

Obwohl die Chefarchitekten bei Oracle regelmäßig mit drängenden Fragen zur Java-Serialisierung konfrontiert werden, wann man dieses Problem angehen wird, gibt es seitens Oracle auch weiterhin keine konkreten Aussagen. Brian Goetz hat zumindest einen Beitrag veröffentlicht, indem er seine persönlichen Gedanken skizziert, wie er sich eine bessere Serialisierung vorstellt. Dabei betont er die Wichtigkeit, dass sich die Serialisierung der Zukunft sich homogen in das Objektmodell von Java einfügen müsse. Auf der anderen Seite denkt er über eine Abkehr von der Serialisierung komplexer Objektgraphen und Beschränkung auf die Serialisierung reiner Daten nach, um die Komplexität zu reduzieren. Dieses Szenario ginge in die Richtung von JSON und XML und würde demnach nicht besonders gut zum Objektmodell von Java passen. Bereits zu Beginn des Textes heißt es, dass es sich lediglich um einen Entwurf, nicht um eine offizielle Spezifikation für die Java-Plattform handelt.

 

Mark Reinhold spricht in Interviews von einem Serialisierungs-Framework, das eine einheitliche Implementierung von Serialisierung ermöglichen soll, mit dem Entwickler auf einfache Weise den Serialisierungs-Provider ihrer Wahl ähnlich einem Plugin einbinden können – neben sämtlichen Serialisierungs-Frameworks zur Not auch die alte Java-Serialisierung. Die Beschreibung deutet auf eine standardisierte API ähnlich JPA hin. Damit wären Entwickler in der Lage, bei Bedarf an nur einer Stelle des Programms schnell und einfach das Serialisierungs-Framework zu wechseln. Von der Entwicklung einer neuen Implementierung, die die fundamentalen Probleme der bisherigen Java-Serialisierung löst, ist jedoch nicht die Rede. Wann und ob Oracle überhaupt in naher Zukunft das Thema Serialisierung angehen wird, dazu wollte sich Mark Reinhold nicht verbindlich äußern.

 

Eine neue Serialisierung für Java

Wie so oft ist die Java-Community sehr viel schneller mit Lösungsansätzen, die in der Praxis funktionieren und bereits erprobt sind – so jetzt auch in Sachen Serialisierung: MicroStream hat jetzt eine von Grund auf völlig neu entwickelte Serialisierung für Java veröffentlicht, die nicht nur sicher sein soll, sondern vor allem nahezu alle gravierenden Einschränkungen der Java-Serialisierung beheben soll und vom Hersteller deshalb vielversprechend als Next-Generation-Java-Serialization bezeichnet wird.

Die Entwicklung von MicroStream wurde 2013 im Zuge eines Großprojekts für die Möbelindustrie unter dem Projektnamen Jetstream gestartet. Seit 2015 läuft die Technologie im Produktivbetrieb als technische Basis eines Transaktionssystems über das die Möbelindustrie ein jährliches Umsatzvolumen zwischen 1,3 bis 1,5 Milliarden Euro abwickelt. Anfang des Jahres wurde das Projekt in MicroStream umbenannt und das im April erst neu gegründete Unternehmen hat schnell Investoren gefunden, die einen größeren Millionenbetrag investiert haben, um die Weiterentwicklung voranzutreiben und die Unterstützung der Java-Community zu gewährleisten.

Mit MicroStream Version 2.0 ist nun das Final-Release frei verfügbar unter www.microstream.one. MicroStream ist eine winzige Java-API. Der Download erfolgt via Maven. Als Minimalanforderung wird lediglich JDK 8 angegeben. Ansonsten hat die Library keine Abhängigkeiten.

Mit MicroStream lassen sich völlig beliebige Java-Klassen serialisieren, ohne dass diese ein Interface implementieren oder von einer Superklasse ableiten müssen. Auch Annotations gibt es nicht. Klassen  die serialisierbar sein sollen, werden in ein Dictionary aufgenommen, das bei der Deserialisierung mit der Klassendefinition des Empfängers verglichen wird. Damit lassen sich auch beliebige Klassen von Third-Party-APIs serialisieren.

MicroStream wurde von Anfang an konzipiert, um komplexe Objektgraphen zu serialisieren, sollte sich elegant in das Objektmodell von Java einfügen und sich wie ein nativer Teil von Java anfühlen.

Mit MicroStream lassen sich jetzt erstmals einzelne Instanzen als Entities ansprechen und gezielt einzelne Objektreferenzen eines Objektgraphen serialisieren. Auf der Empfängerseite wird der Objektgraph dann gezielt upgedatet. Dadurch wird praktisch kein unnötiger Overhead mehr übertragen, was MicroStream hoch effizient macht. Nur umständlich verarbeitbare Objektkopien gibt es nicht mehr, was auch gleichzeitig den Speicherverbrauch deutlich reduziert. Dadurch ergeben sich völlig neue Möglichkeiten.

 

Kommunikation und Datenspeicherung

MicroStream bietet nicht eine Lösung für Alles, sondern bietet für die beiden Anwendungsfälle Kommunikation und Persistierung (Datenspeicherung) jeweils eine optimierte Lösung. Darunter verbirgt sich jeweils dieselbe Serialisierung (MicroStream-Core).

 

Kommunikation zwischen Objektgraphen

Für die Datenübertragung zwischen zwei oder mehreren Java-Anwendungen stellt MicroStream einen Convenience-Layer zur Verfügung, der eine effiziente Objektgraphkommunikation ermöglicht (Host und Clients).

 

Persistierung von Java-Objektgraphen (Java-Native-Data-Store)

Die Möglichkeit, Objektgraphen punktuell updaten zu können, macht MicroStream zu einer leistungsfähigen Storage-Engine für das Speichern, Laden und Updaten nativer Java-Objektgraphen, die den Einsatz externer DBMS völlig überflüssig macht.

Bei der Persistierung werden standardmäßig nur die Änderungen am Objektgraphen persistiert. Die persistente Speicherung des Deltas in einer Datei erfolgt immer anhängend (Append). Schlägt die Persistierung fehl, werden die angehängten Daten wieder verworfen, was grundsätzlich mit einer zurückgerollten Transaktion in RDBMS vergleichbar ist.

 

Lazy-Loading

Zum Laden von Daten ermöglicht MicroStream sämtliche Objektreferenzen lazy zu laden (Lazy-Loading). Damit können Objektgraphen mit einem Datenvolumen im Terabyte-Bereich persistent gespeichert werden, während sich jeweils nur ein kleiner Teil davon im RAM befindet.

 

Klassen-Versionierung und Garbage-Collection auf Dateiebene

MicroStream bietet eine vollautomatisierte Klassen-Versionierung. MicroStream erkennt zur Laufzeit automatisch, ob sich bei einer Klasse etwas geändert hat und aktualisiert die persistenten Daten automatisch. Standardtypen werden automatisch gehandelt. Für komplexere Typen lassen sich Mapping-Rules definieren.

Objektreferenzen, die über den Objektgraphen nicht mehr erreichbar sind, werden bekanntlich vom Garbage-Collector der JVM automatisch gelöscht. Bei erneuter Persistierung des Objektgraphen, werden die zu löschenden Referenzen auch in der persistenten Datei markiert. Damit diese Daten dann auch tatsächlich aus der Datei entfernt werden, bietet MicroStream eine Garbage-Collection-Funktion zur Verfügung, die auf Dateiebene operiert und in eigenen Thread die Storage optimiert.

 

Datenbankabfragen in Mikrosekunden

Für Abfragen ist keine neue Abfragesprache nötig. Die Daten befinden sich in Form eines Objektgraphen im Hauptspeicher, der sich mit Hilfe von Java-8-Streams effizient durchsuchen lässt. Das Durchsuchen selbst komplexester Objektgraphen dauert in-memory i.d.R. nur Mikrosekunden und ist damit bis zu 1.000 Mal schneller als klassische Datenbanksysteme deren Abfrageergebnisse im Bereich von Millisekunden liegen. Mit Hilfe paralleler Streams lässt sich die Performance nochmals steigern. Vielfach ausgeführte Streams-Operationen werden nochmals vom JIT-Compiler der JVM optimiert.

 

Java In-Memory-Computing  

Die geradezu fantastischen Zugriffszeiten haben dabei gar nichts mit MicroStream zu tun, sondern sind das Resultat reiner Java-Programmierung. Gemäß dem Ansatz von Separation-of-Concerns kümmert sich MicroStream grob um nichts anderes als um die Serialisierung. Dieser Ansatz ist so alt wie die Java-Serialisierung, nur brauchbar für die Anwendungsentwicklung wird dieser erstmals mit MicroStream. Die MicroStream-Entwickler bezeichnen diesen Ansatz als Pure-Java-In-Memory-Computing-Paradigma.

 

Einfache Implementierung

Aus Entwicklersicht ist dieser Ansatz ebenfalls spannend. Alles was man braucht sind Java-Entity-Klassen und MicroStream für die Persistierung. Es gibt nur noch ein einziges Datenmodell. Das Objektmodell lässt sich nun völlig frei designen. Ein aufwändiges Type-Mapping wie bei der Verwendung externer Datenbanksysteme gibt es nicht mehr. Der Einsatz von ORM-Frameworks wie Hibernate und die damit verbundene Komplexität fällt ebenfalls ersatzlos weg.

Wer mit MicroStream Datenbankapplikationen entwickeln möchte, muss umdenken. MicroStream ist kein DBMS, sondern eine reine Storage-Engine für Objektgraphen. Um Concurrency muss sich die Businesslogik kümmern. Die Businesslogik wird zum DBMS.

MicroStream läuft auf dem Server, auf Java-Desktops, in Cloud- und Container-Umgebungen und ist prädestiniert für den Einsatz als Persistence-Strategie für Microservices. MicroStream ermöglicht die Entwicklung hochperformanter In-Memory-Datenbankanwendungen mit pure Java. Auch klassische Business-Applikationen lassen sich mit MicroStream stark beschleunigen und die Entwicklung spürbar vereinfachen. In Kürze soll MicroStream auch auf Android, und damit auf mobilen Geräten und Embedded-Systemen lauffähig sein.

Sebastian Späth ist Senior Java Developer und Technology Evangelist bei der XDEV Software Corporation. Er verfügt über eine breite Berufserfahrung und war mit RapidClipse an der Entwicklung einer eigenen Eclipse-Distribution beteiligt. Sebastians Schwerpunkte sind Rapid Development und Rapid Prototyping.

 

[1] https://bit.ly/2NmWlg1

Redaktion


Leave a Reply