Lucene PMC Member Uwe Schindler über die Fehler in JDK7

JDK7-Bugs im Fokus: "Wenn die Fehler auftreten, sind sie schwerwiegend"

Kurz nach Veröffentlichung des JDK7 am 28. Juli gab Apache-Lucene Mitglied Uwe Schindler eine Warnmeldung aus, einige der neuen Hotspot-Optimierungen könnten zu Abstürzen und Berechnungsfehlern führen. Im Gespräch mit JAXenter beleuchtet Uwe Schindler die Hintergründe und gibt eine Einschätzung ab, wer genau von den gefundenen Bugs betroffen ist.

JAXenter: Wo genau hast du die Probleme im JDK7 entdeckt?

Uwe Schindler: Die Probleme wurden an zwei Stellen im Lucene gefunden:

Erstens: Der Porter-Stemmer Algorithmus, welcher für englischen Text eingesetzt wird, um alle Worte in einem Text auf eine Art „Grundform“ zu bringen (z.B. Entfernung des Plural). Dieser „historische“ Code ist nicht Lucene-spezifisch und stammt von Porters Webseite und wird daher auch in vielen anderen Projekten eingesetzt. Betroffen ist hierbei die Methode, welche überprüft, ob Tokens mit bestimmten Suffixen enden (eine Variante von String.endsWith, nur dass diese mit char[] arbeitet). Dieser Code bringt die JVM einfach zum Absturz.

Der zweite Bug (readVInt-Bug) ist schon etwas älter und trat auch kurz vor dem Release von Lucene 3.1 bereits mit Java 6 auf, allerdings hierbei nur unter sehr speziellen Umständen (wenn diese Methode in der DataInput-Klasse über die NIO-API auf MappedByteBuffer.getByte in einer Schleife zugreift). Da der Code für den Zugriff auf MappedByteBuffer neu in Lucene 3.1 war, konnten wir den Bug durch Modifikationen in der readVInt-Methode umgehen (sogenanntes manuelles Loop-Unwinding, eine Schleife, welche eine geringe Anzahl Mal ausgeführt wird, wird durch simples Wiederholen des Codes umformuliert – genau das tut nämlich auch Hotspot automatisch, nur nicht immer korrekt).

In Java 7 trat dieser Fehler nun aber plötzlich noch an weiteren Stellen auf, auch in Schleifen, welche nicht einfach umgeschrieben werden konnten.

Vermutet man selbst solche Fehler in Hotspot, empfiehlt sich folgendes Vorgehen:

  • Ausführen des Programmcodes mit der JVM-Option: -Xint (dies deaktiviert Hotspot). Funktioniert dann alles, liegt ein Hotspot-Fehler vor.
  • Generell sollte man alle Methoden, welche im Verdacht stehen, solche Bugs auszulösen, in TestCases mindestens zehntausend Mal ausführen, weil das das Limit ist, bevor Optimierungen angewendet werden. In Lucene verwenden wir hierfür eine Erweiterung des JUnit-Testframeworks, welches auf Abruf Testcases wiederholt hintereinander ausführt. Die nächtlichen Testbuilds tun genau das. Außerdem sollte man -Xbatch angeben, um die Kompilierung nicht asynchron laufen zu lassen.
  • Nun durch Probieren schrittweise Kompilation von Methoden, welche Schleifen enthalten, deaktivieren, bis der Fehler gefunden ist. Im Falle von Porter war das -XX:CompileCommand=exclude,org/apache/lucene/analysis/en/PorterStemmer,ends

JAXenter: Wie schwerwiegend würdest du diese Fehler einschätzen? Sind das Bugs, von denen viele betroffen sind?

Uwe Schindler: Wenn die Fehler auftreten, sind sie schwerwiegend, da Programme, welche vorher alle ihre Testcases durchlaufen haben und fehlerfrei mit JDK 6 funktionieren, in JDK7 plötzlich andere Ergebnisse liefern. Diese durchlaufen möglicherweise trotzdem die Testcases erfolgreich, weil diese sehr isoliert sind und betreffende Codeteile nicht oft genug aufrufen. Wie schon im JAXenter-Artikel „Wie gravierend sind die Bugs in JDK7 wirklich?“ festgestellt, ist das ganze mit dem Pentium-FDIV-Bug vergleichbar. Im Prinzip funktionierte der Prozessor korrekt, nur in einigen speziellen Fällen lieferte eine Berechnung falsche Ergebnisse.

Ich nehme an, dass Java-Projekte, welche eher servicebasiert arbeiten und mehr an fremde Bibliotheken delegieren, selbst keine solchen Fehler im eigenen Java-Code zu erwarten haben. Wohl aber, wenn das Problem in einer der Komponenten, welche sehr rechenintensiv sind, wie Apache Lucene oder zum Beispiel Apache Derby oder HBase auftritt.

Es ist nicht zu erwarten, dass die Zinsberechnung für Bankkundenkonten betroffen ist. Es könnte aber Code, mit welchem Physiker zum Beispiel für riesengroße Matrizen Eigenwerte berechnen, betroffen sein. Schleifenoptimierungen werden auf Code angewendet, welcher sehr lokal auf einigen wenigen Datenstrukturen arbeitet und dabei wenig externe Methoden aufruft, und wenn nur solche, welche ebenfalls durch den Hotspot-Compiler „inlined“ werden.

Den Bug, welcher zu einem SIGSEGV in der JVM führt, halte ich für nicht so gravierend, da es einen sofortigen Absturz gibt und das betroffene Programm somit gar nicht funktioniert. Wie uns mitgeteilt wurde, kann man das sogar mit der lokalen Eclipse-Installation ausprobieren, wenn diese unter Java 7 läuft. Sucht man dort in der Hilfe, crasht Eclipse einfach (weil es das schon inzwischen antike Lucene 1.9 benutzt).

JAXenter: Gibt es bereits einige Workarounds?

Uwe Schindler: Man sollte die betroffenen Optimierungen ausschalten. Um den SIGSEGV zu beheben, reicht es -XX:-UseLoopPredicate zu benutzen, für die Berechnungsfehler ist nicht ganz geklärt, ob nicht zusätzlich noch sicherheitshalber -XX:LoopUnrollLimit=1 als JVM-Parameter angegeben werden sollte.

In Lucene selbst wäre es möglich, für den SIGSEGV-Porter-Stemmer-Bug einen Workaround einzubauen, es gibt dafür auch einen Patch, welcher lediglich die betroffene Schleife durch einen Methodenaufruf zu einer anderen Klasse ersetzt (welche interessanterweise eine ähnliche Schleife enthält, aber nicht crasht). Aber da dieser Fehler in allen bereits veröffentlichten Releases von Lucene auftritt, der Patch aber nur mit der neuesten Version funktioniert, haben wir uns entschlossen, kein Bugfix-Release herauszugeben. Außerdem wollten wir den originalen Code von Porter unverändert lassen. Betroffene Anwender können die Hotspot-Optimierungen, wie vorher beschrieben, deaktivieren.

Für die readVInt-Berechnungsfehler gibt es keinen Fix im Code von Lucene, da hiervon etliche Schleifen betroffen sind und dieser Code so Performanz-kritisch ist, dass Änderungen funktionierende Java-6-Installationen von Lucene/Solr ausbremsen könnten.


JAXenter: Du hast beschrieben, dass ihr etwa eine Woche vor dem Veröffentlichungs-Termin von JDK7 mit den Tests des Release Candidate für JDK7 begonnen habt. Ist das nicht ein wenig spät, angesichts der Tatsache, dass der RC schon seit Juni vorliegt?

Uwe Schindler: Open Source ist immer noch das freiwillige Engagement der Entwickler, und Entwickler sind eher daran interessiert, neuen Code zu schreiben, als sich damit zu langweilen, Testframeworks für allerhand JVMs aufzusetzen. Da Java 7 eh schon lange auf sich warten ließ, hatte ohnehin schon keiner mehr geglaubt, dass es in naher Zukunft herauskommt, und ich persönlich habe es auch aus den Augen verloren. Ich wurde durch Pressemitteilungen wachgerüttelt und habe dann angefangen, es auszuprobieren. Apache Lucene war das erste Apache-Projekt, was auf den Jenkins-Buildservern der Foundation überhaupt Java 7 eingesetzt hat, seit dem letzten Wochenende steht die JDK7 nun allen Builds zur Verfügung.

JAXenter: Wie ist der Stand der Dinge? Was hat sich bei Apache Lucene seit deinem Blogpost am Sonntag getan?

Uwe Schindler: Die Debatte über die Fehler in Java 7 haben natürlich immer noch hohe Priorität in der Entwicklergemeinde, jeden Tag kommen neue Expertenmeinungen in verschiedenen Blogs hinzu, ich versuche die zu sammeln und in meinem Blog unter Updates zu veröffentlichen. Seitens Oracle kam es zu keinerlei Kontaktaufnahme mit der Apache Software Foundation. Auf der Hotspot-Compiler-Mailingliste gab es ebenso keinerlei weitere Kommunikation zu den Bugs, da der Code für die Fixes inzwischen in den Entwicklungszweig aufgenommen wurde. Ansonsten klingelt das Telefon hier öfters als sonst.

JAXenter: Vielen Dank für Deine Ausführungen!

Eine alternative Einschätzung gibt Software-Architekt Markus Eisele im Beitrag: JDK7-Bugs im Fokus: „Ich gehe davon aus, dass aktuell nicht viele Anwender betroffen sein werden“
Uwe Schindler (uschindler@apache.org) ist Committer und PMCMember
von Apache Lucene Java und Solr. Er kümmert sich hier
vor allem um die neuen Funktionen zur numerischen Suche und
das attributbasierte Textanalyse-API, ein Grundbaustein für das
flexible Indexing. Er arbeitet als Consultant und Entwickler für das
Geoinformationssystem PANGAEA. Er ist regelmäßiger Referent auf
Konferenzen über die Apache-Lucene-Familie.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.