Bytecode Instrumentation

Bytecode Instrumentation is done using Instrumentors. Jour configuration files defines which Instrumentor should be called for class and its methods.

  • Class selection is done using typedef. This is basicaly wildcard for class name.

    instrumentor.instrumentClass would be called.

  • Method selection is done using pointcut. This is more complex wildcard that allow filtering base on method signature.

    instrumentor.instrumentMethod or instrumentor.instrumentConstructor would be called.

To create your own instrumentor you should know Javassist. And follow provided examples:

If instrumentClass

  • jour.xml

    This file is used to define what kind of instrumentation would be applied and to which classes and methods.

    <jour>
        <aspect type="net.sf.jour.instrumentor.MakeEmptyMethodInstrumentor">
            <typedef>com.solect.*</typedef>
            <pointcut expr="* debug*(..)"/>
        </aspect>
    </jour>

    This will instrument all classes that have functions like debug.

    Consider original code.

    public class ClassWithDebug {
    
            public ClassWithDebug(String param) {
                    debug("ClassWithDebug created", param);
            }
    
            public void debug(String message, String v) {
                    System.out.println(message + " " + v);
            }
    }

    This is how the code will look after instrumentation and decompilation

    public class ClassWithDebug {
    
            public ClassWithDebug(String param) {
                    debug("ClassWithDebug created", param);
            }
    
            public void debug(String message, String v) {
            }
    }

    This is how the code will look after instrumentation processing by ProGuard and decompilation

    public class ClassWithDebug {
    
            public ClassWithDebug(String param) {
            }
    
    }

Details of jour.xml

  • aspect Define the instrumentor to be used.

    Predevined values are

    • net.sf.jour.instrumentor.MethodExecutionTimeInstrumentor
    • net.sf.jour.instrumentor.ExceptionCatcherInstrumentor
    • net.sf.jour.instrumentor.MakeEmptyMethodInstrumentor
    • net.sf.jour.instrumentor.ReplaceMethodInstrumentor

    Custom instrumentor should implement net.sf.jour.instrumentor.Instrumentor

  • typedef Apply class filter

    Examples:

    • All test classes
      <typedef>*.*Test</typedef>
    • All classes in package net.sf.jour.examples.
      <typedef>net.sf.jour.examples.*</typedef>
  • pointcut Apply function filter

    Examples:

    • Explicit function name and return type
      <pointcut expr="junit.framework.Test suite()">
    • All getters
      <pointcut expr="* get*()">
    • All not final getters
      <pointcut expr="!final * get*()">

      public private synchronized static modifiers can be used

    • All functions other than seters
      <pointcut expr="* *(..)|!* set*(..)">
    • Any function returning String taking any arguments
      <pointcut expr="java.lang.String *(..)">
    • Any function returning String or int
      <pointcut expr="java.lang.String;int *(..)">
    • Any function taking String and int arguments
      <pointcut expr="* *(java.lang.String,int)">
    • Any function taking String or int arguments
      <pointcut expr="* *(java.lang.String|int)">
    • Any function that implements interface com.exmple.MyInterface
      <pointcut expr="* com.exmple.MyInterface->*(..)">
  • property Any other property of Instrumentor

    This translates to method call "propertyName(String);

    Example:

    <jour>
            <aspect type="net.sf.jour.instrumentor.ExceptionCatcherInstrumentor" enabled="true">
                    <typedef>uut.exceptionCatcher.*Case</typedef>
                    <pointcut expr="* throwMethod*()"/>
                    <property name="exceptionType" value="java.lang.Error"/>
                    <property name="code">
                        <value><![CDATA[
                            {
                            caught = $e;
                            return;
                            }
                        ]]></value>
                    </property>
            </aspect>
    </jour>