[For those who read the book OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide, this is explained on page 441 in the box Why Does readPassword() Return a Character Array?]
Can someone explain me why it would be unsecure to return the password as a String in the method Console.readPassword()? I don't see why the String could go into the pool as it is not a literal. So it should be garbage collected as soon as it is not referenced anymore, right?
Is it related to the fact that Strings are immutable and that they can just stay in memory as long as the memory has not been reallocated even if they are not referenced anymore?
Maybe I'm having trouble with the definition of String pool. I read in the review question 2 on page 445:
Because Java puts all String values in a reusable pool
Is it really correct to say that? What about
Is it not only literals that are inserted into the pool?
The main issue here is not that Strings are interned. The issue here is that Strings are immutable. Once you have the password in a String, the piece of memory that holds that string cannot be changed, in the worst case, ever, and in the best case, until the String is GCed. So during that time it is possible to take a dump of the program memory and figure out the password.
A char array can be wiped clean by the program itself as soon as the need to use the password is over.
It is just one of the several security measures.
First off, I believe the String pool is a Java 8 OCA topic, so you might want to review your OCA material.
It's a little beyond the scope of the text (and Java programming in general) but if you were to do a memory dump of the program in action, perhaps by finding a way to force kill the process, you could read that memory dump and access any String that has been added to the String pool. I believe most JVMs keep Strings in the pool a very long time, perhaps indefinitely. In this manner, storing a password (or credit card details!) as a String is not considered completely safe, at least not in terms of memory management.
Contrast this with, as Paul said, a char array. A char array can be immediately erased in memory by iterating over it and setting a new value for each character. In this case, performing a memory dump would not show the password.
For the OCP exam, you only need to know that the Console method uses char for a password, and it does so for security reasons so the password doesn't end up in the String pool. The details of how you crash an app, read a memory dump, etc are well beyond the scope of the exam.
This explanation about the password being potentially stored in the pool bothered me as well, as it seems to contradict the OCA material, especially regarding the behavior of the == operator between literal strings and "dynamic" strings.
I think I understand it better with Paul's explanation.
Literals strings are put in the pool. Dynamic strings can be put in the pool with the intern() method ; if the string already exists in the pool, intern() returns the instance in the pool. So the password shouldn't be in the pool, unless we explicitly put it in.
But, even if we don't internalized it, from a physical memory point of view, the string instance is still somewhere. As it is immutable, the Java program has no way to erase or scramble it.
When the string stops being referenced in the Java program, it becomes eligible for garbage collection, but is still physically in the memory. And even if it is garbage collected, depending on the JVM implementation, I guess it doesn't necessarily mean that the corresponding physical memory is reset ; it just had to made available for a future allocation. And that's when a new object is allocated in these memory adresses than the bits will be reset. So the string can stay a very long time in the process memory.
Using a char array is the only way for the Java program to voluntarily, and in a timely fashion, overwrite the password in the memory.