Sign up ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free.

If the JVM has a string pool for memory optimization, then why does it create a new object each time we create a string using the new keyword even though it exists in the string pool?

share|improve this question
5  
because that's what new means... –  njzk2 8 hours ago
1  
"Why does the computer does what I tell it to do?" – o.O –  The Paramagnetic Croissant 6 hours ago

7 Answers 7

up vote 28 down vote accepted

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

share|improve this answer
5  
Useful for testing too - forces out those pesky comparing String with == bugs... –  Boris the Spider 14 hours ago
    
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 10 hours ago
    
@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 9 hours ago
    
@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 9 hours ago
    
...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 9 hours ago

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.

share|improve this answer

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

share|improve this answer
1  
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. –  Andy Turner 20 hours ago
    
@AndyTurner - but the newly-created object can be cleaned up quickly if the same string exists in the constant pool. why / how? –  TheLostMind 20 hours ago
    
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 20 hours ago
    
@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 18 hours ago
1  
@TheLostMind that is exactly my point. –  Andy Turner 18 hours ago

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.

share|improve this answer

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")
share|improve this answer
1  
Not really... You are using literal that you pass to constructor and that literal is stored on constant pool –  Gaskoin 19 hours ago
    
@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 : java67.blogspot.in/2014/08/… –  Rehman 17 hours ago
    
"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.5 –  Joe 11 hours ago
    
@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 8 hours ago

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

share|improve this answer
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 18 hours ago
    
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). –  Holger 9 hours ago

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.

share|improve this answer
1  
Not really... You are using literal that you pass to constructor and that literal is stored on constant pool –  Gaskoin 19 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.