欢迎来到天天文库
浏览记录
ID:31283331
大小:77.50 KB
页数:3页
时间:2019-01-08
《java的string对象不可修改?-编程开发技术》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、Java的String对象不可修改?-编程开发技术Java的String对象不可修改?木文由ImportNew・LynnShaw翻译自cupo巧avasite。欢迎加入翻译小组。转载请见文末要求。Java字符串是final且不可变的。不过,它的内容可以被修改。java的生态系统很庞大。大量的新内容始终在产生。紧跟潮流并口记住那些并不会立即使用的东西是很困难的。就我而言,我不停地阅读面试问题,博客以及群组讨论。有时候会碰到我忘了的知识,有时会学习新的知识…有时我看到的答案,嗯,恕我直言,不太准确,或者不完整甚至是错误的。前-段吋间我遇到了这个问题:“为什么ja
2、va字符串是final且不可变的?”。被推荐的原因是线程安全、性能和安全性。我完全同意第一个原因;如果冇像String-样被大量使用的,在多线程中为了安全使用就需要某种同步,这简直是噩梦。笫二个原因我不太确定。《Java并发编程实践》提到了不可变对彖有性能优势,但是《Java性能权威手册》的作者指出在现代JVM屮,这是不正确的。这两个來源都很口J靠,我不知道JVM内部能够为我做出决定。也许不变性没冇宜接的优点。JIT会生成相同的代码,解释器会以相同的方式工作。然而,一个情况是不可变性对垃圾回收机制来说无疑是冇利的:不可变对彖的容器和最年轻的对彖一样“年轻”,
3、所以我可以很容易地猜想到minorcollection跳过整个容器的垃圾收集(GC)。当然了,更少的对象就意味着更少的时间…所以,字符串容器会被跳过不被扫描到。而11,String类在Ja眩早期就被这样设计了。也许是因为在某些时候可变对象会有一些性能损失,所以String被这样设计。那么,JVM这样不断发展后,没冇理由再改变String类了。所以,我假设这个原因是合理的。但第三个原因一String类设计成不可改变和final是为了安全,这一点对我來说绝对是错误的。这个答案的一个例子是通过类名加载类,类名就是一个Stringo如果一个黑客可以在类加载器加载字节
4、码之前改变它,那这就是一个安全漏洞。恕我直言这个原因是有漏洞的,因为如果一•个黑客可以在你的JVPp运行任意代码,那你可能有一个比String不变性更大的问题需要“防卫”。另一方面,如果你想搬起石头砸口己脚,谁能阻止你这样做?毕竞这是你的JVM。有了这个感觉后,我问了自己一个源于“安全假设”的问题:String不可变的设计是否真的意味着一个String对象的内容在其被创建后就不能再被替换了吗?止如你将在下面看到,答案当然是可以。首先,任何东西都可以靠JNI改变。一旦冇调用C语言,你将在很多方而打破很多事情我其至无法数清…所以,我们先把这个放一边,使用纯Ja
5、va来对一个字符串的内容做修改。这不困难,下而是一个概念证明:publicclassStringModifier{publicstaticvoidmain(String[]str){try{Stringtest=/,aaaa,z;StringStringStringtest2test3test4Fieldvalues二test;二newString(test);=newString(test・toCharArray());=String・class・getDeclarcdFicld(,zvaluez,);values.setAccessible(true);
6、char[]ref=(char[])values,get(test);ref[0]二’b';System,out.println(〃3aaa"+test+""+test2+""+test3+""+test4);}catch(NoSuchFieldException
7、SecuriLyExceptionIllegalArgumentException:IllegalAccessExceptionex){}}}输出是:baaabaaabaaabaaaaaaa它仅仅用了4行代码来修改一个字符串内容。不论这个字符串是在-•个常量池里述是分配到了堆上。所有的别名都“看见
8、”了引用对象发生的变化。顺便说,在printlnO字符串文木的后面加+””,就可以使输出变为aaaabaaabaaaaaaa0这种变化发生的原因是java在编译吋连接“眈眈”和””,因此在字符串常量池上就有“aaaa”和“aaaa”。这个“发现”引发了下面的问题:这个发现可以利用吗?我想有时是可以的。举个例了,当把敏感信息存储在字符串:如果我们已经不需要这个信息了,还将这个信息保留绝对是糟糕的做法。只有垃圾冋收机制能决定什么时候冋收一个未引用对彖的内存,所以你宝贵的信息将可能比你想象屮存在得更久一点。但是一些API需要密码作为方法参数的字符串;冇时从环境中传
9、递参数等等。在这种强制使用字符串的情况下,你可以通过
此文档下载收益归作者所有