This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Garbage collection behaviour for String.intern()
How does Java store Strings and how does substring work internally?
According to me the String reference when declared as null doesn't deletes the entry from String literal pool and i want to know how we can clear it .
String object="csk";// creates an Object in Java Heap and makes an entry String Literal Pool .
object=null// however make this reference to null object .
//but it doesn't deletes an entry from String literal .I doubt if it deletes an entry from Literal Pool
String literals (WeakHashMap) are also stored in heap memory called the "permgen" heap.
need to configure in JVM to find and collect dynamically loaded classes that are no longer needed, and this may cause String literals to be garbage collected.
and or when JVM performas the Full gc.
An excerpt from How does Java store Strings and how does substring work internally?:
Strings in the pool can be garbage collected (meaning that a string literal might be removed from the pool at some stage if it becomes full)
Related
I am aware that when we initialize a string literal to a variable this literal will be stored in the string pool by the JVM. Consider the piece of code below.
System.out.println("This is a string literal");
Does the string literal within the quotes also be stored in the string pool even if I don't initialize it to a variable?
I will preface this answer by saying that there is little practical use in gaining a deep understanding of the Java string pool. From a practical perspective, you just need to remember two things:
Don't use == to compare strings. Use equals, compareTo, or equivalent methods.
Don't use explicit String.intern calls in your code. If you want to avoid potential problems with duplicate strings, enable the string de-duplication feature that is available in modern Java GCs.
I am aware that when we initialize a string literal either using the 'new' keyword or not, this literal will be stored in the string pool by the JVM.
This is garbled.
Firstly, you don't "initialize" a string literal. You initialize a variable.
String hi = "hello"; // This initializes the variable `hi`.
Secondly you typically don't / shouldn't use a string literal with new.
String hi = new String("hello"); // This is bad. You should write this as above.
The normal use-case for creating a string using new is something like this:
String hi = new String(arrayOfCharacters, offset, count);
In fact, creation and interning of the String object that corresponds to a string literal, happens either at the first time that the literal is used in an expression or at an earlier time. The precise details (i.e. when it happens) are unspecified and (I understand) version dependent.
The first usage might be in a variable initialization, or it might be in something else; e.g. a method call.
So to your question:
Consider the piece of code below:
System.out.println("This is a string literal");
Does the string literal within the quotes also be stored in the string pool even if I do not initialize it?
Yes, it does. If that was the first time the literal was used, the code above may be the trigger for this to happen. But it could have happened previously; e.g. if the above code was run earlier.
As a followup, you asked:
Why does the String Pool collect string literals which are not stored in a variable and just displayed in the console?
Because the JLS 3.10.5 requires that the String objects which correspond to string literals are interned:
"Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern (§12.5)."
And you asked:
The Presence of the String Pool help optimize the program. By storing literals as such (which is actually not required because it is just to be displayed in the console), isn't it the case that it goes against its whole purpose (which is optimization)?
The original idea for interning and the string pool was to save memory. That made sense 25 years ago when the Java language was designed and originally specified. These days even a low-end Android phone has 1GB of RAM, and interning of string literals to save a few thousand bytes is kind of pointless. Except that the JLS says that this must happen.
But the answer is No, it doesn't go against the (original) purpose. This statement:
System.out.println("This is a string literal");
could be executed many times. You don't want / need to create a new String object for the literal each time that you execute it. The thing is that the JVM doesn't know what is going to happen.
Anyway, the interning must happen because that is what the spec says.
This question already has answers here:
Why is char[] preferred over String for passwords?
(17 answers)
Closed 4 years ago.
I have a problem with storing a plain password in memory as a String. According to the reference, since Strings are immutable there is a vulnerability of using String data type for sensitive data storing in memory.
https://www.geeksforgeeks.org/use-char-array-string-storing-passwords-java/
Why is char[] preferred over String for passwords?
Can I overcome this security issue by nullifying the string variable instead of using char array or String buffer/builder.
eg : String password="password";
password = null;
No. Nullifying a string would only delink the reference. But the value will still exist in string pool. Because to conserve memory, string values are retained in the string pool.
Any potential hacker, can retrieve the value by gaining access to the string pool.
Whereas, using char[], you can simply treat that object as any other object. And nullifying the char object will wipe off the data from heap at the time of garbage collection.
An even better option will be using a byte array.
Read more about String Constant pool.
If you want absolute security, no. Nulling out the String is not the right solution.
The reason for this is that nulling it out makes no guarantees about the String no longer being available. Although it may make it more likely to be garbage collected (and this is only a 'may'), there are no guarantees about when (or even if) it will be garbage collected.
You should use either a byte array, or a char array, and then null each of the elements in the array when you are done.
This question already has answers here:
String s = new String("xyz"). How many objects has been made after this line of code execute?
(21 answers)
What is the difference between "text" and new String("text")?
(13 answers)
Closed 5 years ago.
String str=new String ("xyz");
I read somewhere JVM create 2 object 1st in pool and 2nd in heap.
Is this true ? If true then why JVM create 2 object when one is already there can anyone explain?
Yes, you are right. It creates two objects. One in String Constant Pool and another object in Heap pointing to the String pool.
If we consider String str= "Hello" //String literal, it creates only one object by JVM in String Constant Pool.
As per your syntax(String str = new String("xyz") //String object) JVM creates 2 objects. One in string pool and another in heap).
For further reference, please check the following discussion:
String s = new String("xyz"). How many objects has been made after this line of code execute?
"xyz" is in the constant pool once the class has been loaded
str is put on the heap when that line actually runs
see
Where does Java's String constant pool live, the heap or the stack?
We know that a String will be stored in SCP (String Constant Pool) area:
1. in the same way String[] is also stored in SCP? i mean each array contains a String, so again this will be stored in SCP?
2. and what about ArrayList(String) ? i mean each arraylist contains a String, so again this will be stored in SCP?
In our project we are facing OutOfMemory. we are having more than 1000+ String[]. Each time values for String[] are different. So Huge no of objects are getting created in SCP (guessing) We want to change this to ArrayList(String) to reduce memory. If again ArrayList(String), each String gets stored in SCP area, then there is no use of changing from String[] to ArrayList(String)
Please explain in detail. Your response is valuable.
No. All Strings will not be stored in String Constant Pool. Only String literals and interned Strings will be stored there.
String s = "abc"; // stores "abc" in the SCP if it is not already present.
String s1= "abc";// stores "abc" in the SCP if it is not already present.
String s2="abc";// Doesn't store "abc" into the String pool as it is already present.
String s3=s1+s2; // "abcabc" goes on heap
String[] is just an array that holds references to String objects.
So, I think there is some other problem somewhere else.
Also, from Oracle doc :
In JDK 7, interned strings are no longer allocated in the permanent
generation of the Java heap, but are instead allocated in the main
part of the Java heap (known as the young and old generations), along
with the other objects created by the application. This change will
result in more data residing in the main Java heap, and less data in
the permanent generation, and thus may require heap sizes to be
adjusted. Most applications will see only relatively small differences
in heap usage due to this change, but larger applications that load
many classes or make heavy use of the String.intern() method will see
more significant differences.
Its the String literals that are stored in pool. Rest for all other questions that you have, its just a reference. So String[] holds reference to String Objects which include pooled objects as well. Similarly ArrayList will hold the reference.
Changing [] to ArrayList wont make a difference.
Rather changing these String to StringBuffer/builder will, as basic operations like +(concat) doesnot create a new object all together.
Case 1:
String str = "StackOverFlow";
String str1 = "StackOverFlow";
if(str==str1){
System.out.println("equal");//prints equal
}
Case 2:
String str = "StackOverFlow";
String str1=str.intern();
if(str==str1){
System.out.println("equal");//prints equal
}
follow up questions:
I want to know whether for the first case JVM calls intern() internally and assign the reference of str to str1?
how two references equal in the first case?
Does the first case means whenever you declare a string like String str = "StackOverFlow"; it adds to the pool of string as same as that of intern() method?
Does String pool which is used by String str = "StackOverFlow"; and intern() is allocated outside of heap? if yes where exactly?
For question 4 the answer is as below:
In Java 6 and earlier, interned strings were also stored in the permanent generation. In Java 7, interned strings are stored in the main object heap.
Here is what documentation says:
In JDK 7, interned strings are no longer allocated in the permanent
generation of the Java heap, but are instead allocated in the main
part of the Java heap (known as the young and old generations), along
with the other objects created by the application. This change will
result in more data residing in the main Java heap, and less data in
the permanent generation, and thus may require heap sizes to be
adjusted. Most applications will see only relatively small differences
in heap usage due to this change, but larger applications that load
many classes or make heavy use of the String.intern() method will see
more significant differences.
Further details from here:
String.intern() in Java 6
In those good old days all interned strings were stored in the PermGen
– the fixed size part of heap mainly used for storing loaded classes
and string pool. Besides explicitly interned strings, PermGen string
pool also contained all literal strings earlier used in your program
(the important word here is used – if a class or method was never
loaded/called, any constants defined in it will not be loaded).
The biggest issue with such string pool in Java 6 was its location – the PermGen. PermGen has a fixed size and can not be expanded at
runtime. You can set it using -XX:MaxPermSize=96m option. As far as I
know, the default PermGen size varies between 32M and 96M depending on
the platform. You can increase its size, but its size will still be
fixed. Such limitation required very careful usage of String.intern –
you’d better not intern any uncontrolled user input using this method.
That’s why string pooling at times of Java 6 was mostly implemented in
the manually managed maps.
String.intern() in Java 7
Oracle engineers made an extremely important change to the string
pooling logic in Java 7 – the string pool was relocated to the heap.
It means that you are no longer limited by a separate fixed size
memory area. All strings are now located in the heap, as most of other
ordinary objects, which allows you to manage only the heap size while
tuning your application. Technically, this alone could be a sufficient
reason to reconsider using String.intern() in your Java 7 programs.
But there are other reasons.
The references are equal because they are both String literals.
The intern() call on str is not needed because it is also a literal. An example of when you would need to use intern() (which, by the way is a lot slower then equals(), so don't use it) would be when constructing a String with a byte or char array.
For example:
final String str1 = "I am a literal";
final String str2 = new String(str1.toCharArray());
final boolean check1 = str1 == str2; // false
final boolean check2 = str1 == str2.intern(); // true
1) I want to know whether for the first case JVM calls intern() internally and assign the reference of str to str1?
Well, yes and no.
Yes the intern() method is called internally. But the call doesn't happen when that code is run. In fact, it happens when that code is loaded. The loader then saves the reference to the interned String.
But in this case, the loading process only needs to do the interning once. The two literals (in this case) will actually be represented by a single "constant pool entry" in the class that is being loaded. (The Java compiler will have spotted the duplicate literals in the class ... at compile time ... and eliminated it.)
2) how two references equal in the first case?
Because the two strings have been interned.
3) Does the first case means whenever you declare a string like String str = "StackOverFlow"; it adds to the pool of string as same as that of intern() method?
Yes ... modulo that the interning doesn't happen at the point when the code containing the declaration is run.
4) Does String pool which is used by String str = "StackOverFlow"; and intern() is allocated outside of heap? if yes where exactly?
The answer is somewhat system dependent. In general, the string pool is in the heap. On some systems the heap is divided into regions or spaces which have different garbage collection policies, and the string pool is allocated in the so-called "permgen" space that is sized independently of the rest of the heap. But this is not always true.
I want to know whether for the first case JVM calls intern() internally
No.
and assign the reference of str to str1?
Yes, but because the value is a literal, not because of interning. There is only one instance of it in the .class file in the first place.
how two references equal in the first case?
That's not another question, just the same question re-stated.
Does the first case means whenever you declare a string like String str = "StackOverFlow"; it adds to the pool of string as same as that of intern() method?
Yes, but it's done by the compiler, not intern().
Does String pool which is used by String str = "StackOverFlow"; and intern() is allocated outside of heap?
No.
where exactly?
In the constant pool of the loaded class, which is in the heap.
There are largely 2 ways of creating string objects.
One is
String str = "test-String"; // This string is created in string pool or returned from
string pool if already exists
Second one
String str = new String("test-string");// This string object will be created in heap memory and will be treated as any other object
When you call string.intern on the string instance created using new operator... this string will be created in string-pool or returned from the pool if exists. This is a mechanism to move the string object from heap to perm Gen (String pool)