有没有办法从课外修改Java中的“private static final”字段的值?

前端之家收集整理的这篇文章主要介绍了有没有办法从课外修改Java中的“private static final”字段的值?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我知道这通常很愚蠢,但是在阅读这个问题之前不要拍我.我保证我有一个很好的理由需要这样做:)

可以使用反射来修改java中的常规私有字段,但是当尝试为final字段执行相同操作时,Java会引发安全异常.

我会认为这是严格执行的,但是想到我会问,无论如何,以防万一有人想出了一个黑客这样做.

让我们说我有一个外部库与类“SomeClass”

public class SomeClass 
{
  private static final SomeClass INSTANCE = new SomeClass()

  public static SomeClass getInstance(){ 
      return INSTANCE; 
  }

  public Object doSomething(){
    // Do some stuff here 
  }
}

我本来想要Monkey-Patch SomeClass,以便我可以执行我自己的doSomething()版本.既然没有(据我所知)任何方式在java中真正做到这一点,我唯一的解决办法是改变INSTANCE的值,所以它返回我的版本的类与修改方法.

本质上,我只想用安全检查包裹呼叫,然后调用原始方法.

外部库总是使用getInstance()来获取这个类的一个实例(即它是一个单例).

编辑:只是为了澄清,getInstance()由外部库调用,而不是我的代码,所以只是子类化不会解决问题.

如果我不能这样做,我可以想到的唯一的其他解决方案是复制粘贴整个类并修改方法.这不是理想的,因为我必须保持我的叉最新的图书馆的更改.如果有人有更多的可维护性,我可以接受建议.

解决方法

有可能的.我已经用这个来阻止在webapps中卸载类的调皮的threadlocals.您只需要使用反射来删除最终的修饰符,那么可以修改该字段.

这样的事情会做到这一点:

private void killThreadLocal(String klazzName,String fieldName) {
    Field field = Class.forName(klazzName).getDeclaredField(fieldName);
    field.setAccessible(true);  
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    int modifiers = modifiersField.getInt(field);
    modifiers &= ~Modifier.FINAL;
    modifiersField.setInt(field,modifiers);
    field.set(null,null);
}

有一些高速缓存还有Field#set,所以如果一些代码在运行之前可能不一定正常运行….

猜你在找的Java相关文章