Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory management for Immutable Objects

I have a conceptual doubt regarding the memory management of Immutable objects such as String Objects in java and other languages. For example, if I have a String object "str" holding the value "Hello" and I do the following:

String str = "Hello";
str = str.concatenate("World");

In this case, as I understand it a new String object with the state "Hello World" is created and referenced back to str. Now, in Java (and in most other object oriented languages as well) the lifetime of any object is as long as its reference is alive. So where does the object holding "Hello" go. Does it reside in the memory heap until a garbage collector takes care of it at its own leisure? Also, what about languages that do not support a garbage collector and have to depend on class destructors?

Also, if mutable objects such as StringBuffer and StringBuilder are much more flexible and performance friendly, why make objects immutable in the first place, while designing the language?? (I mean why aren't String Objects mutable right from the beginning instead of having to introduce new structures such as String Buffers in subsequent JDK releases?).

It would be great if someone can guide me on this. I am new to this so a clear, fundamental explanation would be highly appreciated. Thanks.

like image 570
Darth Coder Avatar asked Oct 25 '25 09:10

Darth Coder


2 Answers

This is actually a question about the java String class in particular - not immutability in general. When Java was first introduced the designers decided to make String special - in some ways it's halfway between a reference type and a primitive type.

The advantage we get with String is that a common pool of string literals is kept by the virtual machine stopping the Heap getting filled up - see here for a description. The reasoning behind this is that much of the memory of a program can be taken up with storing commonly used strings. See also String.intern.

For any other kind of immutable object this isn't the case (sadly). Your question about where str goes has been answered by somebody else - it follows the normal garbage collection rules that I'm sure you know about (or can find out).

Perhaps the most interesting part of your question is

Also, if mutable objects such as StringBuffer/StringBuilder are much more flexible and performance friendly, why make objects mutable in the first place, while designing the language?? (I mean why aren't String Objects mutable right from the beginning instead of having to introduce new structures such as String Buffers in subsequent jdk releases?).

My answer would be that the common case is that we have lots of identical strings, and we want to optimise for the common case. Note also that the Java compiler uses StringBuilder when concatenating strings. For example take this code

public class StringBuilderTest {

  public static void main(String [] args){

    String hello = "hello ";
    String world = "world";
    System.out.println(hello+world);
   }
}

and disassemble it using

javap -c StringBuilderTest

and get the following bytecode for the main method

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String hello 
       2: astore_1      
       3: ldc           #3                  // String world
       5: astore_2      
       6: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
       9: new           #5                  // class java/lang/StringBuilder
      12: dup           
      13: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
      16: aload_1       
      17: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      20: aload_2       
      21: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      24: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      27: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      30: return        
}

which uses a StringBuilder to perform the append.

like image 148
selig Avatar answered Oct 26 '25 23:10

selig


Strings are immutable to follow the principle of Least Surprise.

Primitive types such as int, float and char are copied by value - if you copy its value to another place and edit one of the copies, it is actually an entirely new primitive that has been edited, and no changes are seen in the other place.

Strings are not primitives, but they are 'treated as primitives' in a lot of ways, conceptually. Since we are so used to the copy by value traits of primitives, what happens if Strings were made to be mutable but we forgot and treated them as though they had copy-by-value semantics?

Things could get messy. For instance:

-Any time you returned a string, you would have to return a copy of the string, or else the consumer of the string could edit it, and suddenly your string is edited too! For example, data like usernames, passwords, messages could get 'surprisingly' edited.

-Security is an issue. If you call unknown code and it alters a string you are using, then you have to remember and make copies of all the strings (performance issues also!) or suffer random detrimental behaviour when they change out from under your feet.

-String interning would be impossible (which is a mechanic by which strings with the same value can be handed out reusably, so only one object of that string value exists instead of two). The string intern table relies on strings being immutable.

It is a tradeoff - performance in some ways, vs performance in other ways (now needing to copy strings whenever you want to be sure the thing you pass the string to does not edit it is a performance loss!), more difficulty reasoning about your code (strings are so ubiquitous, and if any string could change at any time for any reason, if it's EVER been exposed and another reference acquired to it...), etc.

like image 29
Patashu Avatar answered Oct 27 '25 00:10

Patashu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!