Resourcenverwaltung im Standard Widget Tool (SWT)

Warum Ressourcen verwalten?

Das Betriebssystem stellt jeder Applikation eine endliche Menge an sogenannten “Handles” zur Verfügung. Diese Handles sind Referenzen auf Systemressourcen. Bei der Entwicklung einer Applikation können Objekte instanziiert werden, die auf diese Handles zugreifen. Sie werden solange reserviert bis sie von der Applikation wieder freigegeben werden. Passiert dies nicht, werden Systemressourcen blockiert, die erst nach dem Neustart des Computers wieder zur Verfügung stehen. Dieser Zustand wird als «Ressourcenleck» bezeichnet. Ist die Menge an Ressourcen, die der Applikation zur Verfügung stehen, vor dem Herunterfahren des Computers aufgebraucht, so steigt die Applikation mit einer «Out of Handles» Fehlermeldung aus. Um diesen Zustand zu vermeiden, ist es wichtig das Konzepte der Ressourcenverwaltung im Standard Widget Toolkit zu verstehen und anzuwenden.

If you created it, you dispose it

Die Architekten vom SWT haben die Entscheidung getroffen, das neue Ressourcen nur über den Konstruktor initialisierbar sind. Das Konzept der Architekten folgt der Regel: Wenn du es erstellt hast, musst du es wieder freigeben. Fast alle Instanzen die von der Klasse org.eclipse.swt.graphics.Resource abgeleitet sind, müssen über die dispose Methode wieder freigegeben werden. Ausgenommen sind unter anderem die Rectangle- und die Point-Klasse. Das folgende Beispiel erstellt eine Font-Ressource und gibt sie in der nächsten Zeile wieder frei:

// the one and only way to create a new resource is to call the constructor
Font font = new Font(Display.getCurrent(), new FontData( "Arial", 10, SWT.BOLD ));

// if you forget to call the dispose method, you have created a resource leak
font.dispose();

Der Konstruktor erwartet als ersten Parameter ein Display-Objekt, welches die Schnittstelle zwischen dem SWT und dem Betriebssystem ist. Dieses Objekt hält u.a. Information über die Systemressourcen. Der nachfolgende Parameter definiert die Eigenschaften des Resource-Objekts. Der zweite Methodenauruf gibt den Speicher wieder frei. Dieser Aufruf sollte erst erfolgen, sobald das Objekt nicht mehr verwendet wird.
Analog zur Regel gilt: Wenn du es nicht erstellt hast, dann gib es auch nicht frei. Das folgende Beispiel greift auf eine vorhandene Font-Ressource zu:

// you will get the default font from the OS
Font font = Display.getDefault().getSystemFont();

// prints the name of the font
System.out.println(font.getFontData()[0].getName());

In diesem Beispiel wird das Font-Objekt genutzt, welches beim initialisieren des Device-Objekts erstellt wurde. Das Device-Objekt ist die Elternklasse des Display-Objekts und erbt dadurch die Eigenschaften.

Um die Verwaltung von Resource-Objekten zu vereinfachen, kann der JFace Resource Manager verwendet werden.

JFace Resource Manager

Der Resource Manager vereinfacht und optimiert die Verwaltung von Images, Font und Color-Objekten. Jedes Objekt, welches über den Resource Manager erstellt wird, wird in der jeweiligen Registry angemeldet. Diese prüft, ob das Objekt bereits erstellt wurde und liefert die Referenz auf das Objekt zurück. Jede Referenz wird mitgezählt und das Objekt bleibt solange erhalten bis keine Referenz auf das Objekt verweist. Dies hat den Vorteil, das Systemressourcen eingespart werden. Das folgende Beispiel zeigt die Verwendung des Resource Managers:

// create a new ResourceManager instance to add resources
ResourceManager resourceManager =  new
LocalResourceManager(JFaceResources.getResources(), parent);

// the descriptor holds the font data and gives some useful methods
FontDescriptor fontDescriptor = FontDescriptor.createFrom("Arial", 10, SWT.BOLD);

// create the font
Font font = resourceManager.createFont(fontDescriptor);

Von der JFaceResources.getResources()- Methode erhält man den ResourceManager des aktuellen Display-Objekts. Der zweite Parameter ist ein Control-Objekt. Auf dieses Objekt wird ein DisposeListener registriert, um die ResourceManager-Instanz freizugeben, sobald das Control-Objekt freigegeben wird. Dadurch werden die allokierten Resource-Objekte, die über diesen ResourceManager erstellt wurden, freigegeben. Ohne den zweiten Parameter muss die dispose-Methode des ResourceManagers aufgerufen werden.
Als nächstes wird eine FontDescriptor-Objekt erstellt, welches ein existierende Font des Betriebssystems beschreiben sollte. Über dieses Objekt kann der ResourceManager den Font erstellen.
Resourcen die über den ResourceManager erstellt wurden, in diesem Beispiel das Font-Objekt, sollten nicht vorzeitig freigegeben werden, da eine Runtime-Exception geworfen wird und die Applikation nicht weiter verwendet werden kann!

Disposing the parent disposes the children

Die erste Oberfläche im Standard Widget Toolkit ist ein Fenster, welches im Code das Shell-Objekt repräsentiert. Jedes Objekt das etwas auf dieser Oberfläche darstellt, verwendet dieses Shell-Objekt als Elternelement (direkt oder indirekt). So entsteht eine Baumstruktur mit der Bedingung, dass jedes Kindelement abhängig ist vom Elternelement. Sobald das Wurzelelement, also das Fenster geschlossen wird, werden automatisch alle Kindelemente freigegeben.

Erweiterung zu Regel:

  • Beim freigeben der MenuItem-Instanz, wird das Untermenü mit dem Stylebit SWT.CASCADE mit freigegeben.
  • Beim freigeben der Control-Instanz, wird das Pop-Up Menü, welches über die setMenu-Methode gesetzt wurde, mit freigegeben.

Links und Quellen

Managing Operating System Resources

Eclipse Documentation – JFace

Eclipse Documentation – SWT

chevron_left
chevron_right

Join the conversation

comment 1 comment
  • Barcelone

    Many thanks a whole lot for sharing! I will definitely be back.

Leave a comment

Your email address will not be published. Required fields are marked *

Comment
Name
Email
Website

This site uses Akismet to reduce spam. Learn how your comment data is processed.