Thema der Woche: Paketierung mit <fx:deploy>

Seit Neustem kann man mit Java auch ausführbare Dateien bzw. Installer bauen. Ließ dazu http://docs.oracle.com/javafx/2/deployment/self-contained-packaging.htm bzw. suche nach weiterer Dokumentation im Netz.

  • Teste das an einer eigenen kleinen Hello-World-Anwendung.
  • Wie groß ist das Ergebnis mit JRE?
  • Welche Zielformate sind möglich und kann man alle etwa auf einem Linux-Build-Server bauen?
  • Nutze log4j und nimm die Jar mit in das Zielformat mit auf. Lassen sich auch native Dateien einbinden?
  • Gilt diese Möglichkeit nur für JavaFX oder auch für für AWT/Swing oder SWT?

Java 8 könnte auf 18. März 2014 verschoben werden, wäre dann aber “Der Profi”

Bisher Vorschläge!

  • http://mail.openjdk.java.net/pipermail/jdk8-dev/2013-April/002336.html
  • http://mreinhold.org/blog/secure-the-train
  •   2013/05/09  M7  Feature Complete
      2013/07/18      Rampdown start
      2013/09/05  M8  Developer Preview
      2013/09/12      All Tests Run
      2013/10/10      API/Interface Freeze
      2013/10/24      Zero Bug Bounce
      2013/11/21      Rampdown phase 2
      2014/01/23  M9  Final Release Candidate
      2014/03/18  GA  General Availability

    Der 18.03. ist bestimmt kein Zufall, denn Luc Besson hat Geburtstag, und der ist uns ja in Erinnerung mit dem 1994er Klassiker “Der Profi”mit Jean Reno (nicht der mit Jean-Paul Belmondo, der war 1981). Damit wird Java 8 bestimmt auch so ein Profi im Bereich Sicherheit (naja, der Profi stirbt am Ende), sodass wir alle sagen können “Hier wird es uns gut gehen, Java”.

    Java 9 kommt dann in der ersten Hälfte von 2016. Oder irgendwann.

    Buchkritik: Wicked Cool Java: Code Bits, Open-Source Libraries, and Project Ideas

    Brian Eubanks; ISBN-10: 1593270615; No Starch Press; 15.11.2005; 248 Seiten
    Mit dem Buch hat Brian eigentlich das gemacht, was sich jeder Autor wünscht: sich hinzusetzen und einfach mal im Artikelstil über alles zu schreiben, was einem interessiert, ohne darauf zu achten, ob das nützlich oder wichtig ist. Dafür nimmt er sich 8 Kapitel Zeit:
    Chapter 1: Java Language and Core API, Chapter 2: String Utilities, Chapter 3: Processing XML and HTML, Chapter 4: Crawling the Semantic Web, Chapter 5: Math and Science, Chapter 6: Graphics and Data Visualization, Chapter 7: Multimedia and Sychronization, Chapter 8: Fun, Integration and Project Ideas. Im Grunde ist nur das erste Kapitel ein kleines Einstiegskapitel, insbesondere in die Neuerungen von Java 5, und zusammen mit dem zweiten Kapitel haben sie die Java SE selbst zum Inhalt. Das Niveau ist an Anfang niedrig und passt nicht zum Rest. Syntaktisch ist nicht immer alles sauber, so gibt es immer wieder umständliche Feldinitialisierungen wie int[] theList = new int[]{2,3,5,7}; oder java.util.Random random = new Random(); wo ich mich Frage, ob der Autor dort gerade wach war. Dann wird assert geklammert wie eine Methodenaufruf, das ist aber nur in C so, nicht in Java, wo assert ein Schlüsselwort ist und der Ausdruck nicht geklammert wird. (Macht Krüger im Buch aber leider auch so.) Leider sind auch nicht alle Beispiele konsequent auf Java 5 ausgelegt, immer wieder findet sich der Raw-Type etwa von Datenstrukturen, bei seinen verketten Listen-Implementierung oder mit verketteten Knoten wiederum fehlt ein Generic, hier steht nur Object content. An anderer Stelle im Buch gibt es den Hinweis, das ein Listing mit Generics auf der Buchseite (http://www.wickedcooljava.com/) ist, warum nicht gleich im Code? Mit Generics scheint Brian auch noch nicht so vertraut zu sein, anders kann ich mir nicht erklären, warum er eine Methode removeMatches(List<Number> aList) schreibt, denn man muss verstehen, da man so etwas nicht zum Beispiel mit einer List<Double> aufrufen kann; eleganter wäre ein Typ-Bound er Art List<? extends Number> hin. Weiter: Statt StringBuilder kommt noch StringBuffer zum Einsatz. Nicht gut gefällt mir auch der Bezug auf konkrete Klasse, statt Basistypen, etwa bei ArrayList<String> getNames(), hier würde als Rückgabe auch List oder Collection reichen. (In dem gleichen Beispiel ist auch unglücklich den Scanner auch nicht im finally zu schließen. Und getFloat() statt getDouble() zu nehmen ist auch Geschmackssache.) Bei den Farben verwendet der Autor noch die klein geschriebenen Namen also Color.blue statt Color.BLUE. Sehr geschwätzig ist auch if ( … ) { return true; } else { return false; } — das ist uncool.
    Im Mittelpunkt des Buches geht es um wilde Open-Source Bibliotheken, etwa für mathematische Operationen, Textanalyse, Suche (nicht wild), semantische Netze, RDF, MIDI-Sounds. Eigentlich nichts, was man wirklich/dringend/oft bräuchte, und wenn, würde man vermutlich in ein spezielles Buch schauen. Positiv ist anzumerken, dass uns der Autor die Libs vorstellt und des Lesers Horizont erweitert. Ein Probekapitel gibt es nicht online, allerdings unter http://www.wickedcooljava.com/related.jsp eine Linkliste der Bibliotheken. April 2013

    Assertions feiner aktivieren oder deaktivieren

    Assertions müssen nicht global für das ganze Programm gesetzt werden, sondern könne auch feiner deklariert werden, etwa für eine Klasse oder ein Paket. Mit geschickter Variation von –ea (Assertions aktivieren) und –da (Assertions desaktivieren) lässt seht gut steuern, was die Laufzeitumgebung prüfen soll.

    Beispiel

    Aktiviere Assertions für die Klasse com.tutego.App:

    $ java -ea:com.tutego.App AppWithMain

    Aktiviere Assertions für das Default-Paket (dafür stehen die drei Punkte):

    $ java -ea:… AppWithMain

    Aktiviere Assertions für das Paket com.tutego inklusive aller Unterpakete (auch dafür stehen drei Punkte):

    $ java -ea:com.tutego… AppWithMain

    Aktiviere Assertions für das Paket com.tutego inklusive aller Unterpakete, aber desaktiviere sie für die Klasse App in dem Paket com.tutego:

    $ java -ea:com.tutego… -da:com.tutego.App AppWithMain

    Assertions müssen Nebeneffekt frei sein

    Assertions stehen immer in der Klassendatei, da sie der Compiler immer in Bytecode abbildet. Die JVM ignoriert Assertions standardmäßig bei der Ausführung und eine Aktivierung erfolgt nur auf Befehl; ein Ablauf ohne Bedingungstests ist also der Normalfall. Daraus folgt, dass Ausdrücke in den assert-Anweisungen ohne Nebeneffekte sein müssen. So etwas wie

    assert counter– == 0;

    ist keine gute Idee, denn das Vermindern der Variablen ist ein Nebeneffekt, der nur dann stattfindet, wenn die JVM auch Assertions aktiviert hat. Allerdings lässt sich das auch für einen Trick nutzen, Assertions bei der Ausführung zu erzwingen. Im statischen Initialisierer einer Klasse können wir setzen:

    boolean assertEnabled = false;

    assert assertEnabled = true;

    if ( ! assertEnabled )

      throw new RuntimeException( "Assertions müssen aktiviert werden" );

    Mein Abendvortrag “Java 8 Features” in Braunschweig am 13. Juni

    Java User Group Ostfalen

    CKC
    13 Am Alten Bahnhof
    38122 Braunschweig
    Deutschland

    Donnerstag, 13. Juni 2013, von 19:00 bis 22:00 (MESZ)

     

    Christian Ullenboom gibt in seinem Abendvortrag einen Einblick in die Neuerungen von Java 8, angefangen von statischen Schnittstellenmethoden über Default-Methoden, Lambda-Ausdrücken, Annotationen-Ergänzungen bis zu den Erweiterungen der Standard-Bibliothek. In der gemütlichen Diskussionsrunde im Anschluss gibt es keine Denkverbote und es darf auch über Plagiate, Flughäfen in großen Städten, ausgefüllte Dirndl offen und frei gesprochen werden.

     

    Referent:

    Presenter.build().name( "Christian Ullenboom" ).born( 1973 ).studied( "Diplom-Informatik" )
    .cameToJava( "im ‘Ruck’-Jahr 1997" )
    .knownFor( "Java-Blog", URI.create( "http://javainselblog.tutego.de" ) )
    .autored( "Java ist auch eine Insel" ).autored( "Java – mehr als eine Insel" )
    .orElse( "Den Rest des Tages verbringt er mit seiner Liebe" )
    .orElse( "Erweiterung des Schulungsunternehmens tutego", URI.create( "http://tutego.de/" ) )
    .orElse( "alten Computern/Videospielkonsolen", URI.create( "http://RetroBu.de/" ) ).done();

    Thema der Woche: Etwas Design mit UML

    DRUG LORD (http://www.old-games.com/download/5218/druglord) ist ein Spielklassiker für DOS von 1993. Mit Kauf- und Verkauf von Drogen in verschiedenen Städten muss man möglichst viel Geld verdienen.

    5218-5-druglord

    Bild © old-games.com

    Überlege, wie das Spiel in seinem Grundzügen (nur Kauf/Verkauf von Drogen, Orte und Cash aber kein Hospital/Health, keine Waffen, Bank, Schulden) objektorientiert modelliert werden kann. Nutzte UML-Diagramme zur Darstellung. Das Programm soll am Ende lauffähig sein, die Darstellung kann beliebig sein. (Wer das Retro-Feeling mag, kann http://sourceforge.net/projects/javacurses/ ausprobieren.)

    Mit Java für C64 entwickeln

    Knackige Überschrift, was steckt dahinter? Wir warten auf den Architekten für unser Restaurant hier in den Philippinen und so hatte ich etwas Leerlauf, um was total Unnötiges zu programmieren.

    Um Java-Programme, beziehungsweise eine Teilmenge der Sprache/Bibliothek, auf dem C64 (oder anderen 8-Bit-Computern zum Laufen zu bringen), sind mehrere Ansätze denkbar:

    • Eine JVM auf dem Heimcomputer, die Bytecode interpretiert. Das würde im Prinzip gehen, es gibt auch Mini-Laufzeitumgebungen für so etwas. Auch Java Smart Card ist ein Stichwort.
    • Compiler, die entweder Bytecode oder Source-Code in ein Quellformat umsetzen, was der 65xx versteht.

    Ein JVM ist richtig viel Arbeit, und war in 2 Tagen nicht zu schaffen. Und mit http://sourceforge.net/projects/vm02/ gibt es so etwas auch schon für Apple II Computer. Ein (Cross-)Compiler ist deutlicher einfacher. Bytecode in 65xx-Assembler zu übersetzen ist relativ einfach, doch dann müsste ich wieder Assembler anfassen und damit das ganze schnell wird, müsste ich auch einen Code-Optimierer schreiben, denn einfach die Stack-Maschine umzusetzen, führt auch zu keinen Performance-Wundern. Da es für den C64 auch Compiler gibt, etwa für PASCAL (auf der Maschine) oder C (als Cross-Compiler etwa mit CC65), kann man aus Bytecode auch dieses Format generieren. Aber dann hätte ich wieder mit Java-Bytecode arbeiten müssen, was mir auch keine Freunde macht. Am Schnellsten verspricht Resultate eine Code-Transformation von Java nach C. Das Resultat kann dann der http://www.cc65.org/ in Maschinencode umsetzen, und dann bekommt man auch ein paar Optimierung geschenkt.

    Das JDK bringt alles mit, um an den AST des Compilers zu kommen, wie schon im Blog hier beschrieben: http://www.tutego.de/blog/javainsel/2012/07/mit-der-internen-compiler-api-auf-den-ast-einer-klasse-zugreifen/. Von den erkannten Elementen (Ausdrücke, Variablenzugriff, Schleife, …) muss man nur C-Code schreiben und fertig ist. Um mir die Sache einfach zu machen vereinfache ich Java jedoch massiv:

    • kein float/double/long/boolean
    • kein new, keine Klassen, Stellen und sonstiges objektorientiertes “Zeugs”, das dranhängt, wie enum, erweitertes for, nur statische Methoden, keine Ausnahmen, Keine String-Konkatenation
    • String-Literale können verwendet werden, allerdings nur von 0×0000 – 0x00FF (256) und eigentlich geht PETSCII nur von 0-191
    • Nichts von der Java-Bibliothek

    Des weiteren muss sehr “C”-ähnlich programmiert werden:

    • Alle lokale Variablen müssen am Anfang einer Methode deklariert sein
    • Alle Bezeichner müssen für den C-Compiler gültig sein, keine Unicodes
    • Die Reihenfolge muss stimmen, der Umsetzer erzeugt keine Prototypen
    • Eine main()-Methode muss etwas zurückgeben in C99, Java macht das nicht, daher nutzt man System.exit(0).

    Das auf diese Weise kastrierte Java ist zwar im Prinzip für nix mehr zu gebrauchen, aber für Heimcomputer immer noch akzeptabel und eine nette Spielerei.

    Wer bis dahin noch nicht das Interesse verloren hat, kann ein wenig mit dem Compiler spielen; die Source liegen unter https://code.google.com/p/java2c-transcompiler/.

    Jetzt brauchen wir Input:

    import static j2c.lib.Stdio.printf;
    
    // Source: http://skoe.de/wiki/doku.php?id=ckurs:04-abend4
    public class Application
    {
      public static char istPrimzahl( int n )
      {
        int divisor;
        int testEnde = n / 2;
    
        /* Alle potentiellen Teiler bis zur Mitte testen */
        for ( divisor = 3; divisor < testEnde; divisor += 2 ) {
          /* Mit Rest 0 teilbar? */
          if ( n % divisor == 0 ) {
            /* Ueberprüfung abbrechen, keine Primzahl */
            return 0;
          }
        }
    
        /* Kein Test durchgefallen, ist eine Primzahl */
        return 1;
      }
    
      public static void main( String[] args )
      {
        int zahl;
    
        /* Von 3 beginnend jede zweite Zahl testen, bis unter 1000 */
        for ( zahl = 3; zahl < 1000; zahl += 2 ) {
          if ( istPrimzahl( zahl ) != 0 ) {
            printf( "Primzahl: %u\n", zahl );
          }
        }
    
        System.exit( 0 );
      }
    }

    Für die C-Funktionen (http://www.cc65.org/doc/funcref.html) gibt es eine paar statische Imports und native Platzhalter:

    package j2c.lib;
    
    // http://www.cplusplus.com/reference/cstdio/
    
    public class Stdio
    {
      /**
       * Print formatted data to stdout.
       * <code>int printf ( const char * format, ... );</code>
       * @param format
       * @param args
       * @return
       */
      native public static int printf( String format, Object... args );
    }

    Das setzt der Compiler im Grunde 1:1 so um. Es lohnt sich das Eclipse CDT unter http://download.eclipse.org/tools/cdt/releases/juno zu installieren, damit die syntaktische Hervorhebung funktioniert (den CC65 Compiler einbinden könnten wir hier NICHT). Nach einer CDT-Neuformatierung ergibt sich:

    #include <stdio.h>
    #include <stdlib.h>
    #include <peekpoke.h>
    #include <c64.h>
    #include <conio.h>
    /* CLASS Application { */
    char istPrimzahl(int n) {
        int divisor;
        int testEnde = n / 2;
        for (divisor = 3; divisor < testEnde; divisor += 2) {
            if (n % divisor == 0) {
                return 0;
            }
        }
        return 1;
    }
    int main(void) {
        int zahl;
        for (zahl = 3; zahl < 1000; zahl += 2) {
            if (istPrimzahl(zahl) != 0) {
                printf("Primzahl: %u\n", zahl);
            }
        }
        return 0;
    }
    /* END CLASS } */

    Um das Compilat zu Erzeugen muss nun der cc65 installiert werden. Unter ftp://ftp.musoftware.de/pub/uz/cc65/ lädt man die für Windows etwa die 1.3 MB große EXE und installiert. Die Eintragungen in den Path kann man vornehmen, nach der Installation folgt dann mit dem kleinen Test:

    C:\..>cc65

    cc65.exe: No input files

    Kappt also.

    Das Ganze soll im Emulator laufen, hier ist WinVICE gut: http://www.viceteam.org/#download.

    Eine Batch-Datei bindet alles zusammen, also Java –> C, Compilieren und im VICE starten:

    set JAVA_HOME="C:\Program Files\Java\jdk1.7.0"
    %JAVA_HOME%\bin\java -cp bin/;%JAVA_HOME%\lib\tools.jar j2c.J2CC65 src/java/Application.java > app.c
    del app.prg
    cl65 -o app.prg app.c
    "C:\Program Files\WinVICE-2.2-x64\x64.exe" app.prg

    Und das Ergebnis sieht so aus:

    image

    Hat jmd. Lust das weiter zu entwickeln? Schreibt mir eine E-Mail.