Reloading classes with maniupulated bytecode from rt.jar

451 views Asked by At

I am currently trying to track method calls for learning purposes.

The javagent I have implemented is a modified version of the implementation in this article. The programm adds to any method call logging instructions into the bytecode. Unfortunately bootstrap classloader refuses to load any manipulated content from rt.jar. I can understand that this isn't a good idea for a production enviroment, but for a student it would be really amazing.

Do you got any ideas how to make this happen?

2

There are 2 answers

4
Rafael Winterhalter On

The only chance you have is to change the contents of rt.jar. The bootstrap class loader is special in many ways, many, but not all, of the classes are loaded before the agent even starts up.

Some classes can be explicitly redefined using the redefine method. This is however not possible for all bootstrap classes.

1
Rodrigo V On

I could successfully manipulate classes from the rt.jar.

For example I manipulated the bytecode of the BigDecimal class. Which class are you training to manipulate? And what kind of manipulation are you doing? Just adding logs to every method of the class like in the article that you mentioned?

In additional of following the instructions of article, I had to do some other things in order to be able manipulate the classes of rt.jar.

  1. In the LoggerAgent class I added an array of classes that I explicitly want to manipulate.

    String[] includeArr = new String[] { "java/math/BigDecimal" };
    ArrayList<String> include = new ArrayList(Arrays.asList(includeArr));
    
  2. In the transform method of the LoggerAgent class I modified the loop to include the classes I explicitly want to manipulate.

    for (int i = 0; i < ignore.length; i++) {
        if (className.startsWith(ignore[i]) && !include.contains(className)) {        
            return bytes;
        }
    }
    
  3. Fixed the method methodReturnsValue of JavassistHelper to correctly distinguish between methods and constructors.

    private static boolean methodReturnsValue(CtBehavior method)throws NotFoundException {
    
        if (method instanceof CtMethod){
            CtClass returnType = ((CtMethod) method).getReturnType();
            String returnTypeName = returnType.getName();
            if(returnTypeName.equals("void")){
                return false;
            }else{
                return true;
            }    
        } else{
            return false;
        }
    }
    
  4. Last, in the HelloWorld class I created a BigDecimal just to check the manipulation behavior.

The output looks like as follow:

19/06/2015 16:00:26 java.math.BigDecimal signum
INFO: << signum() returns: 1
19/06/2015 16:00:26 java.math.BigDecimal layoutChars
INFO: << layoutChars(1=true) returns: 11.1099999999999994315658113919198513031005859375
19/06/2015 16:00:26 java.math.BigDecimal toString
INFO: << toString() returns: 11.1099999999999994315658113919198513031005859375
19/06/2015 16:00:26 com.runjva.demo.HelloWorld main
INFO: << main(args=[])
BigDecimal=11.1099999999999994315658113919198513031005859375
Stop at Fri Jun 19 16:00:26 PDT 2015

I hope it helps. If not, please add more details of what you are trying to do.