`
mingren135
  • 浏览: 72465 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

intern在jdk7的变化

    博客分类:
  • JAVA
 
阅读更多

之前的印象都是string pool分配在perm gen内存中的,也通过intern方法验证过perm gen的oom,今天在用jprofiler观察时却发现是heap一直在做gc,直到报heap oom,还以为是测试代码有误,检查了好久猛然想到会不会是jdk7对intern方法有改变呢?参考http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html,原文如下:

Area: HotSpot
Synopsis: In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.
RFE: 6962931

 

参考这篇文章http://www.tuicool.com/articles/Q73YRf,里面有个案例也很有代表性

String.intern放进的String Pool是一个固定大小的Hashtable,默认值是1009,如果放进String Pool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用String.intern时性能会大幅下降(因为要一个一个找)。 
之前碰到过一个频繁抛异常造成cpu us很高的case: http://bluedavy.me/?p=409 
现在仔细想想,看来当时这个case并不是因为频繁抛异常造成的,而是因为这个case中抛的是NoSuchMethodException,而抛这个异常的原因是因为调用了Class.getMethod找方法没找到,在class.getMethod这方法的实现里会调用name.intern,而很不幸的是这个case里传入的name会根据请求而变,因此导致了String Pool中放入了很多的String,hash冲突严重,链表变长,从而才导致了造成了String.intern过程变得比较耗CPU。

JDK为了解决这个问题,在6u32以及JDK 7的版本里支持了StringTable大小的配置功能,可在启动参数上增加-XX:StringTableSize来设置,不过目前JDK未提供方法来查看StringTable中各桶的链表长度,如果提供这个的话就更好了。

 

 

 

分享到:
评论

相关推荐

    jdk1.8之后的String.intern()方法内存分析

    关于String.intern()方法,这个问题都被问烂了,有的文章在分析的时候还在用jdk1.7,jdk1.8之后内存模型发生了变化,内存的变化也会影响intern方法的执行,这里有必要写文章分析一下,请大家务必从头开始看,这样...

    jdk6-8String类

    在JDK的不同版本中,`String`类经历了一些优化和改进,尤其是在性能和内存管理方面。这里我们将对JDK 1.6、1.7和1.8中的`String`类进行对比研究,探讨其中的关键变化。 ### JDK 1.6中的String 在JDK 1.6中,`...

    jdk1.7+jdk1.8

    安装这两个版本的JDK可以让开发者在同一个系统上同时使用Java 7和Java 8,这对于需要在不同版本之间进行兼容性测试或者比较新旧特性时非常有用。 总之,Java 7和Java 8分别带来了许多改进和新特性,它们对于Java...

    java 常见面试题.pdf

    而在JDK 7及以后的版本中,由于字符串常量池被移至堆中,intern方法的行为也有所变化。 4. 并发编程核心知识点---volatile与Synchronized volatile关键字和synchronized关键字是Java并发编程中用于保证线程安全的...

    尚硅谷面试题第三季1

    【描述】:本题目涉及的是Java基础,特别是关于字符串常量池的使用和理解,以及在JDK7及后续版本中的变化。在Java14环境下,测试结果显示两个使用`intern()`方法的比较都返回了`true`,这与预期的第二个为`false`的...

    通过String.intern()方法浅谈堆中常量池

    【String.intern()方法】 String类的intern()方法在Java中扮演着重要的角色,它涉及到字符串对象的内存管理和...从JDK 7开始,常量池的迁移带来了新的内存管理策略,开发者需要理解这些变化以充分利用Java的性能优势。

    详解Java字符串在内存中的存储位置

    在JDK6中,字符串存储在方法区中的常量池中,在JDK7中,字符串存储在堆中,在JDK8中,字符串可能存储在堆中。 Java字符串在内存中的存储位置是一个复杂的问题,需要根据具体的JDK版本和虚拟机配置来判断。

    StringTable.pdf

    2. **性能影响**:StringTable的大小可以通过`-XX:StringTableSize`设置,默认值在不同版本中有变化。若表大小不足,会导致哈希冲突,降低性能。过度的字符串操作可能导致内存浪费,甚至引发OOM。 3. **优化建议**...

    06-VIP-JVM调优实战及常量池详解(1)1

    在JDK 1.6及以前,字符串常量池位于方法区(也称为永久代),而在JDK 1.7中,随着永久代逐渐被移除,字符串常量池被移到堆中。到了JDK 1.8及以后,永久代完全消失,元空间取代了它的位置,但字符串常量池仍然存在于...

    字符数组的存储方式 字符串常量池.docx

    然而,从JDK7.0开始,`String#intern()`的行为有所变化,使得池中不仅可以存储字符串字面量,还可以存放堆内存中的字符串对象引用。这意味着动态生成的字符串,只要内容相同,也可能被放入字符串常量池。 接下来,...

    搜索推荐Serverless架构和业务中台技术实践.pdf

    7. **标准化算子**: 借鉴Blink,实现业务逻辑的标准化和同步编程体验,通过UDF(用户定义函数)承载业务逻辑,后端全异步执行以优化性能。 8. **全图化**: 将复杂的业务逻辑归一化,使用Reactive编程范式,降低异步...

Global site tag (gtag.js) - Google Analytics