加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-14 16:19:28 所属栏目:Java 来源:网络整理
导读:我知道这通常很愚蠢,但是在阅读这个问题之前不要拍我.我保证我有一个很好的理由需要这样做:) 可以使用反射来修改java中的常规私有字段,但是当尝试为final字段执行相同操作时,Java会引发安全异常. 我会认为这是严格执行的,但是想到我会问,无论如何,以防万一有
我知道这通常很愚蠢,但是在阅读这个问题之前不要拍我.我保证我有一个很好的理由需要这样做:)

可以使用反射来修改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,所以如果一些代码在运行之前可能不一定正常运行….

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读