This question already has an answer here:
What is meant by String Pool? And what is the difference between the following declarations:
String s = "hello";
String s = new String("hello");
Is there any difference between the storing of these two strings by the JVM?
Its puzzling that no one directly answered the question but most answers have a lot of upvotes.
In a nutshell, the first creates an entry in the String Pool, which can be re-used (more efficient due to above links on immutability, basically, interning), and the second creates a new String object (more costly).
Both objects live in the Heap. The references to both will be in the thread's stack.
http://www.journaldev.com/797/what-is-java-string-pool gives a clear insight into how this is achieved
The string pool is the JVM's particular implementation of the concept of string interning:
Basically, a string intern pool allows a runtime to save memory by preserving immutable strings in a pool so that areas of the application can reuse instances of common strings instead of creating multiple instances of it.
As an interesting side note, string interning is an example of the flyweight design pattern:
JLS
As mentioned by Andrew, the concept is called "interning" by the JLS.
Relevant passage from JLS 7 3.10.5:
JVMS
JVMS 7 5.1 says:
Bytecode
It is also instructive to look at the bytecode implementation on OpenJDK 7.
If we decompile:
we have on the constant pool:
and
main
:Note how:
0
and3
: the sameldc #2
constant is loaded (the literals)12
: a new string instance is created (with#2
as argument)35
:a
andc
are compared as regular objects withif_acmpne
The representation of constant strings is quite magic on the bytecode:
new String
)and the JVMS quote above seems to say that whenever the Utf8 pointed to is the same, then identical instances are loaded by
ldc
.I have done similar tests for fields, and:
static final String s = "abc"
points to the constant table through the ConstantValue Attributeldc
Conclusion: there is direct bytecode support for the string pool, and the memory representation is efficient.
Bonus: compare that to the Integer pool, which does not have direct bytecode support (i.e. no
CONSTANT_String_info
analogue).The
JVM
performs some trickery while instantiating string literals to increase performance and decrease memory overhead. To cut down the number of String objects created in the JVM, the String class keeps a pool of strings. Each time your code create a string literal, the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool.Output : true
Unfortunately, when you use
String object is created out of the String literal pool, even if an equal string already exists in the pool.
Output : false
The string pool allows string constants to be reused, which is possible because strings in Java are immutable. If you repeat the same string constant all over the place in your Java code, you can actually have only one copy of that string in your system, which is one of the advantages of this mechanism.
When you use
String s = "string constant";
you get the copy that is in the string pool. However, when you doString s = new String("string constant");
you force a copy to be allocated.String objects are basically wrappers around string literals. Unique string objects are pooled to prevent unnecessary object creation, and the JVM may decide to pool string literals internally. There is also direct bytecode support for String constants which are referenced multiple times, providing the compiler supports this.
When you use a literal, say
String str = "abc";
, the object in the pool is used. If you useString str = new String("abc");
, a new object is created, but the existing string literal may be reused on either the JVM level or bytecode level (at compile time).You can check this for yourself by creating lots of strings in a for loop and using the
==
operator to check for object equality. In the following example,string.value
is private toString
, and holds the string literal used. Because it is private, it has to be accessed via reflection.Output: