Java trace all method calls

How to log/trace any method call of object in java

Update 3 3 years after: Update on timing with current JVM. Solution 3: Java 9 — JEP 259: Stack-Walking API JEP 259 provides an efficient standard API for stack walking that allows easy filtering of, and lazy access to, the information in stack traces. Question: I want to trace the beginning [& ending] of functions called in Java, like the following code: But maintaining of the dump code is something tedious and error-prone, for there may be tens of thounds of function in an class.

How to log/trace any method call of object in java

I need some thing like a Python decorator. I need to store some information, specifically the method called, its start time, its end time, and its arguments. I cannot import anything outside of Java 1.5 libraries. Is there some thing like what is available in Python?

Good tracing tool for Java is btrace.

You can try some profiler using Java Management Extensions or java agent.

No, Python decorators do not let you monitor all the code without changing anything. You still have to put your decorator everywhere (and — essentially — wrap each of your functions into a function that does the counting).

I am not sure if I understand your requirements (you do not say if you need the code for production or testing; also, the requirement «not to import anything» is bizarre: are all your classes in the default package? are you allowed to use an IDE and a compiler?), but I think the simplest way would be to use Javassist (the second link kindly provided by cschooley is a perfect introduction), but do not use the agent: instead use CtClass#write() to instrument class files and save them to disk (possibly in a custom ant task). This way the final build will not need any special set-up.

Static analysis of Java call graph, What I’d like to do is scan a set of Java classes, and trace all method calls from a specific method of an Abstract Class, and within that context, build a list of all …

Java, how to trace functions called

I want to trace the beginning [& ending] of functions called in Java, like the following code:

Читайте также:  margin

But maintaining of the dump code System.out.println is something tedious and error-prone, for there may be tens of thounds of function in an class.

Any good idea can ease this work? I don’t want dump statements all over the file.

Implementation of both or one of the beginning & ending traces is perferd.
But, if impossible, recordings of that the function has been called is also helpful. I mean not care the exact beginnig and ending, just tell that the function has been called.

Another approach would be using BTrace — it is kind of similar to AspectJ but can attach to a running java application and apply the logging code on-the-fly (it can also detach from the application, removing all the injected code but leaving the app running as it was before using BTrace )

In order to use BTrace you would write a simple tracing script which is POJO annotated with BTrace annotations (and some restrictions regarding what is possible to use to avoid crashing the target application).

In this case the the script would look like this:

@BTrace public class FooTracer < @OnMethod(clazz="Bar", method="foo") public static void onEntry() < println("begin of foo()"); >@OnMethod(clazz="Bar", method="foo", location=@Location(Kind.RETURN)) public static void onExit() < println("end of foo"); >> 

There are many more things you can do with BTrace — just refer to the user guide and examples. Nominally, it is console application but there is integration into VisualVM making the experience of working with BTrace more pleasant.

The easiest approach is the one you’ve chose.

An easy replacement for the System.out calls would be using a logging framework. Then you could switch the information on and off according to a selected «logging level»

More sophisticated solutions would use aspect oriented programming techniques (provide by AspectJ, for instance), but this puts you on a steep learning curve.

Maybe a tool-based a approach fits your needs: so called «profilers» can «instrument» your code and report exactly which method was called during a run.

If there are lots of methods to log, AOP could be used. For example, aspectJ.

You could use log4j for this:

static Logger log = Logger.getLogger( log4jExample.class.getName()); public void loggedMethod()

How to track java method calls and get alerts in, 1 Answer. I would take a look at Custom Services for Java which will cause invocations of the method to be monitored in more detail. Maybe you can …

How do I find the caller of a method using stacktrace or reflection?

I need to find the caller of a method. Is it possible using stacktrace or reflection?

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace() 

According to the Javadocs:

The last element of the array represents the bottom of the stack, which is the least recent method invocation in the sequence.

A StackTraceElement has getClassName() , getFileName() , getLineNumber() and getMethodName() .

Читайте также:  Чем заменить пробел php

You will have to experiment to determine which index you want (probably stackTraceElements[1] or [2] ).

Note : if you are using Java 9 or later you should use StackWalker.getCallerClass() as described in Ali Dehghani’s answer.

The comparison of different methods below is mostly interesting for historical reason.

An alternative solution can be found in a comment to this request for enhancement. It uses the getClassContext() method of a custom SecurityManager and seems to be faster than the stack trace method.

The following program tests the speed of the different suggested methods (the most interesting bit is in the inner class SecurityManagerMethod ):

/** * Test the speed of various methods for getting the caller class name */ public class TestGetCallerClassName < /** * Abstract class for testing different methods of getting the caller class name */ private static abstract class GetCallerClassNameMethod < public abstract String getCallerClassName(int callStackDepth); public abstract String getMethodName(); >/** * Uses the internal Reflection class */ private static class ReflectionMethod extends GetCallerClassNameMethod < public String getCallerClassName(int callStackDepth) < return sun.reflect.Reflection.getCallerClass(callStackDepth).getName(); >public String getMethodName() < return "Reflection"; >> /** * Get a stack trace from the current thread */ private static class ThreadStackTraceMethod extends GetCallerClassNameMethod < public String getCallerClassName(int callStackDepth) < return Thread.currentThread().getStackTrace()[callStackDepth].getClassName(); >public String getMethodName() < return "Current Thread StackTrace"; >> /** * Get a stack trace from a new Throwable */ private static class ThrowableStackTraceMethod extends GetCallerClassNameMethod < public String getCallerClassName(int callStackDepth) < return new Throwable().getStackTrace()[callStackDepth].getClassName(); >public String getMethodName() < return "Throwable StackTrace"; >> /** * Use the SecurityManager.getClassContext() */ private static class SecurityManagerMethod extends GetCallerClassNameMethod < public String getCallerClassName(int callStackDepth) < return mySecurityManager.getCallerClassName(callStackDepth); >public String getMethodName() < return "SecurityManager"; >/** * A custom security manager that exposes the getClassContext() information */ static class MySecurityManager extends SecurityManager < public String getCallerClassName(int callStackDepth) < return getClassContext()[callStackDepth].getName(); >> private final static MySecurityManager mySecurityManager = new MySecurityManager(); > /** * Test all four methods */ public static void main(String[] args) < testMethod(new ReflectionMethod()); testMethod(new ThreadStackTraceMethod()); testMethod(new ThrowableStackTraceMethod()); testMethod(new SecurityManagerMethod()); >private static void testMethod(GetCallerClassNameMethod method) < long startTime = System.nanoTime(); String className = null; for (int i = 0; i < 1000000; i++) < className = method.getCallerClassName(2); >printElapsedTime(method.getMethodName(), startTime); > private static void printElapsedTime(String title, long startTime) < System.out.println(title + ": " + ((double)(System.nanoTime() - startTime))/1000000 + " ms."); >> 

An example of the output from my 2.4 GHz Intel Core 2 Duo MacBook running Java 1.6.0_17:

Reflection: 10.195 ms. Current Thread StackTrace: 5886.964 ms. Throwable StackTrace: 4700.073 ms. SecurityManager: 1046.804 ms. 

The internal Reflection method is much faster than the others. Getting a stack trace from a newly created Throwable is faster than getting it from the current Thread . And among the non-internal ways of finding the caller class the custom SecurityManager seems to be the fastest.

Читайте также:  Css background gradient angle

Update

As lyomi points out in this comment the sun.reflect.Reflection.getCallerClass() method has been disabled by default in java 7 update 40 and removed completely in Java 8. Read more about this in this issue in the Java bug database.

Update 2

As zammbi has found, Oracle was forced to back out of the change that removed the sun.reflect.Reflection.getCallerClass() . It is still available in Java 8 (but it is deprecated).

Update 3

3 years after: Update on timing with current JVM.

> java -version java version "1.8.0" Java(TM) SE Runtime Environment (build 1.8.0-b132) Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode) > java TestGetCallerClassName Reflection: 0.194s. Current Thread StackTrace: 3.887s. Throwable StackTrace: 3.173s. SecurityManager: 0.565s. 

Java 9 — JEP 259: Stack-Walking API

JEP 259 provides an efficient standard API for stack walking that allows easy filtering of, and lazy access to, the information in stack traces. Before Stack-Walking API, common ways of accessing stack frames were:

Throwable::getStackTrace and Thread::getStackTrace return an array of StackTraceElement objects, which contain the class name and method name of each stack-trace element.

SecurityManager::getClassContext is a protected method, which allows a SecurityManager subclass to access the class context.

JDK-internal sun.reflect.Reflection::getCallerClass method which you shouldn’t use anyway

Using these APIs are usually inefficient:

These APIs require the VM to eagerly capture a snapshot of the entire stack , and they return information representing the entire stack. There is no way to avoid the cost of examining all the frames if the caller is only interested in the top few frames on the stack.

In order to find the immediate caller’s class, first obtain a StackWalker :

StackWalker walker = StackWalker .getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); 

Then either call the getCallerClass() :

Class callerClass = walker.getCallerClass(); 

or walk the StackFrame s and get the first preceding StackFrame :

walker.walk(frames -> frames .map(StackWalker.StackFrame::getDeclaringClass) .skip(1) .findFirst()); 

Sounds like you’re trying to avoid passing a reference to this into the method. Passing this is way better than finding the caller through the current stack trace. Refactoring to a more OO design is even better. You shouldn’t need to know the caller. Pass a callback object if necessary.

Источник

Оцените статью