String Intern and Memory Usage

0
1139

In this post, we will cover about java.lang.String.intern() and show some examples as well to understand the concept completely. Prior to that it is important to understand the concept of Strings in Java and String Pool. Learning that would make it easy to understand the usability of intern and the benefits it brings.

Concept of String Pool

String Pool a concept built over Flyweight design pattern. It is basically a pool of Strings stored in Java Heap. String is a special class in Java and the String object can be created in a couple of ways but its allocation can be costly in terms of time and memory. A lot is dependent on how we are creating a String.

JVM itself provides a couple of techniques to increase the performance and decrease the memory overhead. To cut down in-necessary String object creation, the JVM keeps track of string pool. “So every time a String is created, it checks the string literal pool first. If a string is already there it returns a reference to that address else a new String object is instantiated.”

String Pool
String Pool

Different ways to initialize a String

Understanding the difference between String literal and String object is very important here. Any String which is inside double quotes like “string”, “java” etc. is a String literal. At high level both are String objects but the main difference comes from the point that:
This will be much clearer when you compare two String objects created using String literal and new operator. Let’s see with an example how Strings are stored in Memory:

String a = Value;
String b = Value;

String c = new String (Value);
String d = new String (Value);

System.out.println(a == b); // TRUE – Because String a and String b has same String reference
System.out.println(c == d); // FALSE – Because new() created a new String Object reference
System.out.println(a == d); // FALSE – Because new() created a new String Object reference

What is String Intern

The java.lang.String.intern() is a method of storing only one copy of each distinct string value.
All literal strings and string-valued constant expressions are interned. Intern() method returns a string that has the same content as this string, but is guaranteed to be from the pool of unique strings.

In simple words “String interning is intended to reuse String objects to reduce memory usage”

Strings in java have a build in feature of intern which is also called automatic intern. When we declare a string using literals they are automatically interned but when a new () operator is used to declare a string then it always create a new String Object. We can use intern () method in a situation when they are not constants, and we want to be able to quickly compare them to other interned strings. The intern () method should be used on strings constructed with new String () in order to compare them by == operator.

Another difference between string literal and new string is – In case of new(), interning doesn’t happen automatically, until you call intern () method on that object.

[symple_highlight color=”gray”]For any two strings a and b, a.intern() == b.intern() is true, if and only if a.equals(b) is true.[/symple_highlight]

Let us first write a simple code sample to bring more clarity on this.

An example of Implicit or Automatic Interning

public class goyalsBit {
public static void main(String[] args) {
String str1 = "goyal::5";
String str2 = "goyal::5";

System.out.println(str1.equals(str2));
System.out.println(str1 == str2);
}
}

Output in this case is true, true.
Both strings were initialized with compile time constant expressions (“goyal::5”) and referring to the same object. This concept is called automatic or implicit interning.

Now let’s look at another example:

public class goyalsBit {
public static void main(String[] args) {
int a=5;
String str1 = "goyal::5";
String str2 = "goyal::"+a;

System.out.println(str1.equals(str2));
System.out.println(str1 == str2);
}
}

Output in this case is true, false. Here, although the value of both strings is same but still initialization method was different. So automatic interning did not happen for str2. Now you know that in this case there will be two different objects having same value.

An example of Explicit Interning

public class goyalsBit {
 public static void main(String[] args) {
  int a=5;
  String str1 = "goyal::5";
  String str2 = "goyal::"+a;
  Str2=str2.intern();
  System.out.println(str1.equals(str2));
  System.out.println(str1 == str2);
}
}

The output here is true, true. The statement str2.intern() will compare the value of str2 with values in the pool and return the reference to the string literal pointed by str1 from the pool . Now String being immutable, it will not change the value of str2 automatically. So we need to reinitialize string str2 by assign the value of str2.intern().

In Java we mostly use equals() method instead of operator ==, to compare two strings. The equals() method can be fairly slow as it involves a character-by-character comparison of the strings. Since the == operator compares identity, all it has to do is compare two pointers to see if they are the same, and obviously it will be much faster than equals(). So if you’re going to compare the same strings repeatedly, you can get a significant performance advantage by reducing it to an identity comparison rather than an equality comparison.

The Java Pooling implements the above concept using auto interning & making sure that if two strings contain the same characters, they are also the same instance. This means that you can safely compare strings using == operator rather than equals() method, gaining a significant performance advantage with repeated comparisons.

String str1 = new String ("goyal");
String str2 = new String ("goyal");

System.out.println("Compare first " + (str1 == str2));
System.out.println("Compare Second " + (str1.intern()==str2.intern()));

The output is false, true.

When to use java.lang.String.intern()

Many people ask if is it a good practice to use java.lang.String.intern(). Well based on the discussion we had above, my conclusion is that the intern() method can be very useful when we want to search through Strings or when we want to retrieve information from a large text. The best practice is to use String.intern() on Strings that occur multiple times inside a program and only when you want to save memory. It will be effective depending on the ratio of unique versus duplicate String objects.

If you have used these concepts anywhere, share your experience in comments section.

References

https://weblogs.java.net/blog/enicholas/archive/2006/06/all_about_inter.html
https://docs.oracle.com/javase/6/docs/api/java/lang/String.html

Previous articleLogging in Java – Log4J
Next articleTop 10 Eclipse Short cut keys
Rahul Goel has 8+ years of experience in IT industry working on design & development of web based applications in Java /JEE technology stack. He posses various business domains knowledge like HealthCare, Banking & Finance, E Commerce, Retail, and Security. Rahul is passionate about cricket, traveling and his technical writing.

NO COMMENTS

LEAVE A REPLY