Is String really immutable?

Preface

When you mention String in Java, you always mention that String is immutable.But is this true?Can String's immutability be destroyed?

Before validating, you need to first introduce the immutable properties of String.

PS: Also mention the interview questions you have encountered here:

String str = "abc";


// Output def
System.out.println(str);

String Invariant

String's immutability refers to

  • String internally uses a final-modified char array value to store the value of a string
  • The value of the array value is already assigned when the object is constructed
  • String does not provide a method to modify values in an array value
  • The method in String that needs to modify the value, such as replace, returns a new String object directly

So String is immutable.

Destroy String's Invariance

String immutability is essentially achieved around the fact that value is an immutable array of char s, but it can be completely destroyed by Java reflection.

The key codes are as follows:

        String str="test";
        // Reference address of str object
        printAddresses("str",str);
        try {
            Field field=str.getClass().getDeclaredField("value");
            //
            char[] newChars={'h','e','l','l','o'};
            // Make the value of the private property accessible
            field.setAccessible(true);
            // Replace the value of the value array
            field.set(str,newChars);
            // Replaced value
            System.out.println("str value:"+str);
            // After replacement, the reference address of the str object
            printAddresses("str",str);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

The way to print the object address above is by reference How to get the address of a Java object Sample code, as follows:

    /**
     * Print object address
     * @param label
     * @param objects
     */
    public void printAddresses(String label, Object... objects) {
        System.out.print(label + ":0x");
        long last = 0;
        Unsafe unsafe=getUnsafe();
        int offset = unsafe.arrayBaseOffset(objects.getClass());
        int scale = unsafe.arrayIndexScale(objects.getClass());
        switch (scale) {
            case 4:
                // 64-bit JVM
                long factor = 8;
                final long i1 = (unsafe.getInt(objects, offset) & 0xFFFFFFFFL) * factor;
                System.out.print(Long.toHexString(i1));
                last = i1;
                for (int i = 1; i < objects.length; i++) {
                    final long i2 = (unsafe.getInt(objects, offset + i * 4) & 0xFFFFFFFFL) * factor;
                    if (i2 > last)
                        System.out.print(", +" + Long.toHexString(i2 - last));
                    else
                        System.out.print(", -" + Long.toHexString(last - i2));
                    last = i2;
                }
                break;
            case 8:
                throw new AssertionError("Not supported");
        }
        System.out.println();
    }

    /**
     * Obtaining Unsafe Objects by Reflection
     * @return
     */
    private static Unsafe getUnsafe() {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            return (Unsafe) theUnsafe.get(null);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }

Run Results

str:0x76b4136e0
str value:hello
str:0x76b4136e0

As you can see from the results, reflection allows you to modify the value of a String object without modifying its object address.

conclusion

Reflection can actually be used to destroy the immutability of String, but it is also a Java-provided feature that makes it hard to avoid being used.

At that time, I still thought there was no solution to the question mentioned above, but as I continue to learn, I find that many times I can find different ways from a different angle.

Keywords: Java jvm

Added by golfinggod on Wed, 24 Jul 2019 19:09:47 +0300