2

I want to print out all methods that get called during runtime. They should be printed out in the order that they're called in and if they're called multiple times, they should be printed multiple times.

This can be used for reverse engineering - seeing which functions get called when you press a button or do a specific action.

I want to use Java agents and instrumentation for this.

Nopslide
  • 121
  • 2
  • 7
  • 2
    Possible duplicate of [Get current stack trace in Java](http://stackoverflow.com/questions/1069066/get-current-stack-trace-in-java) – Ravi Mar 26 '17 at 11:02
  • This is what a debugger is for. You can trace each method as it is called. You can use the debugger API to do this programatically but stepping through the code is likely to be simpler as you can also see the values used. – Peter Lawrey Mar 26 '17 at 11:07
  • Clarified that I want it to be done using a java agent. – Nopslide Mar 26 '17 at 11:28

1 Answers1

5

This can be done using Java Agents and an instrumentation library.

Java agent - Separate code that can be made to run before the main part of the code.

Instrumentation - Changing the source code during the load-time of a program.

Code for making it work

(taken from appcrawler and modified slightly):

The agent.jar source code:

SimpleTransformer.java:

package test;

import java.security.*;
import java.lang.instrument.*;
import java.util.*;
import javassist.*;
 
public class SimpleTransformer implements ClassFileTransformer {
 
  public SimpleTransformer() {
    super();
  }
 
  public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) throws IllegalClassFormatException {
    return transformClass(redefiningClass,bytes);
  }
 
  private byte[] transformClass(Class classToTransform, byte[] b) {
    ClassPool pool = ClassPool.getDefault();
    CtClass cl = null;
    try {
      cl = pool.makeClass(new java.io.ByteArrayInputStream(b));
      CtBehavior[] methods = cl.getDeclaredBehaviors();
      for (int i = 0; i < methods.length; i++) {
        if (methods[i].isEmpty() == false) {
          changeMethod(methods[i]);
        }
      }
      b = cl.toBytecode();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    catch (Throwable t) {
      t.printStackTrace();
    }
    finally {
      if (cl != null) {
        cl.detach();
      }
    }
    return b;
  }
 
  private void changeMethod(CtBehavior method) throws NotFoundException, CannotCompileException {
    /*if (method.getName().equals("doIt")) {
      method.insertBefore("System.out.println(\"started method at \" + new java.util.Date());");
      method.insertAfter("System.out.println(\"ended method at \" + new java.util.Date());");
    }*/
    

  
          //MY CODE
      //!Modifier.isAbstract(method.getModifiers()) -- abstract methods can't be modified. If you get exceptions, then add this to the if statement.
      //native methods can't be modified.
      if (!Modifier.isNative(method.getModifiers())) {
          String insertString = "System.out.println(\"started method " + method.getName() + "\");";
          method.insertBefore(insertString);
      }
  }

SimpleMain.java:

package test;

import java.lang.instrument.Instrumentation;

public class SimpleMain {
  public static void premain(String agentArguments, Instrumentation instrumentation) {  
    instrumentation.addTransformer(new SimpleTransformer());
  } 
}

MANIFEST.mf:

Manifest-Version: 1.0
Boot-Class-Path: javassist.jar
Premain-Class: test.SimpleMain

Take these files and package them into a jar file. Also make sure to include files from javassist.jar (downloadable from www.javassist.org) and tools.jar (found in Program Files/Java/jdk/lib/). Not sure if the second one is necessary, but the article says it is for some reason.

Now you can use this jar file as a java agent.

java -javaagent:agent.jar YourJavaProgram

And voila. The java agent will instrument all methods and print out every method called during execution.

samabcde
  • 6,988
  • 2
  • 25
  • 41
Nopslide
  • 121
  • 2
  • 7
  • 1
    Note: This code works for simple programs, but may break with more complex ones, as it did with my project. – Nopslide Mar 27 '17 at 16:07