3

I understanding the internal working of intern() in java. It will start referring to the string pool area object. But when we use inter() along with new, does it still create an object in heap and the reference is now pointing to pool object? Or is it that it wouldn't create any heap object at all?

String s1 = new String("hello").intern();

For example in the above line, when intern is used, is it creating only one object in the string pool and referring it? Or is it creating one object in heap and one object in pool and it starts referring to pool object, thereby leaving the object at heap for garbage collection?

Deca
  • 1,155
  • 1
  • 10
  • 19

2 Answers2

0

In the Oracle/OpenJDK it doesn't create any objects, however, this is implementation dependent.

The method intern() either returns the existing object, in this case, the original "Hi" or the String used to call intern

But when we use inter() along with new, does it still create an object in heap and the reference is now pointing to pool object?

String literals are still in the heap. Nothing is moved to add it to this pool

For example in the above line, when intern is used, is it creating only one object in the string pool and referring it?

This is only creating one object, wrapping the char[] or byte[] of the original String literal. The intern will return the original string literal.

Or is it creating one object in heap and one object in pool and it starts referring to pool object, thereby leaving the object at heap for garbage collection?

The string literal pool is implemented in native memory and is not made up of objects.

For comparison, this call to intern() adds the new string to the literal pool as concat is computed at runtime.

String hi = "h".concat("i").intern();

This does nothing as the + is computed at compile time.

String hi = ("h" + "i").intern();
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • True. String literals are still in the heap. So you mean to say it leaves one object for garbage collection? – Deca Aug 07 '18 at 15:04
  • @Deca correct, the `new String` can be GC-ed. – Peter Lawrey Aug 07 '18 at 15:05
  • This was gray area for me. I was wondering why would java do that. I mean it knows that once it starts using the pool reference in the first statement itself, it knows that the object will never ever be used in the future. Why can't it be like don't create the object in itself. Anyways it is going to behave like literals from the very first occurance – Deca Aug 07 '18 at 15:17
  • @Deca actually it can eliminate object creation with Escape Analysis in most cases. In this case, the JVM need to understand what the intern() does i.e. when will it actually use the object passed in. This optimisation is probably not in the JVM, so the object will get created anyway. – Peter Lawrey Aug 07 '18 at 15:54
0

If you look at the documentation this quote here explains exactly what happens.

https://docs.oracle.com/javase/9/docs/api/java/lang/String.html#intern--

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.

So with your question:

For example in the above line, when intern is used, is it creating only one object in the string pool and referring it? Or is it creating one object in heap and one object in pool and it starts referring to pool object, thereby leaving the object at heap for garbage collection?

bold faced is what is happening.

Here you can see in this demonstration that your code returns the interned object.

https://ideone.com/dKFkEl

    String s1 = new String("hello").intern();
    String s2 = new String("hello");
    String s3 = "hello";
    System.out.println("s1 == s2 = "+(s1 == s2));// false
    System.out.println("s1 == s3 = "+(s1 == s3));// true
    System.out.println("s2 == s3 = "+(s2 == s3));// false
Tschallacka
  • 27,901
  • 14
  • 88
  • 133
  • Is it not like, "In Java with new, an object will always be created in heap". – Deca Aug 07 '18 at 15:06
  • @Deca The `new String("hello")` does create it in heap. But since you daisychain the intern() call, the heap object is iterated against pool to find a match and that is then returned to be assigned to the variable. Your heap object is then cleaned in the next iteration of the garbage collector because there are no references to it. – Tschallacka Aug 07 '18 at 15:08
  • yup. Thank you. Looks like that to me too. – Deca Aug 07 '18 at 15:21
  • @Deca depending how optimized your program becomes during running or if you hard code it like that that it might end up with a simple direct pool assignment. Java is pretty good in recognizing those patterns and then just skipping to the essential step. a hardcoded `String s1 = new ("Hello").intern()` as a `String s1 = StringPool.static_reference` for efficiency sake. – Tschallacka Aug 07 '18 at 15:24