Schlagwort-Archive: Rant

Ich weiß nicht ob das typisch für mich ist, dass ich das neue Jahr mit einem Rant einleite, aber zeitlich ist es jedenfalls nicht beabsichtigt. Ich wasche meine Hände in Unschuld. Zunächst also ein frohes neues Jahr. Die tollen, freundlichen Beiträge kommen alle noch die Tage. Wieder einmal habe ich die Hoffnung, dass dieser Artikel all jenen hilft, die mit einem ähnlichen Problem konfrontiert werden. Das Programmiererleben ist sicherlich vieles, aber gewiss nicht einfach.

Vergangene Woche war ich in der Situation eine portable Version einer Solaris JVM (Java Virtual Machine) aktualisieren zu dürfen. Die bisherige Version des JDK6 war leider veraltet und brachte regelmäßig Segmentation Faults im Dauerbetrieb zustande. Ein neueres Update (1.6.0 Update 38) sollte hoffentlich stabiler laufen. Mit einer portablen Version ist eine Java-Installation gemeint, die man einfach auf dem Zielsystem in ein Verzeichnis seiner Wahl entpackt und die sofort (und vor allem ohne betriebssystemabhängige Installation) lauffähig ist. Aus diesem Grund wollte ich mir eine solche Version von Oracle herunterladen. Das war aber schon das erste Problem: Oracle ist nämlich ziemlich scheiße.

Oracle bietet (jedenfalls für Java 6) keine portablen JDKs zum Entpacken an – nur Installer. Da ich auf dem Zielsystem aber keine Installationsprogramme ausführen kann/darf/will, ist das selbstverständlich keine Alternative, zumal ich ja wusste, dass Java problemlos portabel ausführbar ist. Eine Installation ist daher gar nicht nötig. Kurzerhand musste ich also kreativ werden und basteln. Ich wollte den doofen Installer umgehen und die Dateien von Hand extrahieren. Das war gar nicht so schwierig wie ich dachte. Mein Werk wollte ich im Vorbeigehen kurz an einer Client-Anwendung testen, als beim Starten der JVM eine wilde Fehlermeldung erschien:

Error occurred during initialization of VM
java/lang/NoClassDefFoundError: java/lang/Object

Soso, sehr interessant. Die JVM kann die Klasse java.lang.Object nicht finden. Wenn diese Klasse fehlt, dann fehlt praktisch alles. Ein freundliches Google teilte mir mit, dass es vermutlich mit einer fehlenden Datei rt.jar im Verzeichnis /jre/lib/ zusammenhängt. Tatsächlich, diese Datei gab es dort nicht. Ist Oracle wirklich so bescheuert und liefert ein unvollständiges, nicht lauffähiges JDK aus? Ist das die Strafe dafür, dass ich den Installer übergangen habe?

Ist es. Denn der Installer hat zudem die Aufgabe, die rt.jar aus einer gepackten Datei namens rt.pack auszupacken, und diverse weitere Dateien:

./lib/tools.pack
./jre/lib/charsets.pack
./jre/lib/jsse.pack
./jre/lib/deploy.pack
./jre/lib/javaws.pack
./jre/lib/plugin.pack
./jre/lib/rt.pack
./jre/lib/ext/localedata.pack

Warum das so ist, weiß nur der Teufel. Platzersparnis bringt es gegenüber dem umliegenden Archiv keine. Es ist wahrscheinlich reine Schikane. Manche behaupten auch, das wäre ein Mechanismus, um sicherzustellen, dass niemand den Installer umgeht, da dieser ja zum Akzeptieren der AGB auffordert. Zum Glück gibt es die mitgelieferten Java-Tools pack200 und unpack200. Mit deren Hilfe kann man die JAR-Dateien aus den PACK-Dateien befreien – sogar über verschiedene Betriebssysteme hinweg. Und dann klappt das auch wieder mit der JVM.

Seit diesem Tag hasse ich Oracle wieder ein bisschen mehr, und ich bin ein bisschen weiser geworden. In meinen Augen eine echte Schweinerei. Portable Versionen sind super und hinterlassen weniger Spuren. Wenn man weiß was man tut, und wenn man in der Lage ist, sich selbst um die richtigen Pfadangaben zu kümmern, dann hat ein portables Java viele Vorteile, vor allem wenn man viele homogene Systeme unter seiner Obhut hat.

Quellen:
http://www.cynosurex.com/Forums/DisplayComments.php?file=Java/Finding_rt.jar_in_JRE_5.0_Update_9
http://tntit.blogspot.de/2012/04/linux-jdk-6-installation-hard-way.html
http://turbolinux.org/2011/05/error-occurred-during-initialization-of-vm-javalangnoclassdeffounderror-javalangobject/
http://stackoverflow.com/questions/1619662/where-can-i-get-the-latest-jre-jdk-as-a-zip-file-i-mean-no-exe-installer

„Wie bitte? Sound in Java? Wer würde denn so etwas wollen? Und dann wahrscheinlich auch noch 100% plattformunabhängig, ja? Wer Sound in Java haben will, soll wenigstens furchtbar leiden müssen. Also gut, wir machen es! Aber wir machen es so schlecht wie möglich, damit es niemand benutzen will!“

So oder so ähnlich muss das wohl bei Sun geklungen haben, als man sich irgendwann notgedrungen entschloss eine Java Sound API zu entwickeln. Ich kann mir jedenfalls nicht anders erklären, wieso es im Jahr 2012 immer noch nicht möglich ist, anständig mit JavaSound zu arbeiten, wenn es um so simple Dinge wie Ausgabe von z.B. WAVE-Audio geht. Es funktioniert – keine Frage – aber es macht keinen Spaß und es ist eine performancetechnische Katastrophe.

Gestraft ist man vor allen Dingen dann, wenn man sich aus Gründen des Minimalismus und im Sinne der größtmöglichen Platzersparnis entschließt, weitestgehend unabhängig von den bekannten teilweise mehrere Megabyte großen Java-Soundbibliotheken irgendwelcher Fremdanbieter bleiben zu wollen, die vereinzelt scheinbar sogar 3D-Audio in Java realisieren können. Aber sowas wollte ich gar nicht. Ich wollte einfach nur Audiodateien ausgeben ohne zusätzlichen Ballast von irgendwelchen Multimediabibliotheken und Java-Spiele-Komplett-Engines einbinden zu müssen. Ich bräuchte sowieso nur Start, Stopp und einstellbare Loops, mehr nicht. Zum Glück kann das JavaSound alles. Theoretisch.

Man hat die Wahl der Qual zwischen Pest und Cholera. Es gibt java.applet.AudioClip, welches den Vorteil hat, wirklich extrem einfach zu bedienen zu sein. Man kann da gar nichts falsch machen. Leider funktioniert das mit vielen WAVE-Dateien nicht, wenn sie z.B. eine etwas exotischere Samplingfrequenz haben. Auch gibt es Probleme mit sehr kurzen oder sehr langen Audiodateien. Und das Loopen und Abspielen ist mir dann eigentlich doch zu spartanisch. Looppoints wären schon nötig gewesen.

Für so etwas gibt es JavaSound mit javax.sound.sampled.Clip. Funktioniert ähnlich einfach, und bringt gleich die nötigsten Methoden mit, man kann sogar „Vor- und Zurückspulen“ und die Anzahl der Loops setzen. Clip leidet allerdings unter einer unglaublich miesen Performance. Das macht sich beim Abspielen eines einzelnen Samples gar nicht bemerkbar, außer man hält den Speicher- und CPU-Verbrauch seiner JVM sehr genau im Auge. Nein, das ganze Ausmaß des Grauens entdeckt man erst, wenn man – wie das z.B. in Spielesoftware recht üblich ist – den selben Clip in sehr kurzen Abständen mehrfach hintereinander abspielt (z.B. Sprung- oder Schieß-Geräusche). Die ganze Anwendung beginnt zu ruckeln, die Sounds werden teilweise verschluckt, manchmal überhaupt nicht abgespielt. Das ist so natürlich nicht akzeptabel. Ich vermute es liegt einfach am nicht unerheblichen Overhead für das Starten und Stoppen der Threads jedes einzelnen Sounds.

Es gab da noch eine weitere Kleinigkeit, die mir die Haare zu Berge stehen ließ. Bei Clip lassen sich zwar bequem die Looppunkte setzen, beim ersten Abspielen mittels loop() scheint es diese aber komplett zu ignorieren. Erst beim zweiten und bei jedem weiteren Mal geht es dann plötzlich wie gewünscht. Ich habe alle erdenklichen Kombinationen versucht, den Audiopuffer geleert, und alle Methoden getestet, die diese Klasse mit sich bringt. Da war nichts zu machen. Ich musste mir schließlich mit einem billigen Workaround behelfen, das Sample zuvor „heimlich“ einmal für eine Millisekunde anzuspielen und sofort mit anschließendem Rewind zurücksetzen, damit es dann gleich beim ersten Mal richtig loopt.

JavaSound hat noch soviele Kinderkrankheiten, dass es beinahe schon absurd ist, wenn man bedenkt, wie lange es Java schon gibt. Sogar die deutlich jüngere Dalvik VM unter Android bietet mehr und leistet mehr, ist vor allem sehr viel spielefreundlicher in dieser Hinsicht. Multimedia in Java ist wohl leider noch etwas, das äußerst stiefmütterlich von Sun bzw. Oracle behandelt wird. Okay, dafür gibt es ja wenigstens JavaFX 2.0. Vielleicht taugt das ja für solch verrückte und völlig abwegige Experimente wie Soundausgabe in einer Java-Anwendung.

Deutsche Bahn ist das, was passiert, während du gerade dabei bist, deinen Feierabend zu planen.

Fast zehn Stunden gearbeitet, stressiger Tag, die Nerven liegen blank, hundemüde, der Magen knurrt, nur noch mit der Bahn nachhause fahren. Ich kann höchstens mutmaßen, dass die lustige Bahn genau darauf gewartet hat, dass ich Feierabend mache, zum Bahnhof schlurfe, und dann BAM!!! Massive Verspätung voll in die Fresse! So als hätte ich sonst keine Probleme. Zeit für einen ordentlichen Rant um die Luft rauszulassen.

Wie kann es sein, dass der Zug, mit dem ich in aller Früh zur Arbeit pendle, in dem ich mit den quengelnden lautstarken nervtötenden Schülern um die wenigen Sitzplätze kämpfen muss, täglich Verspätung hat? An jedem verdammten Morgen, fünfmal die Woche! Ich weiß immer schon, dass der Zug Verspätung hat, bevor es die Bahn überhaupt für nötig hält, es auf der Anzeigetafel einzublenden. Wenn es denn eingeblendet wird. Und an anderen Tagen, wenn ich leider mal spät dran bin, und ich völlig außer Atem am Bahnhof ankomme, kaum eine halbe Minute zu spät, da kann ich in der Ferne noch die Schlusslichter des Zuges bewundern, der natürlich total pünktlich abgefahren ist, so als wäre es bei der Bahn nie anders.

Wie kann es sein, dass, wenn ich in Zug X Richtung Y sitze, dieser Zug endlose 15 Minuten lang auf Anschlussreisende warten muss, deren Zug heute ganz unerwartet Verspätung hat, aber sobald ICH einer dieser Anschlussreisenden bin, für die normalerweise gewartet wird, schafft es derselbe Anschlusszug nicht einmal 2 Minuten stillzustehen und fährt pünktlich ab? Das war Anfang Februar, um 19 Uhr, bei minus 14 Grad Celsius. Es waren frostige 50 Minuten, die ich an einem fast menschenleeren Bahnhof auf den nächsten Zug warten durfte. Ein großes Vergnügen!

Wie kann es sein, dass immer genau der Zug, in dem ich mich gerade befinde, auf entgegenkommende Züge warten muss, mitten im Nirgendwo gemütlich stehenbleibt, ich panisch auf der Uhr mitzähle, wieviele Sekunden mir am Bahnhof noch zum Umsteigen (oder besser: zum Umrennen) bleiben, bevor der Zug seine Fahrt nach mehreren Minuten fortsetzt? Das beste daran ist die großzügige Pause, die noch gemacht wird, wenn der entgegenkommende Zug längst vorbei ist. Nein, falsch. Das beste daran sind die vielen Leute, die am Bahnhof alle aus dem Zug sprinten, in der Hoffnung, innerhalb von 9,68 Sekunden von Gleis 10 runter nach Gleis 1 zu laufen und dabei weniger als 5 Hürden zu reißen, äh Verzeihung, alte Leute über den Haufen zu rennen. Der Zug ist aber oft sowieso schon weg.

Wie kann es sein, dass die Verspätungen, die Ausfälle, die Zwischenfälle und alle sonstigen Ärgernisse bei der Bahn subjektiv in den letzten Jahren zugenommen haben, und statt als entnervter Dauerfahrgast dafür aber irgendwie entschädigt zu werden, muss ich lesen, dass die Fahrkartenpreise künftig wieder einmal erhöht werden? Irre ich mich oder bedeutet das im Endeffekt, dass ich MEHR bezahle für WENIGER Leistung? Ich will entschädigt werden, wenn ich im Winter morgens oder abends 3 Stunden am Bahnhof warten muss. Nicht nur, dass es schweinekalt ist, sondern auch, dass es einfach verdammt schade um die sinnlos vergeudete Zeit ist. Ein solchermaßen versauter Tag reicht mir bereits, damit ich den Preis für ein Monatsticket aufs Neue in Frage stellen muss.

Ich vermute, das ist einfach die große Ausgabe von „Wieso sind bei mir immer alle Ampeln rot“, aber in all den Jahren hat sich soviel Frust und Ärger wegen der Deutschen Bahn angesammelt, dass jede weitere Verspätung mich zum Kochen bringt. Es gab Wochen, in denen die Bahn mir bis zu 6 Nettostunden an Verspätung beschert hat, und dazu zähle ich natürlich auch solche Begegnungen, wo nur 5 Minuten Verspätung zu einstündiger Zwangswartezeit geführt hat. Das sind 6 Stunden meines Lebens mit denen ich besseres anzufangen gewusst hätte. Ich weiß, dass der Fahrkartenpreis sich allein auf die Beförderungsdienstleistung bezieht, und nicht auf (Un-)Pünktlichkeit oder bequeme Stehplätze mitten auf dem Gang, aber dies wäre ja schließlich kein Rant, wenn nicht wenigstens ein bisschen Drama dabei wäre.

Junge pickelgesichtige minecraft-zockende Gamer verstehen nur wenig von ihrem eigenen … nunja … „Fachgebiet“. Das musste ich jedenfalls vor kurzem feststellen. Was ich zuerst für einen traurigen Einzelfall hielt und ignorierte, begegnete mir in den letzten Wochen so häufig, dass ich die Angelegenheit genauer analysieren musste. Ich habe die Probe gemacht und einige Meinungen zu dem Thema eingeholt. Man berichtete mir von ähnlichen Beobachtungen, was meine These bestätigte. Es scheint fast so als würde es bei dieser neuen Generation von Gamern überall laggen – vor allen Dingen im Gehirn.

Junge razermaus-schwingende headset-tragende Gamer sind zu blöd zwischen ruckeliger Grafik und einem Lag zu unterscheiden. Aber wir uncoolen Oldschooler kennen den Unterschied zum Glück noch, und müssen die Begriffe daher nicht wie Opfer hilflos durcheinanderwerfen. Daher keine Sorge: Mit Hilfe meiner fettkrassen Lehrstunde werden diese armen Seelen vielleicht nicht dumm sterben müssen. Also zumindest nicht ganz so sehr wie zuvor.

Beginnen wir mit einer einfachen Definition der beiden Fachbegriffe. Da ist zunächst der (oder das) sogenannte Lag. Ein Lag entsteht durch einen Engpass bei der Datenübertragung in einem Netzwerk. Er zeigt sich etwa als zeitliche Verzögerung zwischen Aktion des Spielers auf der Tastatur und entsprechender Reaktion der Spielfigur auf dem Bildschirm eines Spieleclients. Wahlweise könnte er auch als Input-Lag gemeint sein, wenn beispielsweise die Mausbewegung spürbar nachzieht. Beides habe ich in diesem Zusammenhang kennengelernt. So ein Lag bewegt sich in einem Bereich von wenigen hundert Millisekunden bis mehreren Sekunden. Ein Lag lässt sich dadurch an einem hohen Ping messen.

Kennen junge Gamer übrigens auch nicht: Netzwerkkarte, BNC-Stecker und T-Stück

Ruckelnde Grafik entsteht vorwiegend wenn die Hardware, die für das Rendern des Bildes zuständig ist, die benötigten Grafikoperationen nicht ausreichend schnell durchführen kann, bis das Bild gezeichnet werden soll. Es entsteht ein zeitlicher Rückstand, der nur kompensiert werden kann, wenn darauf folgende Bilder übersprungen werden (Framedrop). Das Bild ruckelt oder „stottert“. Die Bewegungen sind nicht flüssig, sondern abgehackt, wie ein Daumenkino. Manche sprechen im Extremfall auch von „Diashow“. Der Effekt wird verstärkt oder abgeschwächt, je nachdem wieviele Objekte auf dem Bild gerade zu sehen sind. Ruckelnde Grafik äußert sich in einer niedrigen Framerate, also alles zwischen 0 fps und 25 fps.

Bei einem Lag ist die entscheidende Komponente das Netzwerk und die Netzwerkhardware, etwa wenn im Hintergrund zuviele Downloads/Uploads laufen, und die restliche Bandbreite nicht mehr für die Datenübertragung im Spiel ausreicht. Dagegen ist es bei ruckelnder Grafik die CPU oder die Grafikkarte, beispielsweise weil die Auflösung zu hoch eingestellt ist und so die Kapazität der Hardware übersteigt.

Wir merken uns: Lag – hoher Ping. Ruckelnde Grafik – niedrige FPS. Lag – Spielfiguren reagieren verzögert auf Eingaben oder teleportieren plötzlich wie Zauberer in der Spielwelt herum. Ruckelnde Grafik – Diashow-Effekt, Animation der Spielgrafik ist abgehackt und nicht flüssig.

Wir folgern daraus: „Lag“ ist der falsche Begriff für das was diese Konsumenten DRM-verseuchter Spielekost meinen. Eigentlich meinen sie etwas, das man als „Ruckeln/Ruckler“, „Framedrop“, „low FPS“ oder „scheiß Framerate“ bezeichnen könnte. Es gibt sicher noch bessere Begriffe. Man denke nur mal an die Probleme mit den „Mikrorucklern“ bei einer SLI/Crossfire-Konfiguration von Grafikkarten, die man vor einigen Jahren noch von NVidia und ATI kannte. Niemand wäre auf die Idee gekommen, das Problem „Mikrolag“ zu nennen. Es sind eben keine Lags. Ein Lag ist was anderes.

Das Spiel ruckelt und der unaufgeklärte Gamer flucht: „Wieso laggt das denn so?“. Solche Szenen gehören mit diesem großartigen Artikel hoffentlich bald der Vergangenheit an. Ich bin zuversichtlich, die Welt damit ein bisschen besser und ein bisschen schlauer gemacht zu haben. In der nächsten Folge erkläre ich dann, warum HTML keine Programmiersprache ist. Achja: Dieser Artikel kann Spuren von Satire und Islamkritik enthalten!