2010-01-14 9 views
5

Um die in JDK 5 eingeführten Instrumentierungsfunktionen zu verwenden, können Sie das Flag -javaagent verwenden, das an die JVM übergeben wird. Dadurch wird eine Instanz einer Instrumentation-Klasse in die statische Methode premain eingefügt. Zum Beispiel in einer Klasse wie folgt aus:Wie kann ich java.lang.instrument in einer Eclipse RCP-Anwendung verwenden?

public class MyClass { 
    public static Instrumentation inst; 
    public static void premain(String options, Instrumentation inst) { 
     MyClass.inst = inst; 
    } 
} 

Mit einer entsprechenden Manifest-Datei, können Sie dies wie folgt durchgeführt:

java -javaagent:myfiles.jar SomeClass 

Dies erfordert die premain Methode dann main von SomeClass. Dieser Ansatz wird in der Java.SizeOf Project verwendet, um die ungefähre Größe eines Java-Objekts zu erraten.

OK, jetzt in Eclipse RCP each bundle has its own classloader. Dies bedeutet, dass die statische Instrumentierung, die wir in unserer MyClass gespeichert haben, für eine Eclipse-Anwendung nicht sichtbar ist. Der Java-Agent verwendet einen Klassenlader, die Eclipse-Bundles werden mit einem anderen geladen. Wenn wir innerhalb eines Plugins auf MyClass.inst zugreifen, ist es null, wie , die Klasse ist nicht die gleiche Klasse wie die, die der Java-Agent geladen und premain aufgerufen.

Weitere Hinweise auf eine mögliche Lösung sind this thread auf der Rcp Mailing-Liste. Aber nichts schlüssiges.

Gibt es eine Möglichkeit, dies zu umgehen? Die im Artikel von eclipsezone angedeutete Eclipse-BuddyPolicy klingt gut. Ich habe versucht:

Eclipse-BuddyPolicy: app 

in meinen Plugins ohne Glück. Ich brauche etwas wie Eclipse-BuddyPolicy: javaagent. Irgendwelche Ideen?

+0

Sie erhalten Sie eine Ausnahmen? Eine Falle ist die Agentklasse ohne Paket. (d. h. MyClass ist möglicherweise nicht im Standardpaket enthalten). Funktioniert es außerhalb der Sonnenfinsternis? – stacker

+0

Ja, funktioniert außerhalb von Eclipse mit POJO Zeug. Tatsächlich wird ein "println" in der Präambel aus Eclipse angezeigt, aber die statische Instrumentierung ist null, wenn sie von einem beliebigen Plugin aufgerufen wird. – richq

Antwort

4

Ich denke, die einfachste Lösung ist die Verwendung des globalen Eigenschaftenobjekts. Haben Pre-Hauptspeicher die Instrumentierung Objekt als globale Eigenschaften und dann von überall zugreifen (die Eigenschaften Objekt das gleiche in allen Klassenlader ist):

[Edit: aktualisiert]

public class MyClass { 
    private static final String KEY = "my.instrumentation"; 
    public static void premain(String options, Instrumentation inst) { 
     Properties props = System.getProperties(); 
     if(props.get(KEY) == null) 
      props.put(KEY, inst); 
    } 

    public static Instrumentation getInstrumentation() { 
     return System.getProperties().get(KEY); 
    } 
} 
+0

Es ist eine nette Idee, aber leider ist es 'setProperty (String, String)' - Sie können dort kein altes Objekt einfügen. – richq

+0

Dies kann leicht behoben werden (siehe aktualisierte Version meiner Antwort): System.getProperties() gibt ein Properties() -Objekt zurück, das eine Unterklasse von Hashtable ist, dessen API offsets (String, Object) und get (String) ein Object liefert. –

+0

Solch eine einfache Lösung, und es funktioniert perfekt. Vielen Dank! – richq