Category: HowTos

Stuff that was hard to find & fix

  • How to create Memory Leaks by using Inner Classes.

    The most recent Java Specialists Newsletter finally convinced me to start this post that I was having in mind for quite some time.

    One of the really huge advantages of Java is that you almost do not have to care about cleaning up your memory as the Garbage Collector usually does this for you as soon as Objects are no more referenced. Usually this works really really well so that you really don’t have to care about annything! But maybe once in a while you may be observing something like a memory leak. Some people then call the Garbage explicitly – which is usually just a bad idea and possibly also doesn’t help either so that the “leak” remains. The better solution in this case would be profiling so that you can see why some classes are not cleaned up.

    A nice source for memory leaks can be the use of anonymous inner classes. Assume the following class where you want to compute s.th and return a Result-Object which derives from an Interface:

    interface Result{}
    class Outer {
        int[] data = null;
        public Outer(int s) { data = new int[s]; }
        Object getResult() { return new Result(){}; }
    }

    So if you call new Outer(1).getResult(), you will still have an instance of Outer in memory even though you did not keep an explicit reference. As explained in the Java Specialists Newsletter, each instance of an anoymous inner class always keeps a reference to the outer class! This is not a big deal as long as

    • you don’t keep a lot of data in the Outer instance or
    • if the lifetime of the Result object is not long or
    • if you won’t create a lot of results anyways.

    Let’s have an example. If you execute

    ArrayList l = new ArrayList();
    int i = 0;
    while(true){
        l.add(new Outer(0).getResult());
        System.out.println(i++);
    }

    with the above classes without memory constraints (-Xmx), this will run for quite some time because you are only holding 2 class references (Outer, Result) 1 field (the emtpty data array) and an implicit reference from Result to Outer. Which makes a total of 48 bytes on my Win7 64bit machine (according to this measurement).

    Now change the parameter in the constructor of Outer from 0 to 100000 and execute the code again. In my case I am getting an OutOfMemoryException after a bit more than 2000 created instances as now suddenly each iteration consumes 400.048 bytes (48 bytes as before + 100.000*4 bytes for the int-array) even though we only keep the explicit reference to the Result objects!

    So – if you are creating an inner class the next time – you might have a brief look at the outer class as well and think about memory consumption and lifetime.

  • MARiO: Multi Attribute Routing in Open Street Map

    Yeah, I got a new Publication accepted at Symposium on Spatial and Temporal Databases (SSTD) 2011 that is dealing with OpenStreetMap Data (using the JXMapKit and JXMapViewer).

    MARiO: Multi Attribute Routing in Open Street Map

    Franz Graf, Hans-Peter Kriegel, Matthias Schubert, Matthias Renz

    Published at Symposium on Spatial and Temporal Databases (SSTD) 2011
    Conference Date: August 24th – 26th, 2011
    Conference Location: Minneapolis, MN, USA.

    Abstract:

    In recent years, the Open Street Map (OSM) project collected a large repository of spatial network data containing a rich variety of information about traffic lights, road types, points of interest etc.. Formally, this network can be described as a multi-attribute graph, i.e. a graph considering multiple attributes when describing the traversal of an edge. In this demo, we present our framework for Multi Attribute Routing in Open Street Map (MARiO). MARiO includes methods for preprocessing OSM data by deriving attribute information and integrating additional data from external sources. There are several routing algorithms already available and additional methods can be easily added by using a plugin mechanism. Since routing in a multi-attribute environment often results in large sets of potentially interesting routes, our graphical fronted allows various views to interactively explore query results.

    Documents:

    Bibtex

    @INPROCEEDINGS{GraKriRenSch11,
      AUTHOR      = {F. Graf and H.-P. Kriegel and M. Renz and M. Schubert},
      TITLE       = {{MARiO}: Multi Attribute Routing in Open Street Map},
      BOOKTITLE   = {Proceedings of the 12th International Symposium on Spatial and Temporal Databases (SSTD), Minneapolis, MN, USA},
      YEAR        = {2011}
    }
  • Performanceanalyse mit JVisualVM – evil synchronized

    In einem meiner kleinen Projekte werden an einer Stelle etliche Threads gestartet, die jeweils ein Bild einlesen, skalieren und wieder auf die Platte schreiben. – Die ganze Zeit hat mich schon das Gefühl beschlichen, dass das zu langsam läuft, untersucht hatte ich das bisher nur nie. Nachdem genau diese Funktionalität heute definitv zu langsam war, kam ich um eine Analyse wohl doch nicht mehr herum. Also erst mal untersuchen, was da vor sich geht:

    • Programm gestartet,
    • JVisualVM gestartet (zu finden im bin-Verzeichnis einer JDK-Installation),
    • VisualVM auf das laufende Programm verbunden, und die Threads anzeigen lassen
    • kritische Funktion im Programm gestartet

    Und siehe da: die Threads werden gestartet, aber nur immer genau einer ausgeführt (siehe Bild). Alle anderen Threads die laufen sollten stehen auf “Monitor”. Das ist leicht daran zu erkennen, dass zwar alle PictureScaleWorker ausgeführt werden, aber niemals gleichzeitig alle grün (also im Running State) sind sondern immer nur einer. Na das sollte ja nicht so sein!

    Aber was machen die eigentlich und worauf warten die? Also erst mal einen Thread Dump erstellen (Button oben rechts), vielleicht bringt der ja ein paar Infos:

    Dann zu einem der betreffenden Threads scrollen und nachsehen, ob dort etwas auffällig ist.

    Thread.State: BLOCKED (on object monitor)
    at de.locked.gallery.utils.ImageUtils.read (ImageUtils.java:83)

    Blocked on object monitor – das sieht nach einem synchronized aus. Und betreffende Zeile 83 ist tatsächlich synchronized – was ich bei einem der letzten Refactorings offenbar übersehen habe. Mittlerweile ist die Synchronisierung auf dieser Methode zum Glück nicht mehr nötig und ich kann die Einschränkung ohne Gewissenbisse entfernen. Und siehe da, auf einmal laufen auch alle Threads gleichzeitig, was auf 8 Kernen doch einen spürbaren Unterschied macht. – Willkommen im Multi-Core Zeitalter.

    Ohne die JVisualVM wäre ich früher oder später wohl auch an die Stelle gekommen – aber ich bezweifle ernsthaft dass ich die Stelle innerhalb weniger Minuten gefunden hätte.

    Dazu auch ein interessantes Video.

  • Selektionsfenster in SwingX-WS / JXMapKit

    Um in der Mapkomponente von JXMapKit eine Selektion (Rechteck mit Rahmen und leicht transparenter Füllung) zu zeichnen, wird lediglich ein entsprechender Painter und ein Mouseadapter benötigt. Der Code dazu sieht folgendermaßen aus:

    Der Painter & MouseListener:

    public class SelectionPainter extends MouseAdapter implements Painter<JXMapViewer> {
    
        private Rectangle rect, start, end;
        private Color borderColor = new Color(0, 0, 200);
        private Color regionColor = new Color(0, 0, 200, 75);
    
        public SelectionPainter() {
        }
    
        @Override
        public void mousePressed(MouseEvent e) {
            if (e.getButton() != MouseEvent.BUTTON1) {
                rect = null;
                start = null;
            } else {
                start = new Rectangle(e.getPoint());
                ((JXMapViewer) e.getSource()).setPanEnabled(false);
            }
        }
    
        @Override
        public void mouseDragged(MouseEvent e) {
            if (start != null) {
                end = new Rectangle(e.getPoint());
                rect = start.union(end);
            }
            ((JXMapViewer) e.getSource()).repaint();
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
            if (start == null) {
                return;
            }
            end = new Rectangle(e.getPoint());
            rect = start.union(end);
            ((JXMapViewer) e.getSource()).setPanEnabled(true);
            ((JXMapViewer) e.getSource()).repaint();
        }
    
        @Override
        public void paint(Graphics2D gd, JXMapViewer t, int i, int i1) {
            if (rect != null) {
                gd.setColor(regionColor);
                gd.fillRect(rect.x, rect.y, rect.width, rect.height);
                gd.setColor(borderColor);
                gd.drawRect(rect.x, rect.y, rect.width, rect.height);
            }
        }
    }

    Verbindung zur Map-Komponente:

     SelectionPainter sp = new SelectionPainter();
    mapKit.getMainMap().addMouseListener(sp);
    mapKit.getMainMap().addMouseMotionListener(sp);
    mapKit.getMainMap().setOverlayPainter(sp);

    mapKit ist dabei eine Instanz von org.jdesktop.swingx.JXMapKit.

    Artikel mit gepatchtem SwingX-WS

  • GoogleMail: Dateianhänge aus E-Mails löschen

    Google ist der Meinung, dass es unnötig sei Anhänge/Attachments aus eMails zu löschen. Dummerweise bin ich anderer Meinung. Trotz mittlerweile mehr als 7.5 GB potentiellem Speicherplatz bei Google Mail, will ich nicht jeden Mist an den Mails kleben lassen.

    Da ich per IMAP und Thunderbird auf meine Mails zugreife, kann ich die Anhänge wenigstens im Thunderbird löschen. Gesagt getan – nur wird der belegte Speicher dadurch nicht weniger sondern mehr. Das Problem ist, dass bei jedem Löschen eines Anhangs, eine Kopie der Nachricht (inklusive dem Anhang!) im Ordner “Alle Nachrichten” verbleibt und zusätzlich eine Mail ohne Anhang erstellt wird.

    Die Lösung ist folgendermaßen:

    • Thunderbird per IMAP mit Google verbinden (Anleitung von Google)
    • Die unerwünschten Anhänge löschen – dabei werden unerwünschte Mailduplikate erstellt.
    • Das Thunderbird Addon Remove Duplicate Messages installieren und so konfigurieren:
    • Extras > Add-ons > “Remove Duplicate Messages” Einstellungen > Lösche bevorzugt “größere” E-Mail
    • Anhänge löschen nicht vergessen (z.B. den Ordner “Alle Nachrichten” nach Größe sortieren und dann die Mails durchsehen)
    • Rechts Klick auf den Ordner “Alle Nachrichten” > “Doppelte Nachrichten entfernen”
    • Dort noch schnell die Ausgabe kontrollieren, bestätigen und fertig.

    Die gelöschten Duplikate sollten jetzt im Papierkorb sein, den man bei Bedarf noch löschen kann. Kurz darauf sollte man die Änderung auch in der GoogleMail Oberfläche sehen.

  • Epson Perfection 1240U mit Windows7 64bit und Windows 10

    Epson stellt für den relativ alten Scanner “Epson Perfection 1240U” (aus dem Jahr 2001) keine 64bit Treiber für Windows 7 oder Windows 10 bereit.

    Anstatt einen neuen Scanner zu kaufen scheint es mindestens 3 Lösungen zu geben:

    Kauf zusätzlicher Software (bei Win 7)

    1. Die Empfehlung von Epson ist, die Software VueScan von Hamrick zuinstallieren. Vorteil: es geht! Nachteil: Die Software kostet ca. 30€
    2. In einem Windows 7-Forum wird ein modifizierter Treiber zum Download angeboten. Aber ehrlich gesagt habe ich Skrupel irgendwelche modifizierten Treiber aus nicht absolut vertrauenswürdigen Quellen zu installieren.
    3. Einen original Epson-Treiber eines anderen Scanners verwenden. Der Tip kommt übrigens aus dem selben Forum – da ich den Beitrag in einigen Monaten / Jahren nicht mehr wiederfinden werde, wenn ich es brauche: hier nochmal eine Beschreibung:

    Epson Perfection 1240U mit Windows7 64bit:

    1. Scanner abstecken
    2. Epson Perfection 2400 Treiber für Windows 7 von Epson runterladen (EPSON Scan 3.0.4 vom 17. Juli 2009 / 20,68 MB)  Download
    3. Treiber installieren
    4. Scanner anstecken (findet keine Treiber)
    5. Start > Systemsteuerung > Gerätemanager: dort sollte jetzt ein neues Gerät mit gelbem Icon sein (der Scanner)
    6. Rechtsklick > Eigenschaften > Treiber > Treiber aktualisieren
    7. “Auf dem Computer nach Treibersoftware suchen”
    8. “Aus einer Liste von Gerätetreibern auf dem Computer Auswählen” > “Bildverarbeitungsgeräte”
    9. Hersteller: Epson, Modell: Epson Perfection 2400 auswählen und bestätigen

    Mit IrvanView kann man nun scannen!

    Zeitaufwand: minimal

    Epson Perfection 1240U mit Windows10

    Ich habe den Scanner mittlerweile entsorgt, aber er scheint auch unter Windows 10 noch seinen Dienst zu tun. Wie mir in einem Kommentar mitgeteilt wurde könnte es ungefähr wie folgt gehen:

    1. Start
    2. Einstellungen
    3. Geräte unter „Verwandte Einstellungen“ (rechts unten) „Geräte und Drucker“ auswählen.
    4. Den Scanner auswählen (Windows 10 schlägt erst mal nur vor das Gerät zu entfernen, da kein passender Treiber verfügbar ist.)
    5. Rechtsklick > Eigenschaften
    6. Hardware > Eigenschaften
    7. Einstellungen ändern > Treiber > Treiber aktualisieren.
  • TeXnicCenter: PDF vor Compilierung schließen

    Sollte TeXnicCenter einen Fehler melden wie “Beim Öffnen dieses Dokuments ist ein Fehler aufgetreten”, liegt es evtl. daran, dass das PDF noch offen ist.

    TeXnicCenter-Ausgabeprofile
    TeXnicCenter-Ausgabeprofile

    Zum automatischen Schließen des PDFs definiert man das “LaTeX => PDF”-Profil derart (siehe Screenshot rechts):

    1. Ausgabe > Ausgabeprofile definieren > Profil links wählen, rechts den Reiter  “Viewer”
    2. Projektausgabe betrachten: [x] DDE Komando, Kommando: [DocOpen(“%bm.pdf”)], Server: acroview, Thema: control
    3. Suche in Ausgabe: [x] DDE Komando, Kommando: [DocOpen(“%bm.pdf”)], Server: acroview, Thema: control
    4. Vor Compilierung Ausgabe schließen: [x] DDE Komando, Kommando: [DocClose(“%bm.pdf”)], Server: acroview, Thema: control

    Alternativ kann man sich eine der folgenden Profile runterladen und importieren. Einmal mit und einmal ohne die Pfade zu Acrobat.

    “Latex => PDF”-Profil ohne Pfad (sollte bei den meisten funktionieren)
    “Latex => PDF”-Profil mit Pfad (wird nicht funktionieren, falls Acrobat nicht im exakt selben Verzeichnis wie bei mir installiert ist)

    Links zum Thema:

  • PAROS download!

    Das Ziel war nobel: Code aufräumen, schöner machen, refactoren und dokumentieren und dann online stellen.

    Die Realität war derart, dass es leider wichtigeres zu tun gibt. Daher stelle ich das PAROS-Projekt, das dieses Jahr auf der SIGMOD war so online wie es ist: lauffähig, und vom Softwareengineeringaspekt ziemlich hässlich. Aber vielleicht kann ja jemand etwas damit anfangen – zumindest die kleinen hacks um größere Graphen auch annehmbar schnell zeichnen zu können.

    Ausserdem ist es ein schönes Beispiel, wie man JXMapKit und OpenStreetMap (OSM) zu Forschungszwecken im Bereich Datamining, GIS (GeoInformationssysteme) und auch SpatialIndexing  verwenden kann. Auf der Konferenz kannten viele OSM nämlich erstaunlicherweise gar nicht, obwohl sie auf dem Bereich tätig waren.

    Und zur nächsten Version muss ich nochmal nachsehen, ob es nach den Google Maps Terms of Services  immernoch verboten ist, Maps in Nicht-Browser-Anwendungen zu integrieren. Wäre natürlich auch sehr nett, oder weiß jemand Bescheid? (Update Jan. 2011: das ist nicht mehr verboten!)

    Relevante Links: