daghanacay
|
Posted: December 05, 2011 06:21 by daghanacay
|
|
Hi there, I am tracing the memory usage in my application using visualVM and Btrace plug in. I can see that a particular class, namely gov.nasa.worldwind.geom.Position is using extra large memory. Since it is a 3rd party class it is created in many places including my code. I would like to identify which method instentiates the largest amount of the class so that I can refactor that method instead of refactoring every method where the class is used. I have used couple of BTrace scripts modifying the example scripts to the best of my understanding:
import static com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.annotations.*;
import gov.nasa.worldwind.geom.Angle;
/**
* A simple BTrace program that prints stack trace
* whenever a class is loaded by a user-defined
* class loader. We insert a return point probe in
* ClassLoader.defineClass method to detect successful
* class load.
*/
@BTrace public class Classload {
@OnMethod(
clazz="gov.nasa.worldwind.geom.Angle",
method="<init>",
location=@Location(Kind.RETURN)
)
public static void defineclass(@Return Class cl) {
println(Strings.strcat("loaded ", Reflective.name(cl)));
println("==========================");
}
}
the code above throws null pointer exception. The reason, I believe, is that "<init>" method cannot be found. I have changed the "<init>" to "/*/" and received invalid regex pattern exception. also changed "<init>" to "add" which is a public API of the class. This time the script compiles but cannot be started. Any help will be appreciated. If this cannot be done by BTrace can you direct me to a profiler which can do what I want? regards -Daghan |
trying to discover which methods instantiate an object
Replies: 1 - Last Post: December 10, 2011 23:10
by: Jaroslav Bachorik
by: Jaroslav Bachorik
showing 1 - 2 of 2
Jaroslav Bachorik
|
Posted: December 10, 2011 23:10 by Jaroslav Bachorik
|
|
Hi Daghan, there are few problems with your script:
You would rather need a script like this:
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
import java.util.Deque;
import java.lang.String;
@BTrace
public class TracingScript {
@TLS
// keep the per-thread stack of my custom code calls
private static Deque<String> eStack = newDeque();
@TLS
// keep the per-thread latest call to my custom code (equals to the top of the stack)
private static String current;
@OnMethod(clazz="/java2d\\..*/", method="/.*/")
// mark down the entry to the custom code
public static void noteCustomEntry(@ProbeMethodName(fqn=true) String m) {
push(eStack, m);
current = m;
}
@OnMethod(clazz="/java2d\\..*/", method="/.*/", location=@Location(Kind.RETURN))
// move up the stack
public static void noteCustomExit() {
current = poll(eStack);
}
@OnMethod(clazz="java.awt.Dimension", method="<init>")
// this is the place where you capture the constructor invocation; you have the caller on the stack
public static void site() {
if (current == null) return;
println(strcat("a new Dimension created @", current));
}
}
This piece of code should do exactly what you want. Edited Also, you should be able to achieve the same result by using Kind.CALL in @Location - unfortunately it seems to have some issues specifically in conjunction with constructors. Actually, you need to use Kind.NEW for tracking instance creation. Using this kind of location the script would look like this:
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.AnyType;
import java.util.Deque;
import java.lang.String;
@BTrace
public class InstanceTracker1 {
@OnMethod(
clazz="/java2d\\..*/",
method="/.*/",
location=@Location(
value=Kind.NEW,
clazz="java.awt.Dimension"
)
)
public static void site(@ProbeMethodName(fqn=true) String caller) {
println(strcat("a new Dimension created @", caller));
}
}
Regards, -JB- |
Replies: 1 - Last Post: December 10, 2011 23:10
by: Jaroslav Bachorik
by: Jaroslav Bachorik







