Java - Unpooled String - java

Is there a legal way to force JVM not to store particular String instance in a long-lived string pool?
Does new String() provide this feature and I can be 100% sure that value created this way will be put into the heap and not into the pool unless I call intern()?

Is there a legal way to force JVM not to store particular String instance in a long-lived string pool?
Other than not initializing it with a string literal, I'm afraid there isn't.
Does new String() provide this feature and I can be 100% sure that value created this way will be put into the heap and not into the pool unless I call intern()?
Yes (keep in mind that if you write String str1 = new String("Hello");, then the String instance referred to by str1 will not get internalized, while the String instance created for the literal string "Hello" will).
Also note that where exactly the pool gets stored in the heap depends on the version of the JVM as explained here

Related

Java String Pool with String constructor and the intern function

I learned about the Java String Pool recently, and there's a few things that I don't quiet understand.
When using the assignment operator, a new String will be created in the String Pool if it doesn't exist there already.
String a = "foo"; // Creates a new string in the String Pool
String b = "foo"; // Refers to the already existing string in the String Pool
When using the String constructor, I understand that regardless of the String Pool's state, a new string will be created in the heap, outside of the String Pool.
String c = new String("foo"); // Creates a new string in the heap
I read somewhere that even when using the constructor, the String Pool is being used. It will insert the string into the String Pool and into the heap.
String d = new String("bar"); // Creates a new string in the String Pool and in the heap
I didn't find any further information about this, but I would like to know if that's true.
If that is indeed true, then - why? Why does java create this duplicate string? It seems completely redundant to me since the strings in java are immutable.
Another thing that I would like to know is how the .intern() function of the String class works: Does it just return a pointer to the string in the String Pool?
And finally, in the following code:
String s = new String("Hello");
s = s.intern();
Will the garbage collector delete the string that is outside the String Pool from the heap?
You wrote
String c = new String("foo"); // Creates a new string in the heap
I read somewhere that even when using the constructor, the String Pool is being used. It
will insert the string into the String Pool and into the heap.
That’s somewhat correct, but you have to read the code correctly. Your code contains two String instances. First, you have the string literal "foo" that evaluates to a String instance, the one that will be inserted into the pool. Then, you are creating a new String instance explicitly, using new String(…) calling the String(String) constructor. Since the explicitly created object can’t have the same identity as an object that existed prior to its creation, two String instances must exist.
Why does java create this duplicate string? It seems completely redundant to me since the strings in java are immutable.
Well it does so, because you told it so. In theory, this construction could get optimized, skipping the intermediate step that you can’t perceive anyway. But the first assumption for a program’s behavior should be that it does precisely what you have written.
You could ask why there’s a constructor that allows such a pointless operation. In fact, this has been asked before and this answer addresses this. In short, it’s mostly a historical design mistake, but this constructor has been used in practice for other technical reasons; some do not apply anymore. Still, it can’t be removed without breaking compatibility.
String s = new String("Hello");
s = s.intern();
Will the garbage collector delete the string that is outside the String Pool from the heap?
Since the intern() call will evaluate to the instance that had been created for "Hello" and is distinct from the instance created via new String(…), the latter will definitely be unreachable after the second assignment to s. Of course, this doesn’t say whether the garbage collector will reclaim the string’s memory only that it is allowed to do so. But keep in mind that the majority of the heap occupation will be the array that holds the character data, which will be shared between the two string instances (unless you use a very outdated JVM). This array will still be in use as long as either of the two strings is in use. Recent JVMs even have the String Deduplication feature that may cause other strings of the same contents in the JVM use this array (to allow collection of their formerly used array). So the lifetime of the array is entirely unpredictable.
Q: I read somewhere that even when using the constructor, the String Pool is being used. It will insert the string into the String Pool and into the heap. [] I didn't find any further information about this, but I would like to know if that's true.
It is NOT true. A string created with new is not placed in the string pool ... unless something explicitly calls intern() on it.
Q: Why does java create this duplicate string?
Because the JLS specifies that every new generates a new object. It would be counter-intuitive if it didn't (IMO).
The fact that it is nearly always a bad idea to use new String(String) is not a good reason to make new behave differently in this case. The real answer is that programmers should learn not to write that ... except in the extremely rare cases that that it is necessary to do that.
Q: Another thing that I would like to know is how the intern() function of the String class works: Does it just return a pointer to the string in the String Pool?
The intern method always returns a pointer to a string in the string pool. That string may or may not be the string you called intern() or.
There have been different ways that the string pool was implemented.
In the original scheme, interned strings were held in a special heap call the PermGen heap. In that scheme, if the string you were interning was not already in the pool, then a new string would be allocated in PermGen space, and the intern method would return that.
In the current scheme, interned strings are held in the normal heap, and the string pool is just a (private) data structure. When the string being interned a not in the pool, it is simply linked into the data structure. A new string does not need to be allocated.
Q: Will the garbage collector delete the string that is outside the String Pool from the heap?
The rule is the same for all Java objects, no matter how they were created, and irrespective of where (in which "space" or "heap" in the JVM) they reside.
If an object is not reachable from the running application, then it is eligible for deletion by the garbage collector.
That doesn't mean that an unreachable object will be be garbage collected in any particular run of the GC. (Or indeed ever ... in some circumstances.)
The above rule equally applies to the String objects that correspond to string literals. If it ever becomes possible that a literal can never be used again, then it may be garbage collected.
That doesn't normally happen. The JVM keeps a hidden references to each string literal object in a private data structure associated with the class that defined it. Since classes normally exists for the lifetime of the JVM, their string literal objects remain reachable. (Which makes sense ... since the application may need to use them.)
However, if a class is loaded using a dynamically created classloader, and that classloader becomes unreachable, then so will all of its classes. So it is actually possible for a string literal object to become unreachable. If it does, it may be garbage collected.

Java: How exactly String intern() and StringPool works?

According to Javadoc about String.intern():
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.
I have few questions about the same.
When a new String object (not using a string literal but using new() operator) is created like:
String str = new String("Test");
Question: I am aware that a new object will be created in heap. But will it also put String Test into the stringpool during object creation? If yes, then why the reference is not returned directly for the stringpool. If no, why not directly put the string in the pool as now the StringPool has been moved out of the PermGen and is in regular heap space (i.e. there is no space constraint apart from the heap space limit). There are some posts which state that the String is inserted in pool as soon as object is created whereas there are posts which contradicts this too.
Once we call String.intern() on a String object (as literals are already interned) what happens to the space allocated to the object? Is it reclaimed at the same moment or it waits for the next GC cycle?
Accepted answer to another question on SO, states that String intern should be used when you need speed since you can compare strings by reference (== is faster than equals).
Question: I am aware that when using String.intern() it returns reference to the string already present in the StringPool. But this requires a full scan lookup on the StringPool which can be an expensive operation in itself. So is this speed achieved during string comparison justifiable? If so, why?
I have looked at below sources:
JavaDoc
SO Question ques1, ques2, ques3
http://java-performance.info/string-intern-in-java-6-7-8/
And other misc sources from SO and outside world
All string literals are interned on compilation time. Using a string literal with the single argument constructor taking a string is a bit of an abuse of that constructor, hence you are likely to get two of them (but maybe there is a special compiler case for this, I can't say for sure). As of java 8 the implementation of the constructor (for openjdk) is this:
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
So no special treatment on this side. If you know the literal don't use this constructor.
I don't think there is any special GC semantics for Strings. It will get collected once it's unreachable and deemed collection worthy by the GC as any other object.
Don't ever use == for comparing strings, the first step in the default equals method for Strings is doing just that. If this is your dominant case (you know you are working with interned strings most of the time) you are only paying the overhead of a method call which is tiny, the potential for future bugs you add by doing something like that is just too big of a risk for a gain that is minuscule.

Does String have any internal mechanism to check existence of object in String constant pool?

I know that When i do below:
String s = "abc";
JVM checks for the "abc" object on string constant pool and if not present, it will create the object and its reference will be returned to s variable.
But here i want to get clear one thing that Do String have any internal mechanism to check existence of such object.
JVM checks for the "abc" object on string constant pool and if not present, it will create the object and its reference will be returned to s variable.
Wrong. Any string literal is in the constant pool, placed there by the compiler and classloader.
But here i want to get clear one thing that Do String have any internal mechanism to check existence of such object.
It has an external mechanism: String.intern(). But that has nothing to do with the code you posted.
You can use String.intern() which the Javadoc says (in part) returns a canonical representation for the string object.
String s = new String("abc").intern();
Or,
String s = "abc".intern();
Do String have any internal mechanism to check existence of such object.
Internally ... obviously yes, because otherwise intern() would not work.
But this functionality is within the JVM native implementation of intern etcetera, and is not exposed in any public java APIs.
I would argue that String.intern() is not a valid test. Sure, if you call intern on a string and that string object is already in the pool, then you will get the same string object back. But that doesn't give you an answer in the case where your string object isn't in the pool. In that case, you can't tell whether the result string was in the pool before your call ... or not. In the latter case, you have added a string to the pool as a side-effect of the intern() call.
Simple test to test the above feature
String one="abc";
String two="abc";
System.out.println(one==two);
Output is
true
Which implies both variables one and two are referencing the same object address.

Self referencing of String constant pool

I read that string constant pool is self referenced Also in this link it is written as the creation of String literal :
String s= "new";
will create a new String "new" in the heap if there is not one.
So does it mean that object is always created in the heap regardless its literal or new object using new keyword?
What i understood of intern is -- it checks if there is a object in the heap with same name then it is referenced else new object is created in the heap.
Please correct if i am wrong here.
Another doubt i have is - does the constant pool contains the objects or just the refernces to the objects in the heap.
does it mean that object is always created in the heap regardless its literal or new object using new keyword?
Yes, in Java all Object-derived objects, including Strings, are created in the heap. The only difference is that identical String objects from the constant pool get reused with the help of the compiler, while String objects created with operator new require explicit code from the programmer in order to get reused.
Yes it is on heap.
and with respect to intern() Yesyou are right.

String POOL in java

Java has string pool, due to which objects of string class are immutable.
But my question stands -
What was the need to make String POOL?
Why string class was not kept like other class to hold its own values?
Is internally JVM need some strings or is this a performance benefit. If yes how?
A pool is possible because the strings are immutable. But the immutability of the String hasn't been decided only because of this pool. Immutability has numerous other benefits. BTW, a Double is also immutable, and there is no pool of Doubles.
The need for the String pool is to reduce the memory needed to hold all the String literals (and the interned Strings) a program uses, since these literals have a good chance of being used many times, in many places of the program. Instead of having thousands of copies of the same String literal, you just have thousand references to the same String, which reduces the memory usage.
Note that the String class is not different from other classes: it holds its own char array. It may also share it with other String instances, though, when substring is called.
When we compiler see's that a new String literal has to be created,it first check's the pool for an identical string,if found no new String literal is created,the existing String is referred.
the benifit of making string as immutable was for the security feature. Read below
Why String has been made immutable in Java?
Though, performance is also a reason (assuming you are already aware of the internal String pool maintained for making sure that the same String object is used more than once without having to create/re-claim it those many times), but the main reason why String has been made immutable in Java is 'Security'. Surprised? Let's understand why.
Suppose you need to open a secure file which requires the users to authenticate themselves. Let's say there are two users named 'user1' and 'user2' and they have their own password files 'password1' and 'password2', respectively. Obviously 'user2' should not have access to 'password1' file.
As we know the filenames in Java are specified by using Strings. Even if you create a 'File' object, you pass the name of the file as a String only and that String is maintained inside the File object as one of its members.
Had String been mutable, 'user1' could have logged into using his credentials and then somehow could have managed to change the name of his password filename (a String object) from 'password1' to 'password2' before JVM actually places the native OS system call to open the file. This would have allowed 'user1' to open user2's password file. Understandably it would have resulted into a big security flaw in Java. I understand there are so many 'could have's here, but you would certainly agree that it would have opened a door to allow developers messing up the security of many resources either intentionally or un-intentionally.
With Strings being immutable, JVM can be sure that the filename instance member of the corresponding File object would keep pointing to same unchanged "filename" String object. The 'filename' instance member being a 'final' in the File class can anyway not be modified to point to any other String object specifying any other file than the intended one (i.e., the one which was used to create the File object).
What was the need to make String POOL?
When created, a String object is stored in heap, and the String literal, that is sent in the constructor, is stored in SP. Thats why using String objects is not a good practice. Becused it creates two objects.
String str = new String("stackoverflow");
Above str is saved in heap with the reference str, and String literal from the constructor -"stackoverflow" - is stored in String Pool. And that is bad for performance. Two objects are created.
The flow: Creating a String literal -> JVM looks for the value in the String Pool as to find whether same value exists or not (no object to be returned) -> The value is not find -> The String literal is created as a new object (internally with the new keyword) -> But now is not sent to the heap , it is send instead in String Pool.
The difference consist where the object is created using new keyword. If it is created by the programmer, it send the object in the heap, directly, without delay. If it is created internally it is sent to String Poll. This is done by the method intern(). intern() is invoke internally when declaring a String literal. And this method is searching SP for identical value as to return the reference of an existing String object or/and to send the object to the SP.
When creating a String obj with new, intern() is not invoked and the object is stored in heap. But you can call intern() on String obj's: String str = new String().intern(); now the str object will be stored in SP.
ex:
String s1 = new String("hello").intern();
String s2 = "hello";
System.out.println(s1 == s2); // true , because now s1 is in SP

Categories