How Many String Objects Will Be Created

String s = new String(xyz). How many objects has been made after this line of code execute?

THERE ARE ERRORS BELOW DEPENDING ON THE JVM/JRE THAT YOU USE. IT IS BETTER TO NOT WORRY ABOUT THINGS LIKE THIS ANYWAYS. SEE COMMENTS SECTION FOR ANY CORRECTIONS/CONCERNS.

First, this question really asks about this addressed here:
Is String Literal Pool a collection of references to the String Object, Or a collection of Objects

So, that is a guide for everyone on this matter.

...

Given this line of code: String s = new String(“xyz”)

There are two ways of looking at this:

(1) What happens when the line of code executes -- the literal moment it runs in the program?

(2) What is the net effect of how many Objects are created by the statement?

Answer:

1) After this executes, one additional object is created.

a) The "xyz" String is created and interned when the JVM loads the class that this line of code is contained in.

  • If an "xyz" is already in the intern pool from some other code, then the literal might produce no new String object.

b) When new String s is created, the internal char[] is a copy of the interned"xyz" string.

c) That means, when the line executes, there is only one additional object created.

The fact is the "xyz" object will have been created as soon as the class loaded and before this code section was ever run.

...next scenario ...

2) There are three objects created by the code (including the interned "a")

String s1 = "a";
String s2 = "a";
String s3 = new String("a");

a) s1 and s2 are just referenced,not objects, and they point to the same String in memory.

b) The "a" is interned and is a compound object: one char[] object and the String object itself. It consisting of two objects in memory.

c) s3, new String("a") produces one more object. The new String("a") does not copy the char[] of "a", it only references it internally. Here is the method signature:

public String2(String original) {
this.value = original.value;
this.hash = original.hash;
}

One interned String ("a") equals 2 Objects. And one new String("a") equals one more object. Net effect from code is three objects.

How many objects will be created in string pool?

  1. String s = "abc"; → one object, that goes into the string pool, as the literal "abc" is used;
  2. s = ""; → one empty string ("") object, and again - allocated in the string pool;
  3. String s2 = new String("mno"); → another object created with an explicit new keyword, and note, that it actually involves yet another literal object (again - created in the string pool) - "mno"; overall, two objects here;
  4. s2 = "pqr"; → yet another object, being stored into the string pool.

So, there are 5 objects in total; 4 in the string pool (a.k.a. "intern pool"), and one in the ordinary heap.

Remember, that anytime you use "string literal", JVM first checks whether the same string object (according to String::equals..()) exists in the string pool, and it then does one of the following:

  1. If corresponding string does not exist, JVM creates a string object and puts it in the string pool. That string object is a candidate to be reused, by JVM, anytime equal to it (again, according to String::equals(..)) string literal is referenced (without explicit new);
  2. If corresponding string exists, its reference is just being returned, without creating anything new.

How many String objects would be created when concatenating multiple Strings?

Any answer to your question will depend on the JVM implementation and the Java version currently being used. I think it's an unreasonable question to ask in an interview.

Java 8

On my machine, with Java 1.8.0_201, your snippet results in this bytecode

L0
LINENUMBER 13 L0
LDC "First"
ASTORE 1
L1
LINENUMBER 14 L1
LDC "Second"
ASTORE 2
L2
LINENUMBER 15 L2
LDC "Third"
ASTORE 3
L3
LINENUMBER 16 L3
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 3
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 4

which proves that 5 objects are being created (3 String literals*, 1 StringBuilder, 1 dynamically produced String instance by StringBuilder#toString).

Java 12

On my machine, with Java 12.0.2, the bytecode is

// identical to the bytecode above
L3
LINENUMBER 16 L3
ALOAD 1
ALOAD 2
ALOAD 3
INVOKEDYNAMIC makeConcatWithConstants(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; [
// handle kind 0x6 : INVOKESTATIC
java/lang/invoke/StringConcatFactory.makeConcatWithConstants(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
// arguments:
"\u0001\u0001\u0001"
]
ASTORE 4

which magically changes "the correct answer" to 4 objects since there is no intermediate StringBuilder involved.


*Let's dig a bit deeper.

12.5. Creation of New Class Instances


A new class instance may be implicitly created in the following situations:

  • Loading of a class or interface that contains a string literal (§3.10.5) may create a new String object to represent the literal. (This will not occur if a string denoting the same sequence of Unicode code points has previously been interned.)

In other words, when you start an application, there are already objects in the String pool. You barely know what they are and where they come from (unless you scan all loaded classes for all literals they contain).

The java.lang.String class will be undoubtedly loaded as an essential JVM class, meaning all its literals will be created and placed into the pool.

Let's take a randomly selected snippet from the source code of String, pick a couple of literals from it, put a breakpoint at the very beginning of our programme, and examine if the pool contains these literals.

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc {
...
public String repeat(int count) {
// ...
if (Integer.MAX_VALUE / count < len) {
throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
" times will produce a String exceeding maximum size.");
}
}
...
}

They are there indeed.


As an interesting find, this IDEA's filtering has a side effect: the substrings I was looking for have been added to the pool as well. The pool size increased by one ("bytes String" was added) after I applied this.contains("bytes String").

Where does this leave us?

We have no idea whether "First" was created and interned before we call String str1 = "First";, so we can't state firmly that the line creates a new instance.

JAVA string number of objects

Although String is a class written in Java it is a kind of special class that has some special relationships with JVM. One of them is string literal (sequence of characters wrapped by quotes). When JVM sees "abc" it does something like the following:

String obj = stringLiteralsCache.get("abc");
if (obj == null) {
obj = new String("abc");
stringLiteralsCache.put("abc", obj);
}

So, in your first example the first line causes creation of the new instance but next 2 lines just get the already created instance from cache.

However cache works on literals only. It cannot prevent creation of new instance when you explicitly invoke constructor. So, new String("Welcome") creates 2 objects: one from literal Welcome because it is not in cache yet, second from explicit invocation of String constructor.

How many String objects are created on the Heap

The answer is 1. "A" is added to the heap before any of the 3 lines run via the String Pool, which exists in the heap. The first two lines reference those existing values from the string pool. The third line forces the creation of a new object on the heap.

Here's a great write-up:
http://www.journaldev.com/797/what-is-java-string-pool

Note: I stand corrected on the comment below. The "A" already exists in the thread pool before line 1 ever runs, so nothing is actually added in line 1. Therefore, the net change to the heap is 1 as you said in the interview since only line 3 actually affects the heap.

How many String objects will be created

"Fred" and "47" will come from the string literal pool. As such they won't be created when the method is invoked. Instead they will be put there when the class is loaded (or earlier, if other classes use constants with the same value).

"Fred47", "ed4" and "ED4" are the 3 String objects that will be created on each method invocation.



Related Topics



Leave a reply



Submit