Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get bytecode of cglib proxy class instance?

I'm trying to get bytecode of cglib enhanced object this way using BCEL:

package app;

import cglib.MyInterceptor;
import net.sf.cglib.proxy.Enhancer;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import service.Tool;

public class CgLibApp {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        // target object
        Tool tool = new Tool();

        // proxying
        Enhancer e = new Enhancer();
        e.setSuperclass(tool.getClass());
        e.setCallback(new MyInterceptor(tool));
        Tool proxifiedTool = (Tool) e.create();

        // trying to get proxy byte code
        JavaClass clazz = Repository.lookupClass(proxifiedTool.getClass());
        Method method = clazz.getMethod(Tool.class.getMethod("meth"));

        System.out.println(method.getCode().toString());
    }
}

But I'm getting:

Exception in thread "main" java.lang.ClassNotFoundException: SyntheticRepository could not load service.Tool$$EnhancerByCGLIB$$22a3afcc
at org.apache.bcel.util.SyntheticRepository.loadClass(SyntheticRepository.java:174)
at org.apache.bcel.util.SyntheticRepository.loadClass(SyntheticRepository.java:158)
at org.apache.bcel.Repository.lookupClass(Repository.java:74)
at app.CgLibApp.main(CgLibApp.java:21)

What should I do to get bytecode from Enhanced object?

like image 513
corvax Avatar asked Sep 08 '25 11:09

corvax


1 Answers

I've found this question while researching how to save the CGLIB-generated class in spring-boot 3.0 application (e.g. handling @Transactional or @Configuration-annotated classes). This simple approach may help:

import org.springframework.cglib.core.ReflectUtils;
...
public class SpringCglibUtils {
    public static void initGeneratedClassHandler(String targetPath) {
        File dir = new File(targetPath);
        dir.mkdirs();
        ReflectUtils.setGeneratedClassHandler((String className, byte[] classContent) -> {
            try (FileOutputStream out = new FileOutputStream(new File(dir, className + ".class"))) {
                out.write(classContent);
            } catch (IOException e) {
                throw new UncheckedIOException("Error while storing " + className, e);
            }
        });
    }
}

and then define in your main class before creating context:

SpringCglibUtils.initGeneratedClassHandler("cglib");

Spring will store to the targetPath directory all generated class files.

Note: unfortunately it's not available before spring-boot 3

like image 57
seregamorph Avatar answered Sep 10 '25 03:09

seregamorph