3

I used to know that both of the following statements create the string a in the constant pool at runtime:

String s = "a"
String s = new String("a")

When testing these on the JVM, permgen size is the same for both cases.


The following code snippets, however, behave differently from this:

String s2 = null;
for (int i = 0; i < 100; i++)
{
    s2 = s2 + i;
}

Using .intern(), the permgen size increases in each iteration:

String s2 = null;
for (int i = 0; i < 100; i++)
{
    s2 = s2 + i;
    s2.intern();
}

Why is this behaviour observable? Does s2.intern() add entries to the pool? How is this different from these declarations?

String s = "a"
String s = new String("a")
Clashsoft
  • 11,553
  • 5
  • 40
  • 79
superman
  • 51
  • 6
  • `intern()` adds to the string literal pool as this is it's sole purpose as documented. I am not clear on what the confusion is. – Peter Lawrey Dec 23 '15 at 19:13
  • i use jvisualVM to check..Using .intern(), the permgen size increases in each iteration.the others were not ..why ??? – superman Dec 24 '15 at 01:43
  • Objects are placed on the heap by default, that is what it is for. It should be no surprise that Strings are objects and when they are allocated they are placed on the heap. However when you `intern()` a string you place it in the String literal pool which is in the perm gen. – Peter Lawrey Dec 24 '15 at 11:15
  • http://stackoverflow.com/questions/34462638/a-vs-new-string-b-in-constant-pool-jvm-jdk-6-eager-for-the-truth – superman Dec 25 '15 at 12:14
  • Not sure what you are trying to say with the link. BTW the perm gen is not got, it was replaced with a meta space which serves the same purpose. – Peter Lawrey Dec 26 '15 at 14:21

2 Answers2

4

Here a little explanation:

  • "a" create the String "a" in the intern pool if not already present
  • new String("a") because the parameter is "a", the string "a" is created in the intern pool (if not already present) and a copy of "a" is created out of intern pool
  • taken any string s s.intern() returns an intern copy of that string if present in the intern pool. If not add that string to the intern pool and returns the new copy.

A reference for intern() method:

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

Note: to create a String and don't add it to the intern pool you can use an array of chars as parameter of String constructor:

char[] helloArray = { 'h', 'e', 'l', 'l', 'o', '.' };
String helloString = new String(helloArray);

Here is the reference to the jls where it is explained that a string literal is present in the intern pool of strings:

A string literal is a reference to an instance of class String (§4.3.1, §4.3.3).

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.


Here a step by step explanation to the last comment:

// Creates the string "123", add it to the intern pool and assign "123" to s
String s = "123";  

// s.intern() returns the intern string of s. Because s is already the 
// string "123" present in the intern pool s and s.intern() are the same
System.out.println(s == s.intern());// true 

// "123" is already in intern pool. new String("123") create a new String
// that equals "123" but it is a different object
String s2 = new String("123"); 

// It prints false because s2 is equals to "123", but not the same object
// because a new String was created in the preciding row
System.out.println(s2 == s);// false

// It prints true because s2.intern() returns the string present in the
// intern pool that is equals to s2. That string exists and is "123"
System.out.println(s2.intern() == s);  // true

Additional note: For every string s that equals s2, s.intern() == s2.intern() also if s == s2 returns false.

// If s equals s2 but are not the same
if (s.equals(s2) && s != s2) {
    // THe intern string of s and s2 are always the same
    System.out.println(s.intern() == s2.intern()); // prints always true
}
Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
  • i use jvisualVM to check..Using .intern(), the permgen size increases in each iteration.the others were not ..why ??? – superman Dec 24 '15 at 01:44
  • Yes because you create the literal "a" – Davide Lorenzo MARINO Dec 24 '15 at 06:30
  • how can you prove that??? i thought new String("a") maybe not! if you can ,i 'll apprecia it – superman Dec 24 '15 at 10:50
  • I add a reference to the jls – Davide Lorenzo MARINO Dec 24 '15 at 10:57
  • JLS = Java Language Specification, it is the specification that explains what is java and how it works. It is necessary to build the java compiler for example. – Davide Lorenzo MARINO Dec 24 '15 at 11:25
  • http://docs.oracle.com/javase/specs/jls/se6/html/lexical.html#3.10.5 @Davide it's different in JDK6 – superman Dec 24 '15 at 11:39
  • It changes only the graphic aspect and reference numbers, not the concept. Here is the reference from Java 6: "Each string literal is a reference (§4.3) to an instance (§4.3.1, §12.5) of class String (§4.3.3). String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions (§15.28)-are "interned" so as to share unique instances, using the method String.intern. – Davide Lorenzo MARINO Dec 24 '15 at 11:46
  • i can't understand jls clearly!pelase help me ! why? false: public static void main(String[] args) throws InterruptedException { String s = "123"; System.out.println(s == s.intern());// true String s2 = new String("123"); System.out.println(s2 == s);// false } – superman Dec 24 '15 at 12:04
  • I add an explanation in the answer – Davide Lorenzo MARINO Dec 24 '15 at 12:08
  • but why this code is not Pergen OutMemory???? public static void main(String[] args) throws InterruptedException { List s = new ArrayList(); for (;;) { for (int i = 0; i < 1000000; i++) { s.add(new String("" + i)); } } } } – superman Dec 24 '15 at 13:55
  • please help !! i really want to figure it out........TKS again! @Davide Lorenzo MARINO – superman Dec 24 '15 at 15:46
  • http://stackoverflow.com/questions/34462638/a-vs-new-string-b-in-constant-pool-jvm-jdk-6-eager-for-the-truth – superman Dec 25 '15 at 12:14
0

Since interned Strings are interned JVM-wide, they must be interned statically, which would require the mechanism to use a class attribute for the caching, which would consume permgen memory.

Bohemian
  • 412,405
  • 93
  • 575
  • 722