8 Replies Latest reply: May 25, 2011 3:01 PM by 864482 RSS

    Hacking immutability with reflection and its implications

    843798
      Hi all,

      When I was experimenting with Java reflection, I came to a situation where-in I could access private and final fields of a class and change its value. So I tried it with Java's most famous immutable object-String. I could change the value stored by the string, still retaining its hashCode() value unchanged, and equals() method not recognizing the change. Following is my test code.
      import java.lang.reflect.Field;
      
      
      public class AccessibilityTest {
      
           /**
            * @param args
            */
           public static void main(String[] args) {
                
                String s = "Joby";
                System.out.println("INITIAL Value (Before change) ");
                System.out.println(s);          
                System.out.println(s.hashCode());
                
                Class class1 = String.class;
                try {              
                    Field field = class1.getDeclaredField("value");
      
                    field.setAccessible(true);
                    Object o = field.get(s);
                    if (o instanceof char[]){
                         char[] arr = (char[])o;
                         //Change the internal value of the String.
                         for (int n =0;n<arr.length;n++){
                              arr[n] = 'm';
                         }
                    }
      
                } catch (NoSuchFieldException e) {
                    System.out.println("FieldNotFound: " + e);
                } catch (IllegalAccessException e) {
                    System.out.println("Ilegal Access: " + e);
                }
                System.out.println("Value (After change) ");
                
                System.out.println(s);
                System.out.println(s.hashCode());
                System.out.println("\n ----Equality check--- ");
                System.out.println(s+" == Joby ? "+ s.equals("Joby"));
           }
      
      }
      The interesting output is given below:
      INITIAL Value (Before change) 
      Joby
      2314364
      Value (After change) 
      mmmm
      2314364
      
       ----Equality check--- 
      mmmm == Joby ? true
      Can some one help me in understanding:

      1) Why this is allowed in Java?
      2) What is the implication of this?

      Thanks in advance,
      Joby