javassist 字段检查初始化

标签 java reflection initialization field javassist

我目前正在实现一个注释,强制字段通过 javassist 遵守条件。我想检查一个字段在读取时是否已初始化...因此,目前,我通过在虚拟机通过 Translator.onLoad(ClassPool pool, String className) 加载类时加载它们来获取类。 ,并使用 ExprEditor通过覆盖 edit(FieldAccess arg) 在每个类上方法。现在,我设法通过在 onLoad 中运行以下方法来注入(inject)代码来检查条件:

    private void processFields(FieldsAndMethods data) {
        final FieldsAndMethods copy = data;
        Stack<CtClass> classes = data.getThisClass();
        for(CtClass cc : classes ){
            try {
                cc.instrument(new ExprEditor(){

                @Override
                public void edit(FieldAccess arg) throws CannotCompileException{
                   try{
                        CtField field = arg.getField();
                        if(copy.getFields().contains(field) &&
                           field.hasAnnotation(Assertion.class)){

                            Assertion a =
                                ((Assertion)field.getAnnotation(Assertion.class))   
                            String condition = assertion.value();
                            String fieldName = field.getName();
                            String processCondition = 
                                transformCondition(condition, fieldName);

                            if(arg.isWriter()){

                                String code = "{if(" + evaledCondition + ")" +                                         
                                              "$proceed($$) ;" +
                                              "else throw new " + 
                                              "RuntimeException(\"The assertion " + 
                                                   condition + " is false.\");}";                                                                               
                                arg.replace(code);

            }else if (arg.isReader()){
                                //Here is where I would like to check if the field 
                                //has been initialized... 
            }

                        }catch(ClassNotFoundException e){
                            System.out.println("could not find Annotation " + 
                            Assertion.class.getName() );
                        }catch(NotFoundException e){
                            System.out.println("could not find field " + 
                            arg.getFieldName() );
                        }                                       
                    }
                });
            } catch (CannotCompileException e) {                
                System.out.println("Could not interpret the expression");
                System.out.println(e);
            }
        }       
    }

    private String transformCondition(String condition, String fieldName){
        return condition.replace(fieldName, "$1");      
    }

您能否为我指出正确的方向,以查找字段是否已初始化?请注意,字段可以是原始字段,也可以不是。

提前致谢。

最佳答案

假设

我假设如下:

  • 通过字段初始化,我们正在讨论为空的字段。

  • 基本类型不能为 null,因此无需检查它们。

代码

此示例验证适用于静态和非静态字段。

为了提高可读性,我还在几行中创建了代码字符串。作为 arg 一个 FieldAccess 对象,您可以编写以下内容:

 if (arg.isReader() && !arg.getField().getType().isPrimitive()) {
  String code = "{ java.lang.Object var = $proceed();"
               +  "if(var == null) {"
                   + "java.lang.System.out.println(\"not initialized " + arg.getFieldName() + "\");"
               +  "}"
               + "$_=var;}";
            arg.replace(code);
        }

代码说明

如您所见,在这个小示例中,我使用了一些 javassist 标识符,有关此内容的完整引用,请阅读 javassist official tutorial (我链接到有关代码修改的部分)。

以下是所使用的每个标识符的含义:

  • $proceed():在字段访问的情况下,返回字段的值。
  • $_:这是在读取模式下编辑 FieldAccess 时必需的标识符。该 token 保存将用于设置字段的值。

有了这些信息,就很容易理解代码的想法:

  1. 将字段值放入名为 var 的辅助对象
  2. 检查该字段是否为空,如果是则打印带有字段名称的警告
  3. 使用值设置字段名称(可以为 null,也可以为非 null);

我想这已经为您指明了正确的方向。但如果您还需要任何其他信息,请告诉我。

关于javassist 字段检查初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15531585/

相关文章:

java - 可以在主类中初始化所有类吗?

c# - 当我们可以用纯反射做同样的事情时为什么要使用 PrivateObject

c# - 基类中带有表达式树的字段 getter/setter

java - 是否需要调用构造函数将变量初始化为默认值?

java - 通过 ButtonClick 隐藏 JTable 中的多个元素

java - Apache HttpClient 连接配置

java - 我如何将java对象从服务器端传递到客户端

java - 如何在java中使用同一个套接字连接进行多个http请求?

java - 有没有办法将 String 对象分配为自定义类实例?

c++ - 包裹在共享指针中时的 vector 构造