Why jvm create new string Object each time we create string using new keyword
Asked Answered
S

7

11

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?

Snip answered 23/9, 2015 at 7:11 Comment(3)
because that's what new means...Lareine
"Why does the computer does what I tell it to do?" – o.OStaphylococcus
Closely related to the question What is the difference between “text” and new String(“text”)?.Aileneaileron
S
30

... 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.

Smarten answered 23/9, 2015 at 7:28 Comment(6)
Useful for testing too - forces out those pesky comparing String with == bugs...Tunnel
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?Epoch
@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…Behnken
@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...Epoch
...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...Epoch
...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.Epoch
I
5

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.

Investigation answered 23/9, 2015 at 7:13 Comment(0)
R
3

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.

Rumble answered 23/9, 2015 at 7:16 Comment(0)
D
1

To take advantage of string pooling you need to use String#intern instead of new.

Diggings answered 23/9, 2015 at 7:12 Comment(4)
Might 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.Alexina
@AndyTurner - but the newly-created object can be cleaned up quickly if the same string exists in the constant pool. why / how?Weide
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.Alexina
@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 GCWeide
T
0

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")
Tedie answered 23/9, 2015 at 7:15 Comment(4)
Not really... You are using literal that you pass to constructor and that literal is stored on constant poolAlmondeyed
@Almondeyed - 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 : java67.blogspot.in/2014/08/…Tedie
"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. docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5Rountree
@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.Behnken
W
0

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).

Weide answered 23/9, 2015 at 7:16 Comment(6)
@Almondeyed - 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.Weide
Strings 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
@Behnken - 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.Weide
Please, stop treating the byte code and calling intern() like being the same. Calling intern() does not suddenly modify the class’ byte code. Strings 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
@Behnken - Please, stop treating the byte code and calling intern() like being the same. I never said that they were the same :)Weide
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.Behnken
S
0

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.

Sofa answered 23/9, 2015 at 7:26 Comment(1)
Not really... You are using literal that you pass to constructor and that literal is stored on constant poolAlmondeyed

© 2022 - 2024 — McMap. All rights reserved.