post-compilation removal of annotations from byte code

前端 未结 4 2164
太阳男子
太阳男子 2021-02-08 15:50

we are using a library that contains beans that are annotated with JAXB annotations. nothing in the way we use these classes depends on JAXB. in other words, we don\'t need JAXB

4条回答
  •  孤独总比滥情好
    2021-02-08 16:23

    I recommend BCEL 6. You can also use ASM, but I hear BCEL is easier to use. Here is a quick test method for making a field final:

    public static void main(String[] args) throws Exception {
        System.out.println(F.class.getField("a").getModifiers());
        JavaClass aClass = Repository.lookupClass(F.class);
        ClassGen aGen = new ClassGen(aClass);
        for (Field field : aGen.getFields()) {
            if (field.getName().equals("a")) {
                int mods = field.getModifiers();
                field.setModifiers(mods | Modifier.FINAL);
            }
        }
        final byte[] classBytes = aGen.getJavaClass().getBytes();
        ClassLoader cl = new ClassLoader(null) {
            @Override
            protected synchronized Class findClass(String name) throws ClassNotFoundException {
                return defineClass("F", classBytes, 0, classBytes.length);
            }
        };
        Class fWithoutDeprecated = cl.loadClass("F");
        System.out.println(fWithoutDeprecated.getField("a").getModifiers());
    }
    

    Of course, you would actually write your classes out to disk as files and then jar them up but this is easier for trying things out. I don't have BCEL 6 handy, so I can't modify this example to remove annotations, but I imagine the code would be something like:

    public static void main(String[] args) throws Exception {
        ...
        ClassGen aGen = new ClassGen(aClass);
        aGen.setAttributes(cleanupAttributes(aGen.getAttributes()));
        aGen.getFields();
        for (Field field : aGen.getFields()) {
            field.setAttributes(cleanupAttributes(field.getAttributes()));
        }
        for (Method method : aGen.getMethods()) {
            method.setAttributes(cleanupAttributes(method.getAttributes()));
        }
        ...
    }
    
    private Attribute[] cleanupAttributes(Attribute[] attributes) {
        for (Attribute attribute : attributes) {
            if (attribute instanceof Annotations) {
                Annotations annotations = (Annotations) attribute;
                if (annotations.isRuntimeVisible()) {
                    AnnotationEntry[] entries = annotations.getAnnotationEntries();
                    List newEntries = new ArrayList();
                    for (AnnotationEntry entry : entries) {
                        if (!entry.getAnnotationType().startsWith("javax")) {
                            newEntries.add(entry);
                        }
                    }
                    annotations.setAnnotationTable(newEntries);
                }
            }
        }
        return attributes;
    }
    

提交回复
热议问题