Java反射,更改私有静态最终字段没有执行任何操作

发布于 2025-01-08 03:06:20 字数 1281 浏览 0 评论 0原文

我正在尝试使用 Java Reflection 更改私有静态最终字段。 但它只是失败了。有人有主意吗?

这是我的代码:

public class SecuredClass {
    private static final String securedField = "SecretData";
    public static String getSecretData() { return securedField; }
}

public class ChangeField {
    static void setFinalStatic(Field field, Object newValue) throws Exception
    {
        field.setAccessible(true);

        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~ Modifier.FINAL);

        field.set(null, newValue);
    }

    public static void main(String args[]) throws Exception
    {
        System.out.println("Before = " + SecuredClass.getSecretData());

        Field stringField = SecuredClass.class.getDeclaredField("securedField");
        stringField.setAccessible(true);
        setFinalStatic(stringField, "Screwed Data!");


        System.out.println("After = " + Java_FileMerger_Main.getSecretData());
    }
}

这是我的输出:

Before = SecretData
After = SecretData

我尝试使用 System.setSecurityManager(null); 删除 SecurityManager; 但这并没有改变任何事情。 我知道这很邪恶,但我想让它发挥作用。 我希望有人能帮助我。

I'm trying to change a private static final field with Java Reflection.
But it just fail. Did someone have an idea ?

Here's my code :

public class SecuredClass {
    private static final String securedField = "SecretData";
    public static String getSecretData() { return securedField; }
}

public class ChangeField {
    static void setFinalStatic(Field field, Object newValue) throws Exception
    {
        field.setAccessible(true);

        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~ Modifier.FINAL);

        field.set(null, newValue);
    }

    public static void main(String args[]) throws Exception
    {
        System.out.println("Before = " + SecuredClass.getSecretData());

        Field stringField = SecuredClass.class.getDeclaredField("securedField");
        stringField.setAccessible(true);
        setFinalStatic(stringField, "Screwed Data!");


        System.out.println("After = " + Java_FileMerger_Main.getSecretData());
    }
}

And here's my output :

Before = SecretData
After = SecretData

I've tried to remove the SecurityManager with System.setSecurityManager(null);
But it didn't change anything.
I know this is evil, but i want to get it work.
I hope someone could help me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

当梦初醒 2025-01-15 03:06:20

未定义通过反射更改最终字段的语义(参见 规范)。不保证从字段读取时会看到对最终字段的反射写入。

特别是对于分配了常量的静态最终字段(如您的情况),编译器通常会内联常量,因此在运行时根本不会访问该字段(仅当您使用反射时)。

SecurityManager 在这里不相关。如果 SecurityManager 禁止使用反射,则该操作将引发异常,并且不会静默失败。

问题的答案使用Java反射更改私有静态最终字段 提供更多详细信息,包括一个示例,您可以在其中看到常量内联的字节代码。

The semantics of changing final fields via reflection are not defined (cf. specification). It is not guaranteed that a reflective write to a final field will ever be seen when reading from the field.

Especially with static final fields which have a constant assigned (as in your case), the compiler will often inline the constant and thus the field won't be accessed at all during runtime (only when you use reflection).

The SecurityManager is not relevant here. If using reflection would be forbidden by a SecurityManager, the operation would throw an exception, and not fail silently.

The answers to the question Change private static final field using Java reflection provide some more detail, including an example where you can see in the byte code that constants get inlined.

转瞬即逝 2025-01-15 03:06:20

有一个解决方法可以解决这个问题。如果您在 static {} 块中设置私有静态最终字段的值,它将起作用,因为它不会内联该字段:

private static final String MY_FIELD;

static {
    MY_FIELD = "SomeText"
}

...

Field field = VisitorId.class.getDeclaredField("MY_FIELD");

field.setAccessible(true);
field.set(field, "fakeText");

There is a work around for this. if you set the value of the private static final filed in the static {} block it will work because it will not inline the field:

private static final String MY_FIELD;

static {
    MY_FIELD = "SomeText"
}

...

Field field = VisitorId.class.getDeclaredField("MY_FIELD");

field.setAccessible(true);
field.set(field, "fakeText");
失与倦" 2025-01-15 03:06:20

我对上面给出的例子也有问题。
对我来说,在我没有将字符串定义为文字而是对象之后,它就起作用了。

private static final String SECURED_FIELD = String.valueOf("SecretData");

或者

private static final String SECURED_FIELD = new String("SecretData");

如果您想从文字中受益但我不必关心它,那么这不是最好的解决方案。

I also had problems with the given example above.
For me it worked after I did not define the String as a literal but as an Object.

private static final String SECURED_FIELD = String.valueOf("SecretData");

Or

private static final String SECURED_FIELD = new String("SecretData");

Not the best solution if you want to benefit from literals but I did not have to care about it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文