In order to use the instrumentation features introduced in JDK 5, you can use the -javaagent
flag passed to the JVM. This will inject an instance of an Instrumentation class into the static premain
method. For example in a class like this:
public class MyClass {
public static Instrumentation inst;
public static void premain(String options, Instrumentation inst) {
MyClass.inst = inst;
}
}
With an appropriate manifest file, you can run this as follows:
java -javaagent:myfiles.jar SomeClas开发者_如何学JAVAs
This calls the premain method then main
from SomeClass
. This approach is used in the Java.SizeOf Project to guess at the approximate size of a Java object.
OK, now in Eclipse RCP each bundle has its own classloader. This means that the static Instrumentation that we stored in our MyClass is not visible to an Eclipse application. The javaagent uses one class-loader, the Eclipse bundles get loaded with another. When we access MyClass.inst
from within a plugin it is null
, as that class is not the same class as the one the javaagent loaded and called premain
on.
Other clues as to a possible solution are this thread on the rcp mailing list. But nothing conclusive.
Is there any way to work around this? The Eclipse-BuddyPolicy
hinted at in the eclipsezone article sounds good. I tried:
Eclipse-BuddyPolicy: app
in my plugins without luck. I need something like Eclipse-BuddyPolicy: javaagent
. Any ideas?
I think the simplest solution is to use the global properties object. Have pre-main store the instrumentation object as a global properties and then access it from everywhere (the properties object is the same in all class loaders):
[Edit: updated]
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);
}
}
精彩评论