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
?
... 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.
String
with ==
bugs... –
Tunnel 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? –
Epoch 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… –
Behnken 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... –
Epoch 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... –
Epoch char[]
or byte[]
to combine them than to store them separately, but there's no reason to regenerate massive linear strings all the time. –
Epoch 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.
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.
To take advantage of string pooling you need to use String#intern
instead of new.
String foo = "foo"; String bar = new String("foo").intern();
, bar == foo
, so the instance created by new String("foo")
is no longer referenced. –
Alexina new String("foo")
will have no reference to it and will be eligible for GC –
Weide 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")
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. docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5 –
Rountree 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).
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). –
Behnken 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. –
Behnken intern()
does. –
Behnken 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.
© 2022 - 2024 — McMap. All rights reserved.
new
means... – Lareine