Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使字符串真正不可变_Java_String_Mutable - Fatal编程技术网

Java 使字符串真正不可变

Java 使字符串真正不可变,java,string,mutable,Java,String,Mutable,我有一个问题,但要得到答案,首先必须接受以下事实:在某些情况下,可以修改Java字符串 这在Artima题为“你好”的文章中得到了证明。等于(“干杯!”)==真的 链接: 它在Java1.6中仍然可以很好地工作,而且它肯定在某种程度上违背了流行的信念,即重复“Java字符串总是不可变的” 所以我的问题很简单:字符串是否可以总是这样修改?是否有任何JVM安全设置可以打开以防止出现这种情况?您需要添加一个SecurityManager。有一个例子和解释: 运行时使用: java -Djava.sec

我有一个问题,但要得到答案,首先必须接受以下事实:在某些情况下,可以修改Java字符串

这在Artima题为“你好”的文章中得到了证明。等于(“干杯!”)==真的

链接:

它在Java1.6中仍然可以很好地工作,而且它肯定在某种程度上违背了流行的信念,即重复“Java字符串总是不可变的”


所以我的问题很简单:字符串是否可以总是这样修改?是否有任何JVM安全设置可以打开以防止出现这种情况?

您需要添加一个SecurityManager。有一个例子和解释:

运行时使用:

java -Djava.security.manager UseReflection
以及守则:

import java.lang.reflect.Field;
import java.security.Permission;

public class UseReflection {
    static{
        try {
            System.setSecurityManager(new MySecurityManager());
        } catch (SecurityException se) {
            System.out.println("SecurityManager already set!");
        }

    }
    public static void main(String args[]) {
        Object prey = new Prey();
        try {
            Field pf = prey.getClass().getDeclaredField("privateString");
            pf.setAccessible(true);
            pf.set(prey, "Aminur test");
            System.out.println(pf.get(prey));
        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }

    }
}

class Prey {
    private String privateString = "privateValue";
}

class MySecurityManager extends SecurityManager {
     public void checkPermission(Permission perm) {
         if(perm.getName().equals("suppressAccessChecks")){
             throw new SecurityException("Can not change the permission dude.!");
         }

     }
}

所有反射操作都要经过您安装的
SecurityManager
的检查


如果你担心恶意代码,你必须有一个
SecurityManager
。如果不是,那我就不麻烦了。如果人们如此拼命地想射中自己的脚,应该允许他们射中自己的脚。

据我所知(但我可能错了),这是通过使用反射访问底层的char[]数组来实现的,因为数组内容在Java中无法保持不变,所以这种攻击确实有效。那么,可以采取什么措施来阻止访问该字符[]?我想您可以随时关闭“Hacking Java Internals”开关,一切都会很好。因此,您正在尝试防止出现错误。好吧,祝你好运。我不认为语言设计者能为这样的场景提供一个防白痴的设计。总是可以选择深入本机代码并开始修改随机内存位置…@pap不,没有。如果您接受来自不可靠来源的代码(某些系统必须这样做),那么您应该能够在虚拟机中隔离它们。事实上,这是可能的。技术上正确的答案。但是,我怀疑在生产中使用此SecurityManager是否值得它可能带来的麻烦。我无法列出运行时可能需要
suppressAccessChecks
ReflectPermission
的库/API列表,但我怀疑一些应用程序服务器可能会崩溃,所有这些只是为了防止一些恶意代码运行,有相当多的库可能依赖于这种行为,例如Wicket的PropertyModel。@Vinet Reynolds希望您不是在设计云服务器。:)@biziclop,你的评论可能很搞笑,但在某种程度上也是深思熟虑的。如果GAE有这个安全管理器呢?我可以想象结果会是一个安全剧场。@Vineet Reynolds我不是个人的意思,只是你评论中“只是为了防止一些流氓代码运行”部分引发的一个笑话。在大多数情况下,这一风险可以忽略不计,但在某些特殊领域,这一风险非常重要。不管怎样,您所说的很有趣:为什么关闭封装中的漏洞会成为一个安全剧场?