java - ByteBuddy fails when trying to redefine sun.reflect.GeneratedMethodAccessor1 -


driven curiosity, tried export bytecode of generatedmethodaccessor1 (generated jvm when using reflection).

i try bytecode of class following way:

public class methodextractor {      public static void main(string[] args) throws exception {          exampleclass example = new exampleclass();          method examplemethod = exampleclass.class                 .getdeclaredmethod("examplemethod");         examplemethod.setaccessible(true);          int rndsum = 0;         (int = 0; < 20; i++) {             rndsum += (integer) examplemethod.invoke(example);         }          field field = method.class.getdeclaredfield("methodaccessor");         field.setaccessible(true);         object methodaccessor = field.get(examplemethod);         field delegate = methodaccessor.getclass().getdeclaredfield("delegate");         delegate.setaccessible(true);         object gma = delegate.get(methodaccessor);          bytebuddyagent.installonopenjdk();         try {             classfilelocator classfilelocator = classfilelocator.agentbased                     .frominstalledagent(gma.getclass().getclassloader());             unloaded<? extends object> unloaded = new bytebuddy().redefine(                     gma.getclass(), classfilelocator).make();             map<typedescription, file> saved = unloaded.savein(files                     .createtempdirectory("javaproxy").tofile());             saved.foreach((t, u) -> system.out.println(u.getabsolutepath()));         } catch (ioexception e) {             throw new runtimeexception("failed save class file");         }     } } 

i following error when executing class:

exception in thread "main" java.lang.nullpointerexception     @ net.bytebuddy.dynamic.scaffold.typewriter$engine$forredefinition.create(typewriter.java:172)     @ net.bytebuddy.dynamic.scaffold.typewriter$default.make(typewriter.java:1182)     @ net.bytebuddy.dynamic.scaffold.inline.inlinedynamictypebuilder.make(inlinedynamictypebuilder.java:244)     @ reegnz.dyna.proxy.extractor.methodextractor.main(methodextractor.java:48) 

basically first iterate on method call enough times jvm inflate method (generate generatedmethodaccessor) , try redefine class bytecode.

i tried same method export generated proxy class, , worked flawlessly. that's drove me try this.

it seems delegatingclassloader of generatedmethodaccessor1 class can't reload class when try load class loadclass method.

any ideas how retrieve bytecode generatedmethodaccessor classes?

first of all, nullpointerexception bug, fixed that. loader should have thrown illegalargumentexception instead never got far. bringing attention.

boiled down, problem byte buddy facing that

gma.getclass().getclassloader().findclass(gma.getclass().getname()); 

throws classnotfoundexception. consequence of using delegatingclassloader accessor classes. educated guess, think class loader intends shield classes outside in order make them garbage collectable. however, not allowing lookup of class breaks contract classloader. apart that, assume loading routine refactored use jdk's anonymous class loaders @ point in future (similar classes representing lambda expressions). strangely enough, seems the source code delegatingclassloader not available in jdk though can find in distribution. probably, vm treats these loader specially @ place.

for now, can use following classfiletransformer uses reflection magic on class loader locate loaded class , extract byte array. (the classfilelocator interface takes name instead of loaded class in order allow working unloaded types case. no idea why not work in case.)

class delegateextractor extends classfilelocator.agentbased {    private final classloader classloader;   private final instrumentation instrumentation;    public delegateextractor(classloader classloader, instrumentation instrumentation) {     super(classloader, instrumentation);     this.classloader = classloader;     this.instrumentation = instrumentation;   }    @override   public resolution locate(string typename) {     try {       extractionclassfiletransformer classfiletransformer =            new extractionclassfiletransformer(classloader, typename);       try {         instrumentation.addtransformer(classfiletransformer, true);         // start nasty hack         field field = classloader.class.getdeclaredfield("classes");         field.setaccessible(true);         instrumentation.retransformclasses(             (class<?>) ((vector<?>) field.get(classloader)).get(0));         // end nasty hack         byte[] binaryrepresentation = classfiletransformer.getbinaryrepresentation();         return binaryrepresentation == null           ? resolution.illegal.instance           : new resolution.explicit(binaryrepresentation);       } {         instrumentation.removetransformer(classfiletransformer);       }     } catch (exception ignored) {       return resolution.illegal.instance;     }   } } 

to further simplify code, can use classfilelocators directly instead of applying rewrite matter of fact might modify class file if not apply changes class.


Comments

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

gradle error "Cannot convert the provided notation to a File or URI" -

python - NameError: name 'subprocess' is not defined -