Java string pool coupled with reflection can produce some unimaginable result in Java:
import java.lang.reflect.Field; class MessingWithString { public static void main (String[] args) { String str = "Mario"; toLuigi(str); System.out.println(str + " " + "Mario"); } public static void toLuigi(String original) { try { Field stringValue = String.class.getDeclaredField("value"); stringValue.setAccessible(true); stringValue.set(original, "Luigi".toCharArray()); } catch (Exception ex) { // Ignore exceptions } } }
Above code will print:
"Luigi Luigi"
What happened to Mario?
String Pool is a storage area in Java heap. String allocation, like all object allocation, proves to be a costly affair in both the cases of time and memory. The JVM performs some steps while initializing string literals to increase performance and decrease memory overhead.
All Strings are stored in the String Pool (or String Intern Pool) that is allocated in the Java heap. String pool is an implementation of the String Interring Concept. String Interning is a method that stores only a copy of each distinct string literal. The distinct values are stored in the String pool.
Although both reference variable s3 and s4 point to the String objects with the same value Hello but as these objects are creating with the new keyword, hence, these objects are stored in normal heap memory where the String objects with duplicate values can be stored.
To make the java more memory efficient the concept of string literal is used. By the use of 'new' keyword, the JVM will create a new string object in the normal heap area even if the same string object present in the string pool.
What happened to Mario ??
You changed it, basically. Yes, with reflection you can violate the immutability of strings... and due to string interning, that means any use of "Mario" (other than in a larger string constant expression, which would have been resolved at compile-time) will end up as "Luigi" in the rest of the program.
This kinds of thing is why reflection requires security permissions...
Note that the expression str + " " + "Mario"
does not perform any compile-time concatenation, due to the left-associativity of +
. It's effectively (str + " ") + "Mario"
, which is why you still see Luigi Luigi
. If you change the code to:
System.out.println(str + (" " + "Mario"));
... then you'll see Luigi Mario
as the compiler will have interned " Mario"
to a different string to "Mario"
.
It was set to Luigi. Strings in Java are immutable; thus, the compiler can interpret all mentions of "Mario"
as references to the same String constant pool item (roughly, "memory location"). You used reflection to change that item; so all "Mario"
in your code are now as if you wrote "Luigi"
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With