If jvm
creates string pool
for memory optimization, then why it creates new Object each time we create string using new
keyword even though it exists in string pool
?

- 573
- 6
- 22
-
7because that's what `new` means... – njzk2 Sep 23 '15 at 18:45
-
2"Why does the computer does what I tell it to do?" – o.O – The Paramagnetic Croissant Sep 23 '15 at 20:50
-
Closely related to the question [What is the difference between “text” and new String(“text”)?](http://stackoverflow.com/questions/3052442/what-is-the-difference-between-text-and-new-stringtext). – Raedwald Sep 29 '15 at 11:43
7 Answers
... why does Java create new Object each time we create a string using the
new
keyword even though it exists in string pool?
Because you explicitly told it to! The new
operator always creates a new object. JLS 15.9.4 says:
"The value of a class instance creation expression is a reference to the newly created object of the specified class. Every time the expression is evaluated, a fresh object is created."
For the record, it is nearly always a mistake to call new String(String)
... but in obscure cases it might be useful. It is conceivable that you might want a string for which equals
returns true
and ==
gives false
. Calling new String(String)
will give you that.
For older versions of Java, the substring
, trim
and possibly other String
methods would give you a string that shared backing storage with the original. Under certain circumstances, this could result in a memory leak. Calling new String(str.trim())
for example would prevent that memory leak, at the cost of creating a fresh copy of the trimmed string. The String(String)
constructor guarantees to allocate a fresh backing array as well as giving you a new String
object.
This behavior of substring
and trim
changed in Java 7.

- 698,415
- 94
- 811
- 1,216
-
6Useful for testing too - forces out those pesky comparing `String` with `==` bugs... – Boris the Spider Sep 23 '15 at 13:15
-
I wonder what the performance implications would have been of either having operations like `subString` return strings with new backing stores in cases where they would use less than half the original, but borrow the original otherwise, or of having separate `subString` methods for cases where the copy was expected to outlive the original versus cases where it wasn't? – supercat Sep 23 '15 at 16:48
-
@supercat: I think, there could be several options. E.g. you could have a cheap `substring` implementation sharing the array and a smart garbage collector knowing how to compact those strings if the original large string becomes unreachable. Today’s JVMs *have* a garbage collector that has special knowledge about strings and their character array as it will force sharing of arrays for equal strings. Nevertheless, having the cheap `substring` also implies that each `String` has to carry an extra `offset` and `length` field which have to be respected by every other string operation… – Holger Sep 23 '15 at 18:04
-
@Holger: How much cost do those fields impose in practice? Personally, if I'd been designing Java, I probably would have made `string` behave as distinct type in the language which would typically hold a reference, and allow coercion to `Object` or `StringObject`, but would implement `==` as value equality, and would offer no guarantee as to when `(StringObject)string1 == (StringObject)string1` would yield true or false [a situation similar to e.g. `(Short)x == (Short)x`]. That would have allowed an implementation to efficiently use different kinds of objects for different... – supercat Sep 23 '15 at 18:20
-
...kinds of strings (e.g. `char[]`, `byte[]`, or various kinds of heap objects) and make substitutions as convenient. For example, a `ConcatenatedString` could contain a `String[]` whose first element if non-null would represent its content, and whose remaining elements if non-null would identify constituents. Using a `ConcatenatedString` for any purpose requiring a linear string would cause the system to physically concatenate its pieces and store a reference to the linear string (in case it's needed again) but concatenating a string and then concatenating it to something else... – supercat Sep 23 '15 at 18:27
-
...would not require regeneration of the whole linear string. In cases where the last segment of one string and the first segment of another total less than 256 characters or so, it would probably be better to generate a new `char[]` or `byte[]` to combine them than to store them separately, but there's no reason to regenerate massive linear strings all the time. – supercat Sep 23 '15 at 18:28
To give primitive style of declaration and for performance designers introduced String literals.
But when you use new
keyword, then you are explicitly creating objects on heap not in constant pool.
When the objects created on heap, there is no way to share that memory with each other and they become completely strangers unlike in constant pool.
To break this barrier between heap and constant pool String interning
will help you out.
string interning is a method of storing only one copy of each distinct string value, which must be immutable
Remember that constant pool also a small part of heap with some additional benefits where sharing of memory is available.

- 120,458
- 37
- 198
- 307
When you write
String str = new String("mystring");
then it creates a string object in heap just like other object which you create. The string literal "mystring" is stored in the string constant pool.
From the Javadocs:
A pool of strings, initially empty, is maintained privately by the class String.
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.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.

- 168,305
- 31
- 280
- 331
To take advantage of string pooling you need to use String#intern
instead of new.

- 3,242
- 1
- 18
- 28
-
1Might be worth saying that this still requires the creation of the new String object first, but the newly-created object can be cleaned up quickly if the same string exists in the constant pool. – Andy Turner Sep 23 '15 at 07:14
-
@AndyTurner - *but the newly-created object can be cleaned up quickly if the same string exists in the constant pool.* why / how? – TheLostMind Sep 23 '15 at 07:18
-
Well, because if you say `String foo = "foo"; String bar = new String("foo").intern();`, `bar == foo`, so the instance created by `new String("foo")` is no longer referenced. – Andy Turner Sep 23 '15 at 07:20
-
@AndyTurner - Even if it doesn't exist, the instance created by `new String("foo") ` will have no reference to it and will be eligible for GC – TheLostMind Sep 23 '15 at 08:33
Following object will be stored in String pool :
String s = "hello";
And following object will be stored in Heap (not in string pool):
String s = new String ("hello")

- 3,755
- 3
- 26
- 43
-
1Not really... You are using literal that you pass to constructor and that literal is stored on constant pool – Gaskoin Sep 23 '15 at 08:00
-
@Gaskoin - If you create a string object with new operator it will always create a new object and it will be stored in heap. Please provide a reference based on which you have given that statement. Ref : http://java67.blogspot.in/2014/08/difference-between-string-literal-and-new-String-object-Java.html – Rahman Sep 23 '15 at 09:54
-
1"Literal strings within the same class (§8) in the same package (§7) represent references to the same String object". There is a constant String object created when you compile source code with a string literal. The variable `s` on the first line points to this. On line two, a new String object is constructed, with the constant String object passed as a parameter. https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5 – Joe Sep 23 '15 at 15:55
-
1@Joe: you shouldn’t have stopped at the first bullet of that list. Look at, e.g. “*Literal strings within different classes in different packages likewise represent references to the same String object.*”. In other words, *all* equal literals yield to the same object, regardless of their package or class. – Holger Sep 23 '15 at 18:33
To enforce garbage collection!. If you need some String just one time, then there is no point in keeping it in memory (for almost forever. Which is the case with Strings in constant pool). Strings which are not in the constants pool can be GCed like any other object. So, you should only keep frequently used Strings in the constants pool (by using literals or interning them).

- 35,966
- 12
- 68
- 104
-
1@Gaskoin - The *constant pool* you are looking at is the **class constant pool** and NOT the *JVM String constants pool*. There is a BIG difference between the two. – TheLostMind Sep 23 '15 at 08:30
-
`String`s from the runtime pool can (and will) get garbage collected just like any other unused string. Only if they happen to match an existing constant from a class file, that constant won’t get collected, which is no issue as it exists anyway. The main reason not to use `intern()` on every string is that it is not cheap, as it will incorporate hashing and, even worse, the size of the table of interned strings is *fixed* which raises the likelihood of collisions (and before Java7u40, it’s size was ridiculous small). – Holger Sep 23 '15 at 18:26
-
@Holger - All string constants (that go into the String constants pool) will always be there in the class constants (byte-code). A non-interned string on the heap can get GCed like any other object. A String in the constants pool can get GCed if the class loader that loaded the class in which it is defined / being used gets GCed. – TheLostMind Sep 24 '15 at 05:17
-
Please, stop treating the byte code and calling `intern()` like being the same. Calling `intern()` does not suddenly modify the class’ byte code. `String`s which are interned but don’t match a literal, can get garbage collected without problems. And since the question was about strings created via `new`, we are *not* talking about literals. But *if* we consider that the string could match a literal, allowing garbage collection of the new string is a strange argument as that means solving a problem that doesn’t exist otherwise, i.e. when the existing string is returned and no new one created. – Holger Sep 24 '15 at 09:09
-
@Holger - *Please, stop treating the byte code and calling intern() like being the same*. I never said that they were the same :) – TheLostMind Sep 24 '15 at 09:10
-
Well, your answer contains a single reasoning which ends with “So, you should only keep frequently used Strings in the constants pool (**by using literals or interning them**).” which implies that the entire reasoning applies to both, using literals or interning. But the question is not about literals, hence, is about adding non-literals to the pool like `intern()` does. – Holger Sep 24 '15 at 09:17
Strings created in the form of String literals (String s = "string";
) are stored in string pool, but Strings created by invoking String constructor using new (String s = new String("string");
, are not stored in string pool.

- 5,653
- 7
- 42
- 66
-
1Not really... You are using literal that you pass to constructor and that literal is stored on constant pool – Gaskoin Sep 23 '15 at 08:02