gpt4 book ai didi

java - Java 字符串并非真正不可变的含义是什么?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:09:26 25 4
gpt4 key购买 nike

背景

在 Java 101 中,我们被教导:

A String is immutable.



是的。好的。谢谢。

然后我们进入 Java 102(或者 Java 201),我们发现:

A String isn't really immutable: you can change it using reflection.



啊。美好的。要么很可爱,要么非常反常,这取决于你的观点。

到目前为止,这些东西已经 discussed ad infinitum在 Stack Overflow 和其他地方。在提出这个问题时,我认为这是理所当然的。

我有兴趣问的是:

问题

Once we discover that a String isn't really immutable, what are the implications for how we should write our code?



让我从两个方面更具体地说明这一点。

JVM 沙盒

恶意类是否有可能使用此技巧来破坏 JVM 的安全性,并使用它不应该使用的技巧?例如,JDK 中是否有 String 的地方?是从一个方法返回的,并且只有在它不能被改变的假设下它才是安全的?

这是一个充满希望的开始:
    String prop = "java.version";
// retrieve a System property as a String
String s = System.getProperty(prop);
System.out.println(s);
// now mess with it
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char[] value = (char[])field.get(s);
value[0] = 'x';
//turns out we've changed not just the String we were
//given but the underlying property too!
System.out.println(System.getProperty(prop));

它的作用是从 JVM 中检索系统属性,该属性作为 String 返回。 ,然后更改 String ;结果是基础属性也发生了变化。这可以用来肆虐吗?

我不确定。值得注意的是,您必须具有执行反射的正确权限。到那时安全游戏已经开始了吗?它允许我在这里绕过没有更改安全属性的权限,但这是意料之中的,还是有问题?

有没有办法扩展它来做更糟糕的事情?

防御性克隆

我们总是被告知在将数组和其他对象传递给可能修改它们的方法之前克隆它们是个好主意,除非我们希望它们被修改。这只是良好的编码习惯。如果你把你的数组的唯一副本给了某人,然后它回来了,那是你自己的愚蠢错误。

但看起来似乎同样的论点应该适用于 String !我从来没有听说过有人说我们应该克隆 String在将其传递给其他人编写的方法之前。但这有什么不同,如果是 String和数组一样可变吗?

支持防御性克隆字符串的论据

如果防御性克隆就是不知道一个方法可能对我们传递的东西做什么,并且如果我们传递的东西是可变的,那么我们应该克隆它。如果代码可能是恶意的,那么它可能会更改 String ;所以每当重要的时候 String保持不变,我们应该确保我们发送的是副本而不是真实的东西。

如果我们不相信不受信任的代码不会对 String 做坏事,那么说不受信任的代码应该在安全管理器下运行并没有错。 .如果 String 是真的,对于数组来说是正确的;但是从来没有人说只有在您还使用安全管理器锁定代码的情况下才可以克隆数组和其他对象。

反对防御性克隆字符串的论据

一个数组可能会因为草率的编码而被修改;换句话说,它可能会被无意修改。但没有人改变 String无意中:它只能通过偷偷摸摸的技巧来完成,这意味着程序员试图打破不变性。

这使得两种情况不同。我们真的不应该将数组,甚至是它的克隆传递给我们在任何级别都不信任的代码。您不会从某个狡猾的地方下载库,然后认为您没问题,因为您克隆了您的阵列。您进行防御性克隆是因为您认为程序员可能会犯错误或对您发送的数据允许的内容做出与您不同的假设。如果您担心代码可能会被修改 String在你背后,你真的不应该运行代码。通过克隆 String 实现的所有功能是性能开销。

答案?

我们应该如何思考这个问题?使用这些技巧可以破坏 JVM 沙箱吗?我们是否应该根据 String 的可变性进行防御性编码? ,或者这都是红鲱鱼?

最佳答案

可以为您的 Java 程序启用一个安全设置。根据Javadocs for setAccessible ,

First, if there is a security manager, its checkPermission method is called with a ReflectPermission("suppressAccessChecks") permission.

A SecurityException is raised if flag is true but accessibility of this object may not be changed (for example, if this element object is a Constructor object for the class Class).

A SecurityException is raised if this object is a Constructor object for the class java.lang.Class, and flag is true.


所以,有了 SecurityManager如果不允许此检查,您可以阻止任何代码成功调用 setAccessible ,保留 String 的不变性s。

关于java - Java 字符串并非真正不可变的含义是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26245388/

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