Alter value of a static field during class loading

2019-10-21 06:57发布

我们有一个Java程序调用类X. X类的一些方法有哪些决定应线程等待多长时间在一些错误的情况下超时静态字段。 现在,我要换值,而不改变我的Java程序(我不想部署,而这种变化是实验性的)。 我如何可以使用Java代理,以更改此超时值,说1分(1 * 60 * 1000)

Class X {
    ....
    // timeout = 5 minutes
    private static long timeout = 5*60*1000;
    ....
}

总之,如何编写Java代理,以更改一个静态变量的值。 我已经经历了一些教程去了,但这些都不解释如何做到这一点。 我没有访问的主要方法。 该项目是由IOC容器中运行。

谢谢,

仙人

Answer 1:

使用反射,你可以很容易地实现这一点:

class EasyFieldAlterationAgent {
  public static void premain(String args) throws Exception {
    Field field = X.class.getDeclaredField("timeout");
    field.setAccessible(true);
    field.setValue(null, 42L); // set your value here.
  }
}

请注意,这不会改变之前的场,但类加载时间之后 。 如果这是不可能的你一起工作,你也可能只是重新定义类本身我只想建议,如果:

  1. 您的安全设置不允许你使用反射。
  2. 你需要befor执行类的类型初始化更改值。

如果你想在加载该类之前 ,真正改变的领域,你是幸运的,以至于你想改变一个字段是两者的价值static和限定原始值。 这样的字段直接在外地的网站存储的值。 使用代理,你可以定义一个ClassFileTransformer ,简单地改变磁场对飞的价值。 ASM是实现这样一个简单的转换的好工具。 使用这个工具,你可以大致实现你的代理如下:

class FieldAlterationAgent {
  public static void premain(String args, Instrumentation inst) {
    instrumentation.addTransformer(new ClassFileTransformer() {
      @Override
      public void byte[] transform(ClassLoader loader,
                                   String className,
                                   Class<?> classBeingRedefined,
                                   ProtectionDomain protectionDomain,
                                   byte[] classfileBuffer)
          throws IllegalClassFormatException {
        if (!className.equals("X") {
          return classFileBuffer;
        }
        ClassWriter classWriter = new ClassWriter(new ClassVisitor() {
          @Override
          public FieldVisitor visitField(int access, 
                                         String name, 
                                         String desc, 
                                         String signature, 
                                         Object value) {
            if(name.equals("timeout") {
              value = 42L; // set value here, make sure its a long!
            }
            return super.visitField(access, name, desc, signature, value);
          }
        }, 0);
        new ClassReader(classFileBuffer).accept(classWriter);
        return classWriter.toByteArray();
      }
    });
  }
}

你可以说这后一个版本需要更多的代码,并要求您的代理人连同其ASM依赖包装。

要应用代理,要么把类一个jar文件,并把它放到剂路径 。



文章来源: Alter value of a static field during class loading using a Java agent