如果我使用中的String.intern()来提高性能,因为我可以用“==”来比较实习字符串,将我碰上垃圾收集问题? interned字符串的垃圾收集机制与普通字符串有什么不同?的String.intern垃圾收集行为()
回答
其实,这不是一个垃圾收集优化,而是一个字符串池优化。 当你调用String.intern()
,你与它的基本参考(遇到这个字符串的第一次引用或参考这个,如果它还不知道)代替参考您的初始字符串。
然而,它会成为一个垃圾收集问题,一旦你的字符串是在应用不再使用,因为实习串池是String类的静态成员,永远不会被垃圾收集。
作为一个经验法则,我认为preferrable到从未使用这种实习方式,让编译器仅使用它的常量字符串,这些声明如下:
String myString = "a constant that will be interned";
这是更好的,在意识到它不会让你做假设==
可以工作时,它不会。
此外,事实上,String.equals
潜在地调用==
作为优化,使其确实interned字符串优化是在引擎盖下使用。这是一个更多的证据==
应该从未在字符串中使用。
我不明白,为什么你的示例中的myString会被拦截?也许如果我们将其标记为最终,那么它将被实施。 – 2010-03-12 09:37:29
@Ravi:实习生的JavaDoc(http://java.sun.com/javase/6/docs/api/)说:“所有文字字符串都是实习生。” – 2010-03-12 09:40:11
+1表示“不要使用==表示字符串”。这可能会发展成一个坏习惯。 – Thilo 2010-03-12 10:00:34
String.intern()
管理内部,本地实现的游泳池,里面有一些特殊的GC-相关的功能。这是旧的代码,但如果它被重新实现,它也使用java.util.WeakHashMap
。弱引用是一种保持指向对象的指针而不阻止它被收集的方法。对于一个统一的池(如interned字符串)来说,这是正确的。
那实习的字符串是收集可以用下面的Java代码来证明垃圾:
public class InternedStringsAreCollected {
public static void main(String[] args)
{
for (int i = 0; i < 30; i ++) {
foo();
System.gc();
}
}
private static void foo()
{
char[] tc = new char[10];
for (int i = 0; i < tc.length; i ++)
tc[i] = (char)(i * 136757);
String s = new String(tc).intern();
System.out.println(System.identityHashCode(s));
}
}
此代码创建相同的字符串30次,每次实习吧。同时,它采用System.identityHashCode()
显示什么哈希码Object.hashCode()
将会对实习返回的字符串。运行时,此代码打印出不同的整数值,这意味着每次都不会获得相同的实例。
无论如何,String.intern()
用法有些气馁。它是一个共享的静态池,这意味着它很容易变成多核系统的瓶颈。使用String.equals()
比较字符串,你会活得更长,更快乐。
请问为什么这会变成多核系统的瓶颈或提到一个指针? – Sergio 2013-12-28 22:24:51
如果两个线程在恰好具有相同内容的两个字符串上调用'String.intern()',则它们都必须获得相同的引用。这必然意味着两个核心之间的某种沟通。实际上,'String.intern()'是通过一个由互斥锁保护的散列表实现的,每个访问(读或写)都会锁定互斥锁。这个互斥体可能存在争用,但是大部分的放缓都是由于核心必须同步它们的L1缓存(这种同步被互斥锁定所隐含,并且是昂贵的部分)。 – 2013-12-29 14:00:04
为什么实习表不能只是一个ConcurrentHashMap? – user833771 2017-03-29 19:54:16
请阅读:http://satukubik.com/2009/01/06/java-tips-memory-optimization-for-string/
我可以从你的信息中得到的结论是:你实习太多字符串。如果你真的需要实习生这么多的字符串进行性能优化,增加烫发根内存,但如果我是你,我将检查第一,如果我真的需要这么多的实习字符串。
@ nanda博客条目的正确链接似乎是:http://blog.firdau.si/2009/01/06/java-tips-memory-optimization-for-string/ – 2011-09-30 21:59:39
This article提供了完整的答案。
在java 6中,字符串池驻留在PermGen中,因为java 7字符串池驻留在堆内存中。
手动截取的字符串将被垃圾收集。
如果定义它们的类被卸载,则字符串文字将仅被垃圾收集。
字符串池是一个固定大小的HashMap,它在java 6和早期版本的java 7中很小,但自java 7u40以来增加到60013。
可以使用更改-XX:StringTableSize = <新大小>并使用查看-XX:+ PrintFlagsFinal java选项。
- 1. 垃圾收集
- 2. 不同的垃圾收集行为
- 3. jstat为G1垃圾收集
- 4. 关于垃圾收集行为查询
- 5. 垃圾收集java
- 6. DoctrineCommonCache垃圾收集?
- 7. Java垃圾收集
- 8. 垃圾收集器
- 9. C#垃圾收集
- 10. Java垃圾收集
- 11. WeakEvent垃圾收集
- 12. GWT垃圾收集
- 13. 垃圾收集YGCT和垃圾收集时间不断上升
- 14. 垃圾回收行为
- 15. 数量的垃圾收集
- 16. 有效的垃圾收集
- 17. dalvik vm的垃圾收集
- 18. bash中的垃圾收集
- 19. 的Java newSingleThreadExecutor垃圾收集
- 20. Node.js的垃圾收集器
- 21. Objective-C的垃圾收集
- 22. System.gc()的垃圾收集
- 23. 垃圾收集的OutOfMemoryError
- 24. C#中的垃圾收集#
- 25. 的Python:垃圾收集
- 26. 评估之前应该对垃圾收集功能进行垃圾收集吗?
- 27. 垃圾收集:将对象收集
- 28. 垃圾收集是由
- 29. 垃圾收集提交git
- 30. 从垃圾收集日志
这个问题可能是相关http://stackoverflow.com/questions/372547 – 2010-03-12 09:23:53
参见https://stackoverflow.com/questions/18152560/garbage-collection-on-internd-strings-string-pool-and- perm-space – Vadzim 2017-11-11 11:50:51