gpt4 book ai didi

java - 有什么方法可以从类外修改 Java 中 `private static final` 字段的值吗?

转载 作者:搜寻专家 更新时间:2023-10-30 21:24:39 26 4
gpt4 key购买 nike

我知道这通常很愚蠢,但在阅读问题之前不要开枪。我保证我有充分的理由需要这样做:)

可以使用反射修改 java 中的常规私有(private)字段,但是当尝试对 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() 是由外部库调用的,而不是我的代码,因此仅子类化无法解决问题。

如果我做不到,我能想到的唯一其他解决方案是复制粘贴整个类并修改方法。这并不理想,因为我必须使我的 fork 与库的更改保持同步。如果有人有更易于维护的东西,我愿意接受建议。

最佳答案

这是可能的。我用它来 monkeypatch 顽皮的 threadlocals,它们阻止了 webapps 中的类卸载。你只需要用反射去掉final修饰符,就可以修改字段了。

像这样的东西就可以了:

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 - 有什么方法可以从类外修改 Java 中 `private static final` 字段的值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/767008/

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