gpt4 book ai didi

javassist 字段检查初始化

转载 作者:行者123 更新时间:2023-12-01 14:44:55 26 4
gpt4 key购买 nike

我目前正在实现一个注释,强制字段通过 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com