intern()函数消除了应用程序中的重复字符串对象,并有可能减少应用程序内存的整体消耗。
intern()**是java.lang.String对象中的一个有趣的函数。intern()函数消除了应用程序中的重复字符串对象,并有可能减少应用程序的整体内存消耗。在这篇文章中,让我们了解更多关于这个intern()函数的信息。
1.String intern()函数如何工作?
在Java堆内存中,维护一个字符串对象池。当您在字符串对象上调用intern()函数时,JVM将检查此字符串对象是否已经在池中存在。如果它存在,则将同一对象返回给调用者。如果字符串对象不存在,则将此字符串对象添加到池中,新添加的字符串对象将返回给调用者。
通过示例和图片学习总是很容易的。让我们来做,看看下面的代码片段:
String s1 = new String("yCrash").intern();
String s2 = new String("yCrash").intern();
*最初启动时的JVM堆内存*
应用程序创建的所有对象都存储在JVM的堆内存中。这个JVM堆内存内部有一个字符串对象池。当您最初启动程序时,JVM的堆内存将没有字符串对象。
执行String s1 = new String( "yCrash”).intern();时JVM堆内存
当第一个语句String s1 = new String(" yCrash ").intern();时,JVM将检查yCrash字符串对象是否存在于初始字符串池中。因为它不存在,这个yCrash字符串将被添加到初始字符串池中,这个新创建的字符串对象的引用将返回给s1。
执行String s2 = new String(“yCrash”).intern();时,JVM堆内存
当第二个语句String s2 = new String(" yCrash ").intern();时,JVM将再次检查yCrash字符串对象是否存在于初始字符串池中。这一次,yCrash字符串对象出现在初始字符串池中,因为它是在执行语句#1时添加的。现在,这个旧字符串对象的引用将返回给s2。s1和s2都将指向同一个yCrash字符串对象。因此,在语句#2中创建的重复字符串对象yCrash将被丢弃。
2.没有intern()函数的字符串如何工作
String s3 = new String("yCrash");
String s4 = new String("yCrash");
执行String s3 = new String(“yCrash”);时的JVM堆内存
当第一个语句String s3 = new String(“yCrash”);执行时,JVM会将yCrash字符串对象添加到堆内存中,但不会在初始字符串池中。
执行String s4 = new String(“yCrash”);时的JVM堆内存
当第二个语句String s4 = new String(“yCrash”);执行时,JVM将在堆内存中创建一个newyCrash字符串对象。因此,将在内存中创建重复的yCrash。如果您的应用程序在不调用intern()的情况下创建n个yCrash对象,则将在内存中创建n个yCrash字符串对象。这将导致相当多的内存浪费。
3. intern() 的 == 怎么工作
由于s1和s2指向相同的yCrash字符串对象,当您调用s1和s2之间的==操作时,如下所示,您将得到true。
// true will be printed
System.out.println(s1 == s2);
由于s3和s4指向两个不同的yCrash字符串对象,当您调用s3和s4之间的==操作时,如下所示,您将得到false。
// false will be printed
System.out.println(s3 == s4);
4. JVM内存区域初始字符串池的存储位置
JVM内存具有以下区域:
- 堆区(即年轻一代+老一代)
- 元空间
- 其他地区
在从1到6的早期Java版本中,string intern池存储在 永久代(Perm Generation) 中。从Java 7开始,String intern池存储在JVM的堆内存中。
5.使用intern()还是-XX:+UseStringDeduplication更好?
当您在应用程序启动期间传递-XX:+UseStringDeduplication JVM参数时,JVM将尝试消除重复字符串,作为垃圾收集过程的一部分。在垃圾收集过程中,JVM检查内存中的所有对象。作为这个过程的一部分,它试图识别其中的重复字符串并试图消除它们。但是,使用-XX:+UseStringDeduplication JVM参数有一定的限制。例如,它将只与G1 GC算法一起工作,并且只在永久代字符串对象上消除重复。下面是一个主要应用程序的有趣案例研究,该应用程序试图使用-XX:+UseStringDeduplication JVM参数。
另一方面,intern()函数可以用于任何GC算法,也可以用于短期对象和长期对象。但是,intern()函数对应用程序响应时间的影响可能超过-XX:+UseStringDeduplication。
6.intern()函数的性能影响是什么?
基于这篇文章,您可能已经理解了在字符串对象上调用intern()函数有可能从内存中消除重复的字符串,从而降低整体内存利用率。但是,它会对响应时间和CPU利用率造成影响。
实际使用,还需要根据实际情况考虑是否使用。