Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change a closed-source class to manipulate the methods within

Tags:

java

bytecode

I'm using a 3rd party library and have discovered a performance bug in it during profiling. I can easily fix this by decompiling the offending class and changing the 'getFoo(Bar b)' method to use a LoadingCache. I then just put that file in the same package in my own source and it overrides it. However, the rest of the class is fine and I don't want to have to keep it updated with library updates.

(I'm aware that the function I'm manipulating may change in the future, but this is also a thought exercise as much as anything else)

What I'm looking for is a way to do this without decompiling the class, i.e. using AspectJ / Javassist / some other bytecode manipulator

e.g. change this:

public class SlowWorker{
    public static Foo getFoo(Bar b){
        //do long running op using b and return a Foo
    }
}

to:

public class SlowWorker{
    private static LoadingCache<AdviceDocument, Object> fooCache = CacheBuilder
      .newBuilder()
      .maximumSize(10000)
      .weakKeys()
      .build(new CacheLoader<Bar, Object>() {
            @Override
            public Object load(Bar b) throws Exception {
                return getUncachedFoo(b);
            }
        });

    public static Foo getFoo(Bar b){
        return fooCache.get(b);
    }

    public static Foo getUncachedFoo(Bar b){
        Foo result = //long running op on b
        return result;
    }
}
like image 615
beirtipol Avatar asked Sep 16 '25 20:09

beirtipol


1 Answers

After a few hours of fiddling and researching, I realised that what I was trying to do was Hot-Swap the code.

For the curious:

  • http://www.hotswapagent.org/
  • http://zeroturnaround.com/software/jrebel/
like image 147
beirtipol Avatar answered Sep 18 '25 18:09

beirtipol