Software

Java

Kleines Quellcode-Gruselkabinett

0

In meinem Beruf komme ich sehr oft mit den Quelltexten vieler Kollegen in Kontakt, deren Programmierwerke ich lesen, verstehen und erweitern können muss. Man gewöhnt sich daran, dass jeder irgendwo seinen eigenen Stil hat, und dass eben jener manchmal besser und manchmal schlechter lesbar ist. Auch ich habe schon Code geschrieben, auf den ich nicht stolz bin, aber man lernt ja schließlich aus Fehlern. Umso amüsanter ist es, wenn man als erfahrener Entwickler hin und wieder zu lesen bekommt, was sich ein blutiger Anfänger so aus seinen Hirnwindungen drückt.

So geschehen vor einigen Monaten, als ein unerfahrener Praktikant (nennen wir ihn im Folgenden einfach “Praktikant”) eine unbedeutende Erweiterung für ein Softwareprojekt schreiben sollte, für das ich teilweise die Verantwortung trage. Ich gehe zwar nicht näher auf die Details der Implementierung ein, aber ich habe drei kleine kuriose Codeschnipsel gesammelt, die mir in seinem Quellcode so aufgefallen sind. Das ist übrigens derselbe Praktikant, der (um mir einen Screenshot zu zeigen) eine Bilddatei in ein leeres Microsoft Word-Dokument eingefügt hat, damit er das Dokument als PDF-Datei exportieren konnte, um es mir dann per E-Mail zu schicken.

Achtung, der folgende Beitrag könnte für Nicht-Programmierer äußerst uninteressant sein.

HashMap<String, HashMap<Integer, ArrayList<String>>> listForAllSystems;

Fangen wir mit etwas Leichtem an. Die obige, mehrfach verschachtelte Collection beweist zwar, dass der Praktikant einen sicheren Umgang mit Collections haben muss, aber diese einzeilige Ausgeburt der Hölle beweist leider auch, dass er nicht weiß, dass man im Idealfall gegen Schnittstellen programmiert, und dass er es wohl gern übertreibt. Was auch immer in diesem “Ding” gespeichert wird, es klingt jedenfalls nicht gesund.

if(isExceptionThrown =! false){

Diese Zeile bekommt Sonderpunkte, weil ich darüber erst einen Augenblick nachdenken musste. Mal davon abgesehen, dass der Praktikant sich hier weder an die Namenskonvention für Boolean-Variablen hält, noch verstanden hat, dass eine Boolean-Variable bereits die Antwort auf die Frage ist, bestaunte ich die kreative logische Verknüpfung. Während ich mich ungläubig fragte, ob der Compiler einen “umgedrehten Ungleich-Operator” wirklich durchgehen lässt, fiel mir dann doch auf, dass das eigentlich eine Zuweisung ist, wobei dem zugewiesenen Wert (false) ein NOT vorangestellt wird (also true). Dieser “Vergleich” ergibt immer true, der IF-Block wird immer ausgeführt. Dieses Codekonstrukt ist absoluter Käse. Vielleicht wollte uns der Praktikant aber auch nur ein wenig erheitern.

if (someObject.equals(null))
    throw new NullPointerException();

Das ist der Gewinner in der Kategorie “Kreativster Schundcode”. Drei Dinge sind absolut bemerkenswert: Zunächst testet man immer mit dem Gleichheitsoperator (==) auf null, definitiv nicht mit equals. Außerdem testet man normalerweise deshalb auf null, weil man eine NullPointerException vermeiden möchte, während der Praktikant hier sogar noch selbst eine werfen will. Und überhaupt: Der Test auf null mit equals kann niemals funktionieren, denn wenn someObject tatsächlich null sein sollte, wird mit equals bereits implizit eine NullPointerException geworfen, wo versucht wird, explizit eine zu werfen. Für das Fazit lasse ich den von mir sehr geschätzten, leider kürzlich verstorbenen Harold Ramis als Dr. Egon Spengler zu Wort kommen: “Kurz, aber völlig sinnlos.”

Und dann war da noch dieser eine unwahrscheinliche “interne” Fehler der Eclipse IDE, den ich wohl versehentlich verursacht habe, als ich während eines Debugging-Durchlaufs versuchte das Workbench-Fenster horizontal zu verkleinern. Die Fehlermeldung, die schon beinahe als Realsatire durchgehen könnte, lasse ich im Folgenden einfach mal für sich selbst sprechen:

internalerror eclipse

Tools

Immer Dreima mehr wie WhatsApp

2

threemaFür dieses Jahr hatte ich mir vorgenommen, mir über Sicherheit und Privatsphäre im Netz ein bisschen mehr Gedanken zu machen, und nicht mehr weiter mit dem Strom zu schwimmen. Zur Not muss man eben auch mal die bequemen ausgetretenen Pfade verlassen, um das Richtige zu tun. Es muss sich etwas ändern, wenigstens in kleinen Schritten. Im Klartext bedeutet das, dass ich im Kontext der Kommunikation künftig auf echte Verschlüsselung setzen werde. Hmm, “Klartext” ist ein witziges Wort in so einem Satz. Und ich meine damit echte Ende-zu-Ende-Verschlüsselung und nicht diese fahrlässige Möchtegern-Verschlüsselung der unsicheren De-Mail.

Nun, wie der Zufall es wollte, ergab sich jüngst eine passende Gelegenheit, meine Kommunikationsmöglichkeiten zu erweitern und gleichzeitig einen ersten Schritt hin zu Verschlüsselung zu machen. Im Moment geistert die Meldung durch alle Medien: Facebook kauft WhatsCrap für 19 Fantastilliarden Dollar. Ganz genau. Zwei Datenkraken haben sich endlich gefunden und werden bald die Lebensgeschichten sämtlicher Nutzer gebündelt via Standleitung direkt an die datenhungrigen Geheimdienste übertragen. Ist doch praktisch, werden sich die Fans sagen, denn bald gibt es das inoffizielle NSA-Rootkit für Android und iOS als Kombi-App.

Rückblende. Einige Jahre zuvor wurde mir von Freunden empfohlen, mir doch diesen tollen neuen Messenger zu installieren, damit ich bei den coolen Gruppenchats mitmachen könnte. WhatsApp sei ja quasi die bessere SMS und auch noch kostenlos. Ich weigerte mich. In den folgenden Wochen hörte ich aus vielen Gesprächen die Unlust im Freundeskreis heraus, mich immer extra per teurer SMS anzuschreiben, wo jeder “normale” Mensch längst dank WhatsApp Bescheid wusste. Hätte ich da ein schlechtes Gewissen haben müssen? Auf meine gutgemeinten Hinweise, dass man mit jedem Smartphone auch bequem E-Mails an mich schreiben kann, wurde mir vorgeworfen, ich sei doch total von gestern, und niemand nutze mehr E-Mail, schon gar nicht auf dem Smartphone. Ich begann zu zweifeln, abwechselnd an mir und am Verstand meiner IT-fernen Mitmenschen.

In den Monaten darauf verfolgte ich gespannt die Berichterstattung über die datenschutztechnisch äußerst bedenkliche Messenger-App. Das fängt schon damit an, dass die Entwickler nicht einen Finger krumm machen, wenn man sie darauf hinweist, dass die Nachrichten unverschlüsselt versendet werden. Probleme werden dort lieber verheimlicht und totgeschwiegen als die Nutzer aufzuklären. Dass WhatsApp das gesamte Adressbuch im Klartext an deren Server überträgt, um die Kontaktliste abzugleichen, das mag sein größtes Feature sein, aber gleichzeitig auch das größte Problem, denn vielleicht will das nicht jeder. Vielleicht vor allem die Leute nicht, die in diesen Adressbüchern stehen. Kleiner Denkanstoß: Wenn ich als WhatsApp-Verweigerer in den Smartphone-Adressbüchern von 30 WhatsApp-Nutzern stehe, und man davon ausgehen kann, dass Menschen die sich kennen sich in der Regel gegenseitig in ihr Adressbuch eintragen, dann kann WhatsApp ohne Schwierigkeiten ziemlich genaue Rückschlüsse darüber ziehen, wer so alles in meinem Adressbuch stehen wird. WhatsApp kennt mich längst, ich muss dafür nicht einmal einen Account anlegen. Bei Facebook wird das ähnlich funktionieren.

Ich fühlte mich in meiner Abwehrhaltung gegen WhatsApp bestätigt. Jetzt wollte ich erst recht nicht mehr dabei sein, obwohl ich regelmäßig gefragt wurde, ob ich nicht doch aus Gründen der Einfachheit mitmachen wollte. Manchmal bekam ich zur Belohnung für mein Sicherheitsbewusstsein ein genervtes Augenrollen oder ein ungläubiges Kopfschütteln. “Ich schreibe schon lange keine SMS mehr.”, erzählte mir eine Freundin, die mir damit wohl androhen wollte, dass ich ohne WhatsApp von ihr niemals Textnachrichten bekäme. WhatsApp-Fans schließen die anderen schon wie selbstverständlich aus, der gesellschaftliche Druck steigt. Wenn du nicht drin bist, bist du weg.

Aber um die Wahrheit zu sagen, suche ich eigentlich schon lange wieder nach einem brauchbaren Instant Messenger, der sowohl mobil als auch am Schreibtisch nutzbar ist. Am besten einen, der viele Nutzer hat, und der nicht Facebook oder WhatsApp heißt. Am besten einen, der Nachrichten richtig verschlüsselt. Interessiert bemerkte ich dieser Tage den Eindruck einer leichten Abwanderungsbewegung weg von WhatsApp, als Reaktion auf die Übernahmemeldung. Eine Kombination aus Schadenfreude, geballter Berichterstattung und dem Bedürfnis nach Kommunikation machte mich auf Threema aufmerksam. Threema ist das bessere, sicherere und weniger amerikanische WhatsApp. Drei Gründe, die mir 1,60 EUR allemal wert waren, und seitdem gehöre ich zu den Nutzern. Die Konkurrenz zu unterstützen, gibt mir außerdem ein gutes Gefühl.

Sicherlich, meine Kontaktliste ist mit zwei Personen in den ersten 24 Stunden nicht besonders gut gefüllt. Ich habe keine Wunder erwartet, aber ich bin zuversichtlich, dass sich das schnell ändert, und das ohne mein gesamtes Adressbuch an die Betreiber zu verschicken. Aber selbst wenn ich das wollte, würden nur Hashes dort abgelegt, was in jedem Fall besser ist, als das was der unverdiente Platzhirsch macht. Wenn es bald noch einen brauchbaren Desktop-Client für das Protokoll gibt, dann werde ich bestimmt eine Weile dabei bleiben. Nützlich ist so ein Messenger in jedem Fall, vorausgesetzt eine nicht unerhebliche Menge deiner Freunde ist darüber erreichbar. Da hilft vermutlich nur abwarten. Und wenn aus Threema am Ende doch nichts wird, installiere ich mir WhatsApp trotzdem nicht.

Windows

Der Windows-Papierkorb verliert Dateien

4

papierkorbDa meint man, man sei nach fast 20 Jahren Erfahrung im Umgang mit den verschiedensten Windows-Problemen, -Fehlern und -Eigenarten mittlerweile nicht mehr zu überraschen, und doch stellt sich heraus, dass man sich da ziemlich irren kann. Jemand aus der IT-Fachwelt, der freiwillig von sich behauptet, privat und beruflich Windows zu verwenden, setzt sich ja schon genug dem Spott und der Kritik aus, da müsste man seinen Mitmenschen eigentlich nicht auch noch selbst den Salzstreuer in die Hand drücken. Aber genau das mache ich.

Nicht ausschließlich auf eigener Hardware, aber dennoch intensiv genug, begleiten mich Microsofts Betriebssysteme seit Windows 3.1 bis heute einschließlich Windows 7. Ich habe viele Fehlermeldungen gesehen, viele Bluescreens verdaut, erheblichen Datenverlust überstanden, unzählige Workarounds gefunden, erfunden, und mich über die Jahre und Jahrzehnte damit abgefunden, dass es manchmal einfach abstürzen muss. Inzwischen stürzt es ja sogar schon fast nicht mehr ab. Ja, Linux ist die Zukunft. Linux ist perfekt. Linux habe ich in meinem Studium oft genug abstürzen gesehen. Nicht immer ist das Gras auf der anderen Seite grüner. Ich verstehe die Windows-Kritiker ja. Aber irgendwie fehlt bei mir noch der nötige Funke, der mich zum Wechseln bringt. Ich bin (noch) ganz zufrieden in meiner proprietären Fensterwelt. Windows 8 könnte das freilich ändern.

Ich lasse es mir trotzdem nicht nehmen, über das Betriebssystem meiner Wahl zu schimpfen, wenn mir mal wieder etwas passiert, das mich zum Kopfschütteln bringt. So wie gestern, als ich einer Sache nachgehen wollte, die mir einige Monate zuvor schon begegnet ist. Es muss während eines Live-Scan meiner Festplatten durch den Virenscanner gewesen sein, ich kann mich nicht mehr so genau erinnern. Jedenfalls sah ich mir das beinahe hypnotische Fortschrittsfenster aus mir inzwischen nicht mehr bekannten Gründen eine Weile konzentriert an, als mir auffiel, wie er einige Dateien aus dem Verzeichnis C:\$Recycle.bin, also dem Papierkorb, durchsuchte. Es waren ziemlich viele Dateien, deren Herkunft ich sofort erkannte: Dateien, die zu einem Spiel gehörten, das ich längst deinstalliert hatte.

Mein erster Instinkt war es, den Papierkorb zu leeren – doch er war augenscheinlich leer. Als nächstes setzte ich eine Command-Shell auf das Verzeichnis an, und ließ mir sogar unsichtbare und Systemdateien anzeigen, denn man ist ja kein Anfänger. Oder vielleicht doch, denn meine Suche brachte nichts zu Tage. Das mussten wohl Geisterdateien sein, oder ich war vielleicht einfach übermüdet und hatte mich verlesen. Windows wird mich schon nicht verarschen. Gestern also erinnerte ich mich wieder an das alte Problem, und ich wollte diesmal sogleich das Internet-Orakel der NSA in dieser Sache befragen. Meine Recherche dauerte keine zwei Minuten. Dass der Papierkorb von Windows hin und wieder Dateien “verliert”, ist gar nicht so unwahrscheinlich, wie es aussieht. Es scheint zu helfen, wenn man den Ordner komplett von der Festplatte tilgt, der für die Papierkorb-Funktion reserviert ist:

rd /s /q C:\$Recycle.bin

Dieser Befehl muss mit Administratorrechten ausgeführt werden. Das geht am einfachsten über Start -> (Alle Programme) -> Zubehör -> Eingabeaufforderung (Rechtsklick -> Als Administrator ausführen), oder man legt sich dafür eine eigene Verknüpfung an. Damit löscht man den Ordner und sämtlichen Inhalt, egal ob Verzeichnis oder Datei. Keine Sorge, Windows ist sofort in der Lage, das Verzeichnis neu anzulegen, wenn es vermisst wird. Obwohl mein Betriebssystem mir via Kontextmenü hoch und heilig versprach, dass der Papierkorb total leer sei, hatte ich auf einen Schlag – man höre und staune – 10 GB mehr frei als zuvor. Echt jetzt! 10 GB an Datenmüll, der bei meiner über vier Jahre alten Windows-Installation offenbar irgendwie hinter den Papierkorb gefallen sein muss, so dass nur noch der Virenscanner darauf Zugriff hatte. Wer lustig ist, kann denselben Befehl gerne auch auf seine anderen Festplatten anwenden (Laufwerksbuchstabe ersetzen), denn auch dort konnte ich das eine oder andere versunkene Gigabyte aus der Tiefe des Datenmeeres heben und seinem gerechten Schicksal zuführen.

Ach Windows, erneut hat deine Glaubwürdigkeit bei mir sehr gelitten. Wenn ich mich schon nicht darauf verlassen kann, dass du meine Dateien endgültig vernichtest, so muss ich doch annehmen, dass du sie etwa für die Geheimdienste zwischenspeicherst, denn schließlich geht es ja um Microsoft.

spacolabooks_sidebar

SPACOLA Eclipse WIP 0.29 Preview-Video

0

Leider nicht ganz pünktlich zum dreijährigen Geburtstag von SuccessDenied.com, der diesmal ein wenig im Stillen gefeiert wurde, hier nun nach beinahe zweiwöchiger artikelloser Phase das versprochene WIP-Preview-Video der neuesten Version meines Java-Remakes: SPACOLA Eclipse WIP 0.29. Ich muss hier allerdings wieder einmal betonen, dass YouTube das Originalvideo nach dem Upload unnötigerweise in matschige Videogrütze verwandelt hat(*). Und die niedrige Framerate des Videos repräsentiert in keinster Weise die eigentlich sehr weichen Bewegungen des Spiels. Um das einmal in Zahlen auszudrücken: Das Video hat eine Framerate von etwa 26 fps, das Spiel läuft aber mit 52 fps, also exakt doppelt soviele Bilder. Den Unterschied sieht man.

Drei Jahre SuccessDenied heißt bei aller Sektstimmung aber auch, dass ich seit bald drei Jahren an dem noch lange nicht fertigen Spiel arbeite, aber das ist für mich kein Problem, denn dafür investiere ich als einziger Entwickler eben zuwenig Zeit. Auch die kommenden zwei bis drei Monate sieht es relativ unrosig aus, denn ich muss mich um viele Dinge kümmern, die ich lange aufgeschoben habe. Ich werde den Quellcode nur noch gelegentlich mal anrühren. Aber spätestens nächstes Jahr lege ich wieder richtig los.

Das Video demonstriert so einige Aspekte, die ich in den letzten Monaten fertiggestellt habe: Wüst ballernde Gegner, die Animation des zerstörten Spielerschiffes, das neue Cheatmenü, Geschwindigkeitswarnungen, herumfliegende Waren, schiffbrüchige Piraten, echte Highscore, Kontoabrechnungen, die Kurzanleitung, einen echten Pausemodus, das Anhalten der Game-Engine (mit TOS-Bomben), und dass man Soundeffekte, Ingame-Musik und Partikeleffekte jederzeit ein- und ausschalten kann. An den wichtigen Stellen im Video habe ich Kommentare eingeblendet, damit man nichts verpasst. Auch ist das Video mit seinen stolzen zehn Minuten leider nicht so knapp geraten, wie ich das ursprünglich wollte. Wer seine Zeit als zu kostbar erachtet, dem sei gesagt, dass ab der Hälfte des Videos nicht mehr wirklich viel neues gezeigt wird. Es geht dann nur noch um Details.

Da ich kein Held im Umgang mit Videoschnittsoftware bin, habe ich das Video relativ schnell zusammengeklickt, ohne Rücksicht auf qualitativ hohe Ansprüche. Es ist nur eine kleine Demonstration des aktuellen Entwicklungsstands. Kommentare sind gern gesehen und Fragen jederzeit gestattet. Die Projektseite des Spiels werde ich in Kürze aktualisieren.

Das nächste Preview-Video wird es frühestens wieder in einem Jahr geben, da ich, wie bereits erwähnt, vorerst nicht mehr dazu kommen werde, neue Features umzusetzen. Aber es geht definitiv weiter.

(*) Nachtrag: Jetzt ist die Qualität des Videos auf einmal besser geworden, dabei habe ich nichts verändert. YouTube stinkt manchmal einfach, dagegen kann man wenig machen. Die verteilen wohl hin und wieder einen Stream mit schlechterer Qualität, wenn die Bandbreite als zu gering eingeschätzt wird.

Windows

Manchmal ist Windows eben doch großer Mist

4

Alles trieft, alles klebt, die Affenhitze hat Deutschland fest im Griff, und wochenlang gibt es keinen einzigen Tropfen Regen, der die Qual ein wenig lindern würde. Während ich bei bestimmt 40 Grad unterm Dach vor mich hin transpiriere und es seit letztem Monat kaum terminfreie Tage gab, versuche ich im Umzugsstress meinen Blog nicht komplett zu vernachlässigen, auch wenn ich dafür nur noch zwischen Tür und Angel mal die Möglichkeit habe. Aber es kommen wieder bessere Tage, dafür garantiere ich. Die Gelegenheit ist günstig für einen Füllbeitrag zum Thema “Warum Windows manchmal eben doch großer Mist ist”. Hier habe ich zwei skurrile Dinge gesammelt, die mir beim Arbeiten (oder Zocken) mit Windows sinnlos Probleme bereitet haben.

Fangen wir mit dem größten Übel an: Ein Problem mit Windows Server 2003, das scheinbar schon so manchem die Schuhe beim Gedanken daran auszieht. Ich wollte einen gerade unter Windows laufenden Java-Prozess mit Hilfe des Tools jstack.exe untersuchen. Üblicherweise ist das gar kein Problem, man muss eben nur Process-ID wissen, und die erfährt man mit dem tollen Windows-Befehl tasklist. Soweit alles noch in Ordnung. Als ich dann aber jstack mit besagtem Parameter ausführen wollte, erhielt ich diese völlig nichtssagende weil absurd falsche Fehlermeldung: “Not enough storage is available to process this command.” (im deutschen Windows “Nicht genügend Server-Speicherplatz verfügbar, um diesen Befehl zu verarbeiten“).

Einwandfrei. Nicht genügend Arbeitsspeicher bzw. Swap-Speicher für die winzige jstack.exe auf einem eigentlich gut ausgestatteten Windows-Server? Nein, ich glaube eher nicht. Aber danke für deine unbrauchbare Hilfe, Windows! Ich fand eine Microsoft-Hilfeseite, die versucht das Problem näher zu erläutern und Problemlösungen zu bieten. Mit Betonung auf “versucht”, weil Microsoft grandios daran scheitert, denn schon die Fehlermeldung an sich ist einfach Quatsch. Auch eine deutsche Hilfeseite führte mit ihren Anweisungen nur komplett in die Irre.

Zum Glück kannte jemand auf Stackoverflow.com die Lösung. Man muss jstack mit Hilfe von “psexec -s jstack.exe pid” aufrufen, damit es richtig auf dem Zielrechner ausgeführt wird. Das hat also genau gar nichts mit zuwenig Speicherplatz o.ä. zu tun, wie Windows mir weismachen wollte. Wenn man noch nicht einmal die richtige Fehlermeldung angezeigt bekommt, wenn schon ein Fehler auftritt, dann weiß ich nicht, worauf ich mich bei Windows sonst noch verlassen können soll.

Das zweite Problem ist dagegen ein eher kleines, kürzlich entdeckt und gelöst auf einer LAN-Party, also einem gesellschaftlichen Event zum gemeinschaftlichen Zocken netzwerkfähiger Windows-Spiele. Besonders nervtötend ist es, wenn das Windows-Netzwerk an sich fehlerfrei eingerichtet ist, es aber dennoch vereinzelt Spiele gibt, in denen immer derselbe LAN-Teilnehmer (=ich) die Spiele der anderen nicht sehen kann, und umgekehrt. Die Liste in der Lobby ist leer, obwohl alle anderen bereits dem offenen Spiel beigetreten sind. Man sucht sich also einen Wolf, auf der Suche nach dem einen Fehler, der dafür sorgt, dass man in manchen Spielen für alle anderen unsichtbar ist. Die Fehlersuche wird allein dadurch erschwert, dass das Problem nur manche Spiele betrifft, und auch dann noch nicht einmal immer.

lanadapterDas Problem wäre natürlich gar keines, wenn man in solchen Spielen einfach eine Ziel-IP zum Verbinden eingeben könnte, aber so einfach machen es einem die Entwickler nicht. Könnte womöglich manche Spieler überfordern. Des Rätsels Lösung lag dann in der Existenz weiterer LAN-Adapter, die unter Windows installiert waren: darunter der VirtualBox-LAN-Adapter, Tunngle, bei anderen findet man dort etwa Hamachi oder VMware. Alle diese Adapter müssten – auch wenn sie im Moment nicht benutzt werden – explizit deaktiviert werden, weil die Spiele sonst in Versuchung kommen könnten, diese für die Netzwerkverbindung mit den anderen Spielern zu verwenden, anstelle des eigentlich höher priorisierten richtigen LAN-Adapters.

Kinderspielzeug

Ein kurzer Blick auf Windows 8

4

Kürzlich saß ich mit einem Kollegen zusammen, der mir stolz sein neues Windows-8-betriebenes Notebook zeigen wollte. Bis zu jenem Zeitpunkt hatte ich dieses (für mich relativ uninteressante) Betriebssystem von Microsoft noch nie zu sehen bekommen. Aber ich dachte da so bei mir: Der Kollege versteht nicht viel von PCs, Windows 8 dürfte genau das richtige für ihn sein, weil es ja so benutzerfreundlich ist, und überhaupt.

windows8Der Desktop sieht ja sogar ganz schick aus, und die Sounds gefallen mir auch, aber Metro mit seinen schmucklosen Kacheln wirkt doch sehr rustikal, so wie ich das auch von Screenshots kannte. Ich ließ den Kollegen einfach mal machen, was ihm scheinbar anfangs auch ganz gut gelang, während ich stumm die Oberfläche betrachtete.

Wir wollten im Internet diverse Angebote suchen, und damit es nicht gar so still beim Surfen würde, suchte er auf seiner externen Festplatte ein paar Musikdateien, wovon er eine mit einem beherzten Doppelklick aus dem Explorer startete. Es öffnete sich der Windows Media Player im Vollbildmodus, mit irgendeiner unglaublich lahmen Visualisierung, die ein bisschen aussah wie ein Bildschirmschoner aus den 80ern. Da war ich doch schon Spannenderes von Microsoft gewohnt. Wie dem auch sei, so interessant war die Oberfläche des Media Player nun wirklich nicht, dass wir den auf einem Breitbild-Display unbedingt im Vollbild hätten sehen wollen. So hetzte und klickte der Kollege relativ hilflos mit der Maus auf dem Bildschirm herum, fegte quer durch alle Bildschirmecken, auf der abenteuerlichen Suche nach dem Desktop. Nach einigen erfolglosen Versuchen kommentierte er das Geschehen bereits mit den ersten abfälligen Kommentaren über Windows 8. Ich gab mir Mühe nicht zu lachen.

Besonders viel helfen konnte ich ihm da schon nicht, da ich Windows 8 nicht nutze, aber immerhin entdeckte ich irgendwann in einer Ecke eine Verknüpfung zum Startmenü, und von dort gelangte man über eine Kachel wieder auf den Desktop. Ein Glück: Die Musik dudelte im Hintergrund weiter. Schnell wollte der Kollege mir noch ein paar Fotos zeigen, die er gespeichert hatte. Also via Desktop dorthin navigiert und das erste Foto im Ordner mit einem Doppelklick geöffnet. Das Foto öffnete sich wie erwartet im Vollbild. Wird jetzt etwa doch noch alles gut?

Witzig wurde es erst, als der Kollege mir die anderen Fotos aus dem Ordner zeigen wollte. Er suchte also mit der Maus nach irgendwelchen Pfeilen für die Ordnernavigation Links und Rechts, um durch die Bilder zu schalten. Einen Pfeil fanden wir, allerdings nur für Links, keinen für Rechts. Ein Klick darauf bestätigte die Vermutung, dass der Pfeil eine andere Bedeutung hat. Ich empfahl ihm, doch mal die Pfeiltasten auf der Tastatur zu probieren, weil das bei vielen Programmen funktioniert. Es bewegte sich leider nichts. So fuchtelte er also wieder mit der Maus in allen möglichen Ecken nach einer Diashow-Funktion oder etwas ähnlichem, aber wir fanden nichts. Also zurück zu den Kacheln, und von dort zurück zum Desktop, das nächste Foto mit einem Doppelklick ausgewählt. Dann wieder raus, zurück auf den Desktop, nächstes Foto. Schon beim vierten Mal war uns das eindeutig zu blöd. Mein nächster Tipp war es, doch einfach mal alle Fotos in dem Ordner zu markieren und auf die Selektion mit der rechten Maustaste zu klicken: Da musste es doch eine Diashow-Funktion im Kontextmenü geben, oder?

Fehlanzeige. Bevor wir uns sinnlos weiter mit Windows 8 herumärgerten, schlossen wir seine externe Festplatte an seine alte Kiste mit Windows XP an, dort ging das alles ganz mühelos. Erstaunlich wie Windows 8 beim Thema Intuitivität – wo es doch soviel Wert darauf legt – auf ganzer Linie versagt. Ein Betriebssystem für Rentner, Kinder und DAUs, und dennoch gelang es uns nicht, vernünftig damit zu arbeiten.

Ich bin nach diesem furchtbaren ersten Eindruck froh, dass ich mir Windows 8 nicht aufgehalst habe. Das ist wirklich nichts für mich, dafür ist mir der klassische Desktop und das Startmenü zu wichtig. Für Tablets mag das ja die Offenbarung sein, aber doch nicht am Desktop-PC oder am Notebook.

Java

Java-Kram: Nächstmöglicher Zeitpunkt zu fester Uhrzeit

0

Willkommen zu meinem nächsten Beitrag direkt aus meinem Fundus merkwürdiger Java-Lösungen für nicht ganz so alltägliche Programmierprobleme. Normalerweise würde ich meine kreativen Fehltritte sicher NIE veröffentlichen, aber dieses Mal mache ich noch eine Ausnahme, da ich glaube, es könnte den einen oder anderen auf die richtige Spur bringen, wenn er nicht weiter weiß.

Kürzlich war ich dabei, einen kleinen Indexer für dies und das zu schreiben, der einmal am Tag zu einer bestimmten Tageszeit Datensätze aus einer Datenbank zieht. Wofür genau spielt hier natürlich keine Rolle. Jedenfalls wollte ich dafür einen TimerTask verwenden, und der wird beispielsweise mit einem Delay (Verzögerung in Millisekunden bis zum ersten Start), und einem Intervall (Verzögerung in Millisekunden für alle darauffolgenden Starts) gefüttert. Randbedingung war, dass der Indexer einmal am Tag um dieselbe Uhrzeit läuft. Diese Uhrzeit soll man hinterlegen können. Den TimerTask-Kram habe ich weggelassen, und den eigentlichen Indexer-Code auch, um das Beispiel möglichst auf das Essentielle zu reduzieren.

Mein Problem war nämlich, dass ich auf Anhieb nicht wusste, wie ich herausfinden könnte, wann der nächstmögliche Zeitpunkt für eine festgelegte Uhrzeit ist, also ob beispielsweise 14:30 Uhr noch am selben Tag ist, oder erst am darauffolgenden Tag. Wieviele Millisekunden muss ich als Verzögerung des initialen Starts angeben, damit der Indexer zur nächsten Gelegenheit um eine bestimmte Uhrzeit losläuft?

public int[] timeToNextIndexTask(){
		
	int indexHour = 14;
	int indexMinute = 30;
		
	GregorianCalendar now = new GregorianCalendar();
		
	boolean carryHour = false;
		
	int hourOfTheDay = now.get(Calendar.HOUR_OF_DAY);
	int minuteOfTheDay = now.get(Calendar.MINUTE);

	int hoursUntil = hourOfTheDay - indexHour;
	int minutesUntil = indexMinute - minuteOfTheDay;

	if(minutesUntil < 0){
		carryHour = true;
		minutesUntil = 60 + minutesUntil;
	}
		
	// Next scheduled index still today?
	if(hoursUntil < 0)
		hoursUntil = Math.abs(hoursUntil);
	// Next scheduled index tomorrow?
	else if(hoursUntil >= 0)
		hoursUntil = 24 - hoursUntil;
		
	// Remove one hour if there are minutes left to the hour
	if(carryHour)
		hoursUntil--;
		
	if(minutesUntil != 0 && hoursUntil == 24)
		hoursUntil = 0;
		
	return new int[]{hoursUntil, minutesUntil};

}

Nach einer Weile habe ich mir die obige Lösung für mein simples Problem auserdacht. Die Methode timeToNextIndexTask() gibt einen int-Array zurück, der die Zeit in Stunden und Minuten beinhaltet. Das lässt sich ohne Schwierigkeiten in Millisekunden umrechnen.

Aber wie das so ist, fällt einem schon kurze Zeit später auf, wie sinnlos man sich den Kopf darüber zerbrochen hat, und dass diese Lösung zwar funktioniert, aber eigentlich viel zu aufwändig und der Code ziemlich wackelig ist. Meine Frage lässt sich mit zwei GregorianCalendar-Objekten sehr einfach beantworten:

public int[] timeToNextIndexTask(){
	
	long minuteMilliseconds = 60 * 1000;
	long hourMilliseconds = minuteMilliseconds * 60;
		
	int indexHour = 14;
	int indexMinute = 30;
		
	GregorianCalendar now = new GregorianCalendar();
	GregorianCalendar nextTime = new GregorianCalendar();
	nextTime.set(Calendar.HOUR_OF_DAY, indexHour);
	nextTime.set(Calendar.MINUTE, indexMinute);
		
	if(now.after(nextTime))
		nextTime.add(Calendar.DAY_OF_MONTH, 1);
		
	long millisecondDiff = nextTime.getTimeInMillis() - now.getTimeInMillis();
		
	int hoursUntil = (int) (millisecondDiff / hourMilliseconds);
	millisecondDiff -= hoursUntil * hourMilliseconds;
	int minutesUntil = (int) (millisecondDiff / minuteMilliseconds);
		
	return new int[]{hoursUntil, minutesUntil};
		
}

Kurzgesagt, man legt einen GregorianCalender für den aktuellen Zeitpunkt an, und verstellt einfach die Uhrzeit, behält das Datum jedoch bei. Nun muss man lediglich mit Hilfe der Methode after() bzw. before() vergleichen, ob das verstellte Calendar-Objekt in der Vergangenheit oder in der Zukunft liegt. Falls es in der Vergangenheit liegt, muss man einen Tag dazuzählen, und schon hat man seinen gewünschten Zeitpunkt.

spacolabooks_sidebar

Spacola Eclipse WIP v0.25: Still a long way to go

0

Mein treuester “Spacola Eclipse”-Fan hat sich soeben bei mir erkundigt, wie es denn mittlerweile um mein kleines Remake steht. Wie es der Zufall wollte, konnte es kaum einen besseren Zeitpunkt geben, mich das zu fragen. Nach mehreren Wochen fauler Abstinenz gelang es mir gestern und heute tatsächlich für ein paar Stunden einige Dinge am Code zu ändern und Kleinigkeiten von der To-Do-Liste zu streichen. Zeit für mich, meinen ereignislosen Blog mit Dev-News zu füttern.

spacolabrechnungAuf der linken Seite kann man dazu eine Abbildung sehen. Was auf den ersten Blick wie zweimal exakt derselbe Screenshot aussieht, ist in Wirklichkeit eine Gegenüberstellung von Original (oben) und Remake (unten). Ja genau, dieser kleine Aspekt hat mich bestimmt drei Stunden meines Lebens und so einige Nerven gekostet. Es handelt sich im Spiel um den Teil der “Kontoabrechnung”, also die Grafik, die man zu sehen bekommt, sobald man einen Level erfolgreich beendet hat. Hier werden jeweils gelieferte Waren in bare Münze umgerechnet und anschließend kann man schon den nächsten Level beginnen.

Es waren die vielen kleinen Dinge, die die Arbeit so langwierig machen. Pixelgenaue Abstände, Schriftzeilenhöhe, richtige Zentrierung, originalgetreues Timing, Sounds, HUD-Events während der Animation (Highscore!), sukzessives Entfernen der Sprites aus dem Inventar, dabei gleichzeitiges Hochzählen des Punktestands. Und nein, ich habe nicht einfach nur eine große Grafik eingebunden, alles wird dynamisch gezeichnet. Die Unterschiede sind marginal, aber sie sind (leider) da.

Falls sich jemand wundert, wieso auf dem unteren Screenshot das Abrechnungsergebnis nicht mit dem tatsächlichen Score übereinstimmt: Die Berechnung ist leider noch hartkodiert. Ein Fake, ein Test, nur zum Vergleichen. Alles andere ist echt.

Die zweite größere Neuerung ist, dass die Highscore jetzt vollständig in eine Datei gespeichert und beim nächsten Spielstart auch von dort wieder ausgelesen wird. Jetzt fehlt eigentlich “nur” noch der Dialog zur Eingabe des Namens, dann wäre auch der ganze Highscore-Kram fix und fertig. Aber den Spaß hebe ich mir vermutlich doch für ein anderes Mal auf.

Bereits mit Version 0.23 kam der zweite Gegnertyp hinzu, der zwar komplett eigenständige Sprites hat, sich aber (Copy & Paste sei dank) fast genauso verhält wie der erste Gegnertyp. Ist im Moment eben noch work in progress. Außerdem gibt es jetzt die Geschwindigkeitsstufen für Hyperspeed und natürlich “Ridiculous Speed” in Anlehnung an den Filmklassiker Spaceballs. Anfang April habe ich noch die komplette Vektorarithmetik zusammengefasst, umgeschrieben und in eine eigene Klasse ausgelagert. Damit habe ich drei Dinge erreicht: 1.: eine konsistente Implementierung der Bewegung von Spielobjekten. 2.: jede Menge überflüssiger oder redundanter Code, der jetzt rausgeflogen ist. 3.: um die 20 Klassen mussten angepasst werden, damit der Code seit der Änderung wieder kompilierbar wurde.

Achja, wir haben jetzt Ingame-Musik und die lässt sich in der Konfiguration sogar an- und abschalten. Der Song ist zwar nicht optimal, aber er ist so ziemlich der passendste, den ich bisher finden konnte. Ich werde da mal noch weitersuchen. Zuletzt kann ich noch erwähnen, dass die Raketentriebwerke der Piratenschiffe jetzt auch Partikel sprühen, wenn sie Schub geben. Das sieht deutlich wuseliger aus als noch in der letzten Version. Vor einigen Wochen hatte ich mal ein neues Preview-Video angekündigt. Ich denke, ich werde meine Ankündigung daher etwas relativieren und mit dem Video warten, bis es wieder spektakuläre Änderungen gibt.

Nachtrag vom 02.06.: Heute war ich ebenfalls ein bisschen fleißig: Der Spieler kann jetzt mit aktiviertem Schildgenerator von gegnerischen Schiffen abprallen (so wie bei Asteroiden bisher schon) oder sich von den Piraten bestehlen lassen, wenn er ohne Schild unterwegs ist. Allerdings fehlt den Piraten noch die nötige Intelligenz um das Diebesgut auch abzuliefern. Wenn der Spieler keine Ware mehr im Inventar hat, kann er den Level jetzt nicht mehr beenden. Mal sehen, vielleicht kümmere ich mich heute noch darum, dass die Gegner auch zurückfeuern können.

Nachtrag vom Nachtrag: Keine drei Stunden später ist es dann soweit: Die Gegner können jetzt aus allen Rohren zurückballern. Und als Spieler muss man sich ganz schön in Acht nehmen. Das macht das Gameplay nun tatsächlich um einiges hektischer als zuvor. Vor allem aber macht es das Gameplay um einiges sinnvoller, denn so nähert sich das Spiel langsam einem ansatzweise vorzeige- und spielbaren Zustand. Hurra!

spacolabooks_sidebar

Spacola Eclipse WIP v0.22

0

Das erste Update im neuen Jahr zum aktuellen Entwicklungsfortschritt meiner SPACOLA-Neuimplementation. Im Moment habe ich einen guten Lauf und kann fast täglich immer mal wieder ein bisschen an meinem kleinen Spielewerk arbeiten. Das muss genutzt werden, solange es noch anhält, denn so wie ich mich kenne, wird das nämlich die letzte Meldung in der kommenden Zeit sein. Die neueste WIP-Version enthält rund 50 Änderungen. Eigentlich hätten es noch einige mehr sein müssen, denn meine ToDo-Liste quillt inzwischen über, doch letzten Endes muss man irgendwann mal einen Cut machen. Hier also das Ergebnis der letzten Tage in visueller Form:

spacolaeclipse022

Richtig erkannt. Das HUD auf der rechten Seite ist komplett fertig und dort gibt es so einige Informationen abzulesen. Soweit möglich, habe ich alles wie im Original beibehalten. Was rausgeflogen ist, ist die Angabe zur Buchseite, der Galaxie und des Sonnensystems, denn diese Angaben werden künftig nicht mehr nötig sein. Dafür ist eine neue Anzeige hinzugekommen, die dem Spieler den Weg weist. Also genau das, was er vorher aus dem Buch ablesen musste. Entsprechend habe ich mir die Freiheit genommen, die Symbole in der Anzeige etwas anzupassen, um diesen Umstand hervorzuheben.

Eine weitere große Baustelle ist somit endlich abgeschlossen. Ein wichtiger Stützpfeiler des Original-Spielegrundgerüsts ist in langwieriger Handarbeit aufgestellt worden. Man fühlt sich manchmal wie eine Art Restaurateur für antike Uhren oder sowas. Pixel für Pixel muss das Original fein säuberlich zerlegt und untersucht und dann im Remake detailgetreu nachgebildet werden. Am Gameplay hat sich freilich wieder einmal wenig getan, denn darum werde ich mich wahrscheinlich erst kümmern, wenn alle übrigen Grundfunktionen von SPACOLA übertragen sind.

Außerdem hinzugekommen ist ein deutlich umfangreicheres und besseres Logging mit Logdatei, es gibt Statusmeldungen (z.B. für Schilde, Highscore und die diversen Geschwindigkeitslevels), es gibt Punkte für zerstörte Gegner sowie einen richtigen Punktestand. Entsprechend habe ich die Fake-Highscore-Liste durch eine richtige Highscore ersetzt, die nun dynamisch im Spiel generiert und verändert werden kann. Die Introschleife arbeitet nun korrekt und exakt so wie im Original. Zuvor wurde das Intro einfach immer wieder von vorne abgespielt. Es gibt jetzt Events, z.B. Extraleben, neuer Highscore, oder die Shield-Shutdown-Warnung. Zuletzt habe ich den Algorithmus für den Wurmloch-Effekt (Level-Intro), den ich mir damals selbst ausgedacht habe, durch einen mathematisch “korrekteren” Algorithmus ersetzt, der auch viel einfacher funktioniert (Stichwort: logarithmische Spirale). Thank you internets!

58 Klassendateien, 9 Pakete, über 6100 Nettocodezeilen (SLOC), 574 Funktionen, 146 Bilddateien, 24 Audiodateien, zusammengepackt in ein 4,0 MB Archiv. So langsam nimmt das kleine Spaßprojekt, das ich angefangen habe ohne zu wissen, ob ich morgen überhaupt noch darauf Lust habe, fast schon Ausmaße an, die einen Rückzieher unmöglich machen. Es wäre inzwischen irgendwie zu schade, wenn ich das Projekt nun nicht zuende führen würde. Was als ödes Fenster mit einem Sprite in der Mitte und ein paar Pixelsternen außenrum begonnen hat, hat sich zu etwas entwickelt, was sich schon ein bisschen wie SPACOLA auf dem Atari ST spielt.

Java

Not so weekly rant: Wieso läuft die JVM nicht?

0

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

nach oben