Try*_*ing 2 java string memory-management
情况1:
Run Code Online (Sandbox Code Playgroud)String str = "StackOverFlow"; String str1 = "StackOverFlow"; if(str==str1){ System.out.println("equal");//prints equal }案例2:
Run Code Online (Sandbox Code Playgroud)String str = "StackOverFlow"; String str1=str.intern(); if(str==str1){ System.out.println("equal");//prints equal }
跟进问题:
我想知道JVM是否在intern()内部调用第一种情况并将引用分配str给str1?
第一种情况下两个引用如何相等?
第一种情况是否意味着每当你声明一个字符串时String str = "StackOverFlow";它会像方法那样添加到字符串池中intern()?
请问这是使用字符串池String str = "StackOverFlow";和intern()堆之外分配?如果确实在哪里?
对于问题4,答案如下:
在Java 6及更早版本中,实习字符串也存储在永久代中.在Java 7中,实习字符串存储在主对象堆中.
这是文档说的:
在JDK 7中,实现的字符串不再分配在Java堆的永久生成中,而是分配在Java堆的主要部分(称为年轻和旧的代)中,以及应用程序创建的其他对象.此更改将导致更多数据驻留在主Java堆中,并且永久生成中的数据更少,因此可能需要调整堆大小.由于此更改,大多数应用程序只会看到堆使用中的相对较小的差异,但是加载许多类或大量使用该
String.intern()方法的较大应用程序将看到更显着的差异.
更多细节来自:
Java 6中的String.intern()
在那些美好的旧时代,所有实习字符串都存储在PermGen中 - 堆的固定大小部分主要用于存储加载的类和字符串池.除了显式内部字符串之外,PermGen字符串池还包含程序中较早使用的所有文字字符串(此处使用的重要字 - 如果从未加载/调用类或方法,则不会加载其中定义的任何常量).
Run Code Online (Sandbox Code Playgroud)The biggest issue with such string pool in Java 6 was its location – the PermGen. PermGen has a fixed size and can not be expanded at运行.您可以使用-XX:MaxPermSize = 96m选项进行设置.据我所知,默认的PermGen大小在32M到96M之间变化,具体取决于平台.您可以增加其大小,但其大小仍将固定.这种限制需要非常小心地使用String.intern - 你最好不要使用这种方法实现任何不受控制的用户输入.这就是为什么Java 6时的字符串池主要在手动管理的映射中实现的原因.
Java 7中的String.intern()
Oracle工程师对Java 7中的字符串池逻辑进行了非常重要的更改 - 字符串池已重新定位到堆中.这意味着您不再受限于单独的固定大小的内存区域.所有字符串现在都位于堆中,与大多数其他普通对象一样,它允许您在调整应用程序时仅管理堆大小.从技术上讲,仅此一点可能是重新考虑在Java 7程序中使用String.intern()的充分理由.但还有其他原因.
引用是相同的,因为它们都是字符串文字.
该intern()呼叫str没有必要的,因为它也是一个文字.在构造带有byte或char数组的String 时,你需要使用的一个例子intern()(顺便说一下,慢很多equals(),所以不要使用它).
例如:
final String str1 = "I am a literal";
final String str2 = new String(str1.toCharArray());
final boolean check1 = str1 == str2; // false
final boolean check2 = str1 == str2.intern(); // true
Run Code Online (Sandbox Code Playgroud)