Die Sprachänderungen für Java 7 nun fest

Das schreibt Joseph D. Darcy in seinem Blog http://blogs.sun.com/darcy/entry/project_coin_final_five (und bei Java.net http://weblogs.java.net/blog/forax/archive/2009/08/29/seven-small-languages-changes-will-be-jdk7).
Die Spezifikationen stehen im Einzelnen noch nicht fest.

Raus sind erst einmal
und auch alle anderen Dinge.

Das alles erscheint mir schon mehr merkwürdig in der Auswahl. Improved Exception Handling for Java war so ein heißer Kandidat und wird es nun doch nicht.

Deadline ist Ende Oktober.

Labels:

Beta 1 von Hibernate 3.5 mit JPA 2.0

Steve Ebersole schreibt auf seinem Blog http://in.relation.to/12153.lace dazu:

This is the first release towards supporting JPA 2. Most of the APIs are implemented. Some know limitations for this beta include:

  • Some of the 'metamodel' APIs are still unimplemented, specifically differentiating between declared attributes and attributes (same wording as java.lang.reflect). The getDeclaredXYZ methods simply return null in this release.
  • 'criteria' query building is fully implemented aside from defining subquery correlations, to the best of my knowledge and current state of the spec. However, compiling criteria queries is unimplemented scheduled for the next release.

Additionally, initial support for fetch profiles has been added in this release. Currently only join-fetching is supported as a strategy in fetch profiles.

The artifacts have all been published to the JBoss Maven repository. Additionally the release bundles have been uploaded to SourceForge.

This is also the first version bundling annotations, entitymanager and envers together with the other core modules. Moving forward all will be versioned and released together.

Labels:

Video mit Danny Coward über Java 7

Das Video gibt es bei Sun unter http://java.sun.com/developer/media/deepdivejdk7.jsp. Es zeigt die 5 Top-Features, die in Java 7 erwartet werden. Das Interview erwähnt noch das Swing Application Framework, was aber gestorben ist.

Labels:

Swing Application Framework fliegt aus Java 7 raus

Unter http://weblogs.java.net/blog/alexfromsun/archive/2009/08/saf_and_jdk7.html ist von Alexander Potochkin nun zu lesen:

After much discussion it's become clear that the Swing Application Framework API as it is today hasn't reached consensus and we feel still needs further design work done.

Since the SAF API was committed to milestone 5 of JDK7 and that time is already here, this date is now impossible, and we need to decommit SAF from any specific JDK 7 milestone

Labels: ,

Zusammenfassung der Änderungen von EJB 3.1 und JPA 2

  • Die lokale Schnittstelle (local view) einer lokalen Session Bean kann nun entfallen, da direkt die öffentlichen Methoden als Schnittstelle verwendet werden können. Eine lokale Session Bean muss daher keine Schnittstelle mehr implementieren, um injiziert zu werden und Methoden anzubieten.
  • EJBs müssen nicht mehr in einem EAR-Archiv verpackt sein, sondern können einfach in einem WAR deployed werden. Im Fall von WAR-Archiven liegen dann die Klassen unter WEB-INF/classes.
  • Mit der Annotation @Singleon lässt ein Singleton markieren, sodass sich eine Session Bean (die auch Business Schnittstellen implementieren kann) von unterschieden Stellen nutzen lässt, aber eben nur einmal in der JVM vorhanden ist.
  • Die Annotation @Startup ist ein Zusatz für @Singleton, um über das Hoch-/Runterfahren des Applikationsservers informiert zu werden. Die Callbackmethoden nutzen das bekannte @PostConstruct und @PreDestroy.
  • Der EntityManager erlaubt ein detach().
  • Embeddable's können in JPA 2.0 geschachtelt sein und Relationen eingehen.
  • Weitere Mappings bei JPA-Tabellen. Map-Keys können nun einfache Objekte, Entities und embedded Entities sein.
  • Bisher konnten etwa 1:n-Assoziationen immer nur Verweise auf Entity-Beans realisieren, aber keine Sammlungen etwa von Strings oder Datums-Objekten. Das ändert sich mit JPA 2.0, das Collections von Elementen erlaubt. Hier zieht JPA eine Collection-Table heran.
  • Die Entities im Persistence Context eines Entity-Managers sind in einem Cache, dem Level 1 Cache. Bei zwei Entity-Managern ist es implementierungsabhängig, wie zum Beispiel zwei gleiche Entity-Beans in den beiden EM gehalten werden. Das bestimmt ein Level 2 Cache. Dieser Level 2 Cache lässt sich über die Shared Cache API von JPA 2.0 rudimentär kontrollieren.
  • Mit einer @Version-Spalte erlaubt JPA 1.0 schon immer optimistisches Locking, allerdings nur optimistische Lese- oder Schreib-Sperren. Mit JPA 2.0 wird über die Enum LockMode nun Optimistisches und auch Pessimistisches Locking unterstützt.
  • Eine neue Criteria-API kommt in JPA 2.0 und damit neue Typen wie QueryBuilder, CriteriaQuery. Die API folgt dem Fluent-Interface Prinzip, etwa wie bei criteriaQuery.select(entity.get("id")).where(queryBuilder.cojunction(queryBuilder.equals(...), ...)).
  • JPA-QL kennt für Datumswerte nun auch Literale.
  • JPA-QL unterstützt polymorphe Anfragen der Art WHERE CLASS(e) = Klassenname.
  • JPA-QL ermöglicht CASE-Anfragen wie eine Fallunterscheidung.
  • JPA-QL erlaubt in der WHERE-Klausel Zugriff auf den Index einer Liste.

Labels:

VMware kauft SpringSource

Die Ankündigung von SpringSource liest sich so:

Together, VMware and SpringSource plan to further innovate and develop integrated Platform as a Service (PaaS) solutions that can be hosted at customer datacenters or at cloud service providers. These solutions will allow customers to rapidly build new enterprise and web applications and run and manage these applications in the same dynamic, scalable and cost-efficient vSphere-based internal or external clouds that can also host and manage their existing applications, providing an evolutionary path to the future.

Labels:

SmartGWT 1.2

Aus dem Blog http://www.jroller.com/sjivan/entry/smartgwt_1_2_released:

SmartGWT 1.2 has been released. I have added several new samples to the Showcase including a real world mini-application. The other new samples can be found under the "New Samples" side nav item.

This is a feature-complete production ready release. There are only around 20 enhancement requests and 20 low / medium priority issues in the SmartGWT tracker which I think is pretty telling for such a comprehensive library. I hope to get to them over the weeks to come.

Here are some of the key features of this release :

  • GWT 1.7 is fully supported and integration with GWT widgets has been improved significantly. Along with standard GWT widgets, you can now easily add Google Maps or even a Google Visualization Chart to your SmartGWT application
  • Hosted mode performance improvements
  • Fully implemented the highly requested ResultSet API.
  • ListGrid performance improvements
  • Full Support for Safari 4.x
  • Support for Grid editing with all cell editors active
  • Auto-loading of dependent XML schema for loadWSDL() and loadXMLSchema()
  • Extended WebService APIs to allow simplified input data and allow setting SOAP headers
  • Numerous enhancements. See the detailed API Changes document. Around 35 additional enhancements and bug fixes that were logged in tracker
  • Official Maven Repository
  • Enhancements to RPC Tab in Developer Console (shows component that initiated request, if applicable)

Looking ahead there are several exciting new features that are going to be in the next release. Deep level of customization of pretty much any widget is going to be supported. For example you'll be able to fully customize grid headers, provide your own widget implementation to use as a Tile in a TileGrid, or even customize pretty much any aspect of the Calendar component.

Labels: ,

NIO.2: Wahlfreier Zugriff mit SeekableByteChannel und ByteBuffer

Für den wahlfreien Zugriff auf Bytes in Dateien bietet Java seit Version 1.0 die Klasse RandomAccessFile. Unter Java 7 ist die Klasse nun nicht mehr nötig, und genaugenommen auch schon seit Java 1.4 nicht mehr, denn in Java 1.4 wurde das erste NIO-Paket eingeführt und mit ihm sogenannte Channel-Klassen, die eine offene Verbindung mit einem Datenkanal repräsentieren. Neu in Java 7 ist die Verbindung von Path und einem besonderen Channel für wahlfreie Ein-/Ausgabe, dem SeekableByteChannel, der ebenfalls in Java 7 eingeführt wurde.

SeekableByteChannel

Der SeekableByteChannel deklariert Operationen zum Lesen und Schreiben von Daten und zur Positionierung des Dateizeigers.

public interface java.nio.channels.SeekableByteChannel

extends ByteChannel

§ int read( ByteBuffer dst )

§ int write( ByteBuffer src )

§ long size()

§ long position()

§ SeekableByteChannel position( long newPosition )

§ SeekableByteChannel truncate( long size )

Die Methoden close() und isOpen() kommen aus Channel hinzu.

Es fällt auf, und das ist einer der großen Unterschiede zu RandomAccessFile, dass SeekableByteChannel kein byte-Feld oder einzelne Bytes liest oder schreibt, sondern einen ganz eigenen Typ, einen ByteBuffer, erwartet.

ByteBuffer

Ein ByteBuffer ist einem Byte-Feld sehr ähnlich; seine maximale Größe wird vorher festgelegt und kann später nicht dynamisch wachsen. Ist ein ByteBuffer angelegt, so können über einen Index die einzelnen Bytes gelesen und geschrieben werden, zum Beispiel mit byte get() oder put(byte b) relativ zur letzten Position, oder mit byte get(int index) und put(int index, byte b) absolut. Der wirkliche Unterschied ist aber, dass Java zwei verschiedene Arten von ByteBuffer-Implementierungen bietet (ByteBuffer ist eine abstrakte Klasse):

· Nicht-direkte ByteBuffer sind wie byte[]-Felder, also Java-Objekte, die auf dem Heap Platz einnehmen.

· Bei einem direkten ByteBuffer versucht Java einen Speicherbereich vom Betriebssystem zu bekommen. Während die nicht-direkten ByteBuffer und byte-Arrays auf dem Heap leben, und er normalen GC unterworfen sind, sollten die direkten ByteBuffer vom Betriebssystem verwaltet werden. Im Idealfall sind dadurch hohe Ein-/Ausgabegeschwindigkeiten möglich, denn mit direkten ByteBuffern kann sich das Betriebssystem Kopieroperationen zwischen nativen und Java-Puffern sparen.

Die Methoden auf direkten oder nicht-direkten ByteBuffern sind identisch. Insbesondere speichern die alle Puffer Zustände: Die Position, einen Limit und eine Kapazität. Diesen Eigenschaften wollen wir aber in der Insel nicht nachgehen.

Beispiel mit Path + SeekableByteChannel + ByteBuffer

Das folgende Beispiel fasst alles zusammen: Von einem Path wird über newByteChannel ein SeekableByteChannel erfragt. Anschließen leiten wir aus einer Zeichenkette über das byte[] einen nicht-direkten ByteBuffer ab und schreiben diesen in den SeekableByteChannel, sodass später die Datei Kurt Cobain.txt einen ASCII-Text enthält.

com/tutego/insel/nio2/SeekableByteChannelDemo.java, main()

Path p = Paths.get( "Kurt Cobain.txt" );

SeekableByteChannel raf = p.newByteChannel( StandardOpenOption.CREATE,

StandardOpenOption.WRITE );

String s = "Drugs are bad for you. ";

ByteBuffer byteBuffer = ByteBuffer.wrap( s.getBytes() );

raf.write( byteBuffer );

raf.write( ByteBuffer.wrap( "They will f*ck you up.".getBytes() ) );

raf.position( 34 );

raf.write( ByteBuffer.wrap( new byte[]{'u'} ) );

raf.close();

Das Beispiel zeigt, dass mit ByteBuffer.wrap() aus dem byte[] der Strings ein nicht-direkter Buffer angelegt wird, den write() dann in den Kanal schreibt.

kurt-in-hex

Nur zum Testen schreiben wie ASCII-Zeichen, was aber im „echten Leben“ eher nicht der Fall sein wird, denn wir müssen hier die korrekten Zeichenkodierungen beachten. Auch für sequenzielle Schreiboperationen ist der SeekableByteChannel eher weniger komfortabel – dennoch ist der Einsatz von Kanälen nicht per se falsch. Im nächsten Kapitel werden die Ströme vorgestellt, mit denen das Schreiben, insbesondere von Textdokumenten, viel einfacher wird.

FileChannel

Die Schnittstelle SeekableByteChannel gibt Operationen an, um die aktuelle Position auszulesen und den Positionszeiger neu zu setzen und über ByteBuffer Bytes und Bytefolgen zu lesen und zu schreiben. SeekableByteChannel ist dabei nicht an Dateien gebunden und enthält keine Informationen zu Dateipfaden oder sonstigen tiefer liegenden Schichten. Und da Path grundsätzlich ein Pfad auf alles Mögliche sein kann, etwa auf ein BLOB in der Datenbank, liefert newByteChannel() eine Rückgabe mindestens von Typ SeekableByteChannel, und damit erst ein mal keine Möglichkeiten dateispezifische Operationen vorzunehmen.

Wird allerdings newByteChannel() auf einem Pfad aufgerufen, der eine Datei vom Dateisystem repräsentiert, so ist die Rückgabe nicht einfach nur ein SeekableByteChannel, sondern der Untertyp FileChannel.[1] Ein Typcast ist daher möglich:

Path p = Paths.get( "Kurt Cobain.txt" );

FileChannel channel = (FileChannel) p.newByteChannel( options );

Da FileChannel die Schnittstelle SeekableByteChannel implementiert, bietet natürlich FileChannel alle Methoden zum Lesen, Schreiben und Positionieren. Zusätzlich bietet FileChannel aber Methoden, die explizit an Dateien gebunden sind. Drei Methoden fallen sofort auf:

· lock(): Sperrt die Datei (oder Dateiteile) für andere, soweit es das Betriebssystem unterstützt.

· force(): Updates werden sofort materialisiert, das heißt auf das Dateisystem übertragen.

· map(): Blendet die Datei, oder einen Teil der Datei, in den Speicher ein.

Die Methode map() ist besonders interessant. Damit kann ein FileChannel auf ein ByteBuffer abgebildet werden, sodass unsere Lese-/Schreiboperationen auf dem ByteBuffer direkt aus der Datei kommen oder direkt in die Datei gehen. Das Betriebssystem versucht sein bestes, die Operationen zu optimieren und geeignete Blöcke der Datei in den Speicher zu laden. Java und das Betriebssystem tuen damit ihr Bestes, die Operationen so schnell wie möglich und mit wenigen Kopieroperationen zwischen den internen Puffern vom Dateisystem und den Java-Puffern durchführen.

Das folgende Beispiel bezieht im ersten Schritt über newByteChannel() den FileChannel. Anschließend bildet die Methode map() die gesamte Datei auf einen MappedByteBuffer ab, der ein ByteBuffer ist, wie wir ihn im letzten Beispiel schon kennengelernt haben. Wir könnten nun Methoden auf dem ByteBuffer aufrufen, und die Bytes auslesen, doch hier gehen wir etwa anders vor: Die Bytes des ByteBuffer konvertiert ein CharsetDecoder von ASCII in Java-Unicode; das Ergebnis ist ein CharBuffer. Den CharBuffer laufen wir ab und geben die Zeichen auf der Konsole aus.

com/tutego/insel/nio2/FileChannelDemo.java, main()

Path p = Paths.get( "Kurt Cobain.txt" );

FileChannel fileChannel = (FileChannel) p.newByteChannel( StandardOpenOption.READ );

ByteBuffer byteBuffer = fileChannel.map( FileChannel.MapMode.READ_ONLY,

0, fileChannel.size() );

CharsetDecoder decoder = Charset.forName( "ASCII" ).newDecoder();

CharBuffer charBuffer = decoder.decode( byteBuffer );

while ( charBuffer.hasRemaining() )

System.out.print( charBuffer.get() );

Beim FileChannel gilt das gleiche wie beim SeekableByteChannel. Sequenzieller Lese- oder Schreibzugriff wird am Einfachsten über die Strom-Klassen realisiert. Sie werden im folgenden Kapitel vorgestellt.


[1] Den Typ FileChannel gibt es in Java schon länger, seit Java 1.4. Und vor Java 7 lieferten die Methoden getChannel() von FileInputStream, FileOutputStream und RandomAccessFile den FileChannel.

Labels: ,

NetBeans 6.8 Milestone 1

Gibt es nun auch zum Downloaden unter http://bits.netbeans.org/netbeans/6.8/m1/. Und die News gibt es hier unter http://wiki.netbeans.org/NewAndNoteworthyNB68. Interessant ist:

  • Milestone1 enables basic support for development of applications for Java Enterpise Edition v6.
  • support for JPA 2.0
  • Initial PHP 5.3 support
  • Upgraded bundled JRuby to 1.3.1
  • Support for creating Rails 2.3.2 apps with dispatchers
  • Neue Profiling tools für C++
  • Issue tracking integration now supports JIRA

Labels:

iPhone-Applikationen mit Java entwickeln (XMLVM)

Ein großartiges Projekt ist http://www.xmlvm.org/. Es steht zwar erst am Anfang, aber der sieht sehr vielversprechend aus. Die Idee von XMLVM ist einfach: Man nehme den Bytecode, repräsentierte diesen als XML, transformiere den über XSLT in Objective C und kompilieren dann.

XMLVM Overview Diagram

(Bilder von der Webseite)

 

XMLVM Frontend

Die Stack-Operationen vom Java-Bytecode werden über XSLT einfach in Objective C abgebildet, wobei die Stack-Operationen beibehalten werden. Die Mühe über einen internen AST oder so macht man sich nicht.

<xsl:template match="jvm:irem">
  <xsl:text>
    _op2.i = _stack[--_sp].i; // Pop operand 1
    _op1.i = _stack[--_sp].i; // Pop operand 2
    _stack[_sp++].i = _op1.i % _op2.i; // Push remainder
  </xsl:text>
</xsl:template>

Das gibt zwar für den GCC ‘ne Menge zu optimieren, aber das ist der einfachste Weg der Transformation. Später sieht das dann so aus:

@interface org_xmlvm_test_HelloWorld : java_lang_Object
+ (void) main___java_lang_String_ARRAYTYPE :(NSMutableArray*)n1;
@end
@implementation org_xmlvm_test_HelloWorld;
+ (void) main___java_lang_String_ARRAYTYPE :(NSMutableArray*)n1
{
    XMLVMElem _stack[2];
    XMLVMElem _locals[1];
    int _sp = 0;
    XMLVMElem _op1, _op2, _op3;
    int _i;
    for (_i = 0; _i <1; _i++) _locals[_i].o = nil;
    NSAutoreleasePool* _pool = [[NSAutoreleasePool alloc] init];
    _locals[0].o = n1;
    _op1.o = [java_lang_System _GET_STATIC_java_lang_System_out];
    _stack[_sp++].o = _op1.o;
    _stack[_sp++].o = @"Hello World";
    _sp -= 2;
    [((java_io_PrintStream*) _stack[_sp].o) println___java_lang_String:_stack[_sp + 1].o];
    [_pool release];
    return;
}
@end

 

Weitere Beispiele gibt http://xmlvm.org/showcase/ und der Blog http://www.cokeandcode.com/aboidblog.

Insgesamt ein sehr spannendes Projekt, welches auch die Frage Android –> iPhone Entwicklung angeht, und .NET -> Java Cross-Compilation bietet. Mal sehen, wie sich das Entwickeln wird. MONO für iPhone ist auch bald bereit und dann wird iPhone Entwicklung wirklich einfach. (Bekommen wir dann noch mehr Schrott im Store?)

Labels:

Über die Sicherheitsarchitektur von Google Android

Vom 25.-30. Juli lief in in den USA die Sicherheitsmesse Black Hat. Dort hat Jesse Burns in einem Vortrag die Sicherheitsarchitektur von Android vorgestellt. Sein Paper dazu kann man hier (alternativ unter http://www.isecpartners.com/files/iSEC_Securing_Android_Apps.pdf) runterladen.

Weiterhin lesenswert ist

Labels:

Vorhandene Runtime-Fehlertypen kennen und nutzen

Die Java-API bietet eine große Anzahl von Exception-Klassen und so muss nicht für jeden Fall eine eigene Exception-Klasse deklariert werden. Viele Standard-Fälle, wie falsche Argumente, können durch Standard-Exception-Klassen abgedeckt werden. Einige Standard-Runtime-Exception-Unterklassen des java.lang-Pakets in der Übersicht:

IllegalArgumentException

Die IllegalArgumentException zeigt an, dass ein Parameter nicht korrekt angegeben ist. Diesen Fehlertyp lässt sich somit nur bei Konstruktoren oder Methoden ausmachen, denen fehlerhafte Argumente übergeben wurden. Oft ist der Grund die Missachtung des Wertebereiches. Wenn die Werte grundsätzlich korrekt sind, darf dieser Fehlertyp nicht ausgelöst werden.

IllegalStateException

Objekte haben in der Regel Zustände. Gilt es Operationen auszuführen, aber die Zustände sind nicht korrekt, so kann die Methode eine IllegalStateException auslösen und so anzeigen, dass in dem aktuellen Zustand die Operation nicht möglich ist. Wäre der Zustand korrekt, kommt es nicht zu der Ausnahme. Bei statischen Methoden sollte es eine IllegalStateException nicht geben.

UnsupportedOperationException

Implementieren Klassen Schnittstellen oder realisieren Klassen abstrakte Methoden von Oberklassen, so muss es immer eine Implementierung geben, auch wenn die Unterklasse die Operation eigentlich gar nicht umsetzen kann oder will. Statt den Rumpf der Methode nur leer zu lassen und einen potentiellen Aufrufer in den Glauben zu setzen, die Methode führt etwas aus, sollten diesen Methoden eine UnsupportedOperationException auslösen. In den API-Dokumentationen werden Methoden, die Unterklassen vielleicht nicht realisieren wollen, als „optionale Operation“ gekennzeichnet.

<pic: optional operation.png, „Optionale Operationen in der Schnittstelle java.util.List“>

Unglücklicherweise gibt es auch eine javax.naming.OperationNotSupportedException. Doch diese sollte nicht verwendet werden. Sie ist speziell für Namensdienste und auch keine RuntimeException.

IndexOutOfBoundsException

Eine IndexOutOfBoundsException lost die JVM automatisch aus, wenn zum Beispiel die Grenzen eines Arrays missachtet werden. Wir können diesen Ausnahmetyp selbst immer dann nutzen, wenn wir Index-Zugriffe haben, etwa auf eine Zeile in einer Datei, und der Index im falschen Bereich liegt. Von IndexOutOfBoundsException gibt es die Unterklassen ArrayIndexOutOfBoundsException und StringIndexOutOfBoundsException. Programmierer werden diese Typen aber in der Regel nicht nutzen. Inkonsistenzen gibt es beim Einsatz von IllegalArgumentException und IndexOutOfBoundsException. Ist etwa der Index falsch, so entscheiden sich einige Autoren für den ersten Fehlertyp, andere für den zweiten. Beides ist prinzipiell gültig. Die IndexOutOfBoundsException ist aber konkreter und zeigt eher ein Implementierungsdetail an.

Keine eigene NullPointerException

Eine NullPointerException gehört mit zu den häufigsten Ausnahmen. Die JVM löst diesen Fehler etwa bei folgendem Programmstück aus:

String s = null;

s.length();

Eine NullPointerException zeigt immer einen Programmierfehler in einem Stück Code an und so gibt es in der Regel keinen Sinn, diesen Fehler abzufragen – der Programmierfehler muss behoben werden. Aus diesem Grund wird eine NullPointerException in der Regel nie explizit vom Programmierer ausgelöst, sondern von der JVM.

Oft gibt es diese NullPointerException, wenn an Methoden null-Werte übergeben wurden. Hier muss aus der API-Dokumentation klar hervorgehen, ob null als Argument erlaubt ist, oder nicht. Wenn nicht, ist es völlig in Ordnung, wenn die Methode eine NullPointerException auslöst, wenn fälschlicherweise doch null übergeben wurde. Auf null zu prüfen, um dann eine zum Beispiel IllegalArgumentException auszulösen, ist eigentlich nicht nötig. Allerdings gilt auch hier, dass IllegalArgumentException allgemeiner und weniger Implementierungsspezifisch als eine NullPointerException ist.

Labels:

Frage: Kann man alle Instanzen einer Klasse ermitteln?

Das geht nicht wirklich und wenn, dann nur mit großen Umwegen etwa über die Java Debugging API, mit der man sich an die JVM hängen kann. Auch ein Blick auf den Quellcode von jconsole und jmap/jhat helfen hier, weil die Tools genau das machen und Zahlen geben.

Der Objektgraf verändert sich ständig und so könnte man auch die Objekte stark referenzieren und den GC am Löschen hindern. Das würde zu einer großen Anzahl von Problemen führen. (Schwache Referenzen könnte das Problem abmildern, aber der GC muss hier Zusatzarbeit machen und die Laufzeit würde sich (messbar) verschlechtern.) Die Objekte sind ja immer eine Momentaufnahme. Da kämen ja Millionen von Objekten raus, wenn man etwa nach "Gib mir alle Strings" fragt. Laufend ändert sich diese Menge.

Wenn der Nutzer diese Instanzen wirklich braucht, kann er sie an einer Objekt-Registry anmelden.

  • Von Hand kann man Exemplare etwa in eine Map<Class,List<?>> setzen. Das muss man nicht unbedingt manuell machen, sondern man kann hier einen Aspekt schreiben, der Bytecode in den Konstruktor für solch ein Anmelden einfügt. Dann ist das Abmelden aber noch so eine Sache. Das kann aber eine PhantomReference übernehmen und so meldet man das Objekt an der Registry wieder ab.
  • Wenn man Spring benutzt, deklariert ListableBeanFactory (implementiert etwa von XmlBeanFactory) eine Methode Map getBeansOfType(Class type) für genau diesen Fall.
  • Sind die Exemplare alle MBeans, ist es einfach, dann sind sie schon an einem Container registriert, und Query liefert sie sogar nach gewissen Kriterien.

Labels: