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.
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.
I couldn't find it on the api or by searching the web..
I know the JVM keeps every String object it has in a string pool in order to optimize memory usage. However I can't figure out how does it save it 'under the hood', Since a String is an immutable object using the toCharArray will get me a copy of the internal array the is stored on the String object in the pool? (if so than every operation involved in getting the string array as a char is O(n)) also - using charAt(i) uses the internal array of the string? or does it copy it to a new array and return the char at position i of the new copied array?
Until Java 8, Strings were internally represented as an array of characters – char[], encoded in UTF-16, so that every character uses two bytes of memory.
When we create a String via the new operator, the Java compiler will create a new object and store it in the heap. For example.
String str1= new String("Hello");
When we create a String variable and assign a value to it, the JVM searches the pool for a String of equal value. If found, the Java compiler will simply return a reference to its memory address, without allocating additional memory.If not found, it’ll be added to the pool and its reference will be returned.
String str2= "Hello";
toCharArray() internally creates a new char[] array by copying the characters of original array to the new one.
charAt(int index) returns the value of specified index of the internal (original) char[] array.
With Java 9 a new representation is provided, called Compact Strings. This new format will choose the appropriate encoding between char[] and byte[] depending on the stored content. Since the new String representation will use the UTF-16 encoding only when necessary, the amount of heap memory will be significantly lower, which in turn causes less Garbage Collector overhead on the JVM.
Source:
http://www.baeldung.com/java-string-pool
This question already has answers here:
Why is char[] preferred over String for passwords?
(17 answers)
Closed 7 years ago.
In a discussion one of our senior told that we should not use String for storing password in a Java project because it's a security risk.
But it can be acceptable in C project. I did not get why he said that.
Can anyone tell me why so?
In Java, Strings are immutable, so once you use String to store a password, there is no way that content can be changed because any change will produce new String.
And the String which contains the password, will be available in memory until it got garbage collected. So it will be remain in memory for long duration which might be a security risk.
But, in C language, String is a null terminated character array and you can set all the array elements as blank or zero, therefore the password will not be remain in memory.
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.
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)