编译后从字节码中删除注释 [英] post-compilation removal of annotations from byte code

查看:27
本文介绍了编译后从字节码中删除注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用的库包含用 JAXB 注释进行注释的 bean.我们使用这些类的方式并不依赖于 JAXB.换句话说,我们不需要 JAXB,也不依赖注解.

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 and do not depend on the annotations.

然而,由于注解存在,它们最终会被其他处理注解的类引用.这要求我在我们的应用程序中捆绑 JAXB,这是不允许的,因为 JAXB 位于 javax.* 包中(android 不允许核心库"包含在您的应用程序中).

however, because the annotations exist, they end up being referenced by other classes that process annotations. this requires me to bundle JAXB in our application, which isn't allowed, because JAXB is in the javax.* package (android doesn't allow "core libraries" to be included in your application).

因此,考虑到这一点,我正在寻找一种方法来从已编译的字节码中删除注释.我知道有用于操作字节码的实用程序,但这对我来说很新.对此方面的任何帮助将不胜感激.

so, with this in mind, i'm looking for a way to remove the annotations from the compiled byte code. i know there are utilities for manipulating byte code, but this is quite new to me. any help getting started toward this end would be appreciated.

推荐答案

我推荐 BCEL 6.你也可以使用 ASM,但我听说 BCEL 更容易使用.下面是一个快速测试的方法来制作一个最终的字段:

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());
}

当然,您实际上会将您的类作为文件写入磁盘,然后将它们打包,但这更容易尝试.我手边没有 BCEL 6,所以我不能修改这个例子来删除注释,但我想代码应该是这样的:

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<AnnotationEntry> newEntries = new ArrayList<AnnotationEntry>();
                for (AnnotationEntry entry : entries) {
                    if (!entry.getAnnotationType().startsWith("javax")) {
                        newEntries.add(entry);
                    }
                }
                annotations.setAnnotationTable(newEntries);
            }
        }
    }
    return attributes;
}

这篇关于编译后从字节码中删除注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆