The String.intern() method can be used to deal with the String duplication problem in Java. By carefully using the intern() means you can save a lot of heap memory consumed by duplicate String objects. A String object is said to be duplicated if it contains the same content as another string but occupied a different memory location e.g. str1 != str2 but str1.equals(str2) is true. Since the String object consumes a large amount of heap memory in the average Java application, it makes sense to use the intern() method to reduce duplication and take advantage of the String pool feature provided by Java. You can use the intern() method to intern a String object and store them into the String pool for further reuse.
For example, when you create a String literal like "ABC" then it's automatically stored in String pool, but when you create a new String object, e.g. new String("abc"), even though it's the same String, a new object at a different memory location is created. This is a duplicate String.
By calling the intern() method on this object, you can instruct JVM to put this String in the pool and whenever someone else creates "abc", this object will be returned instead of creating a new object.
This way, you can save a lot of memory in Java, depending upon how many Strings are duplicated in your program. You can also join the Understanding and Solving Java Memory Problems course By Richard Warburton on Pluralsight to learn more.
1. The String.intern() method is there in the String class from JDK 1.1. It returns a canonical representation of String objects. When the intern method is invoked, if the String pool already contains that String object such that equals() return true, it will return the String object from the pool, otherwise it will add that object to the pool of unique String.
2. After calling intern() method on s1 and s2, s1.intern() == s2.intern(), if s1.equals(s2) because both will be pointing same String constant in pool.
3. Prior to Java 6, uncontrolled usage of String.intern() method can cause java.lang.OutOfMemory: PermGen space because String pool was physically located on PermGen area of Java heap, which is quite small in many JVM (32M to 96M) and fixed.
From Java 7 onward, the intern() method has become even more useful because the String pool is relocated to the main heap space of JVM.
This will help to further reduce String duplication by using String.intern() method.
In the below diagram you can see that s3 and s4 are referring to the same String object "java" in the String pool because they are interned String while s1 and s2 are referring to separate objects because they are not interned or not using String literal.
You can also join the Understanding and Solving Java Memory Problems course By Richard Warburton on Pluralsight to learn more.
For example, when you create a String literal like "ABC" then it's automatically stored in String pool, but when you create a new String object, e.g. new String("abc"), even though it's the same String, a new object at a different memory location is created. This is a duplicate String.
By calling the intern() method on this object, you can instruct JVM to put this String in the pool and whenever someone else creates "abc", this object will be returned instead of creating a new object.
This way, you can save a lot of memory in Java, depending upon how many Strings are duplicated in your program. You can also join the Understanding and Solving Java Memory Problems course By Richard Warburton on Pluralsight to learn more.
Important things about String.intern() method in Java
Here are some of the important points about the intern() method from java.lang.String class which is worth remembering:1. The String.intern() method is there in the String class from JDK 1.1. It returns a canonical representation of String objects. When the intern method is invoked, if the String pool already contains that String object such that equals() return true, it will return the String object from the pool, otherwise it will add that object to the pool of unique String.
2. After calling intern() method on s1 and s2, s1.intern() == s2.intern(), if s1.equals(s2) because both will be pointing same String constant in pool.
3. Prior to Java 6, uncontrolled usage of String.intern() method can cause java.lang.OutOfMemory: PermGen space because String pool was physically located on PermGen area of Java heap, which is quite small in many JVM (32M to 96M) and fixed.
From Java 7 onward, the intern() method has become even more useful because the String pool is relocated to the main heap space of JVM.
This will help to further reduce String duplication by using String.intern() method.
In the below diagram you can see that s3 and s4 are referring to the same String object "java" in the String pool because they are interned String while s1 and s2 are referring to separate objects because they are not interned or not using String literal.
You can also join the Understanding and Solving Java Memory Problems course By Richard Warburton on Pluralsight to learn more.
And, if you like to read then you can also read Java Performance, The Definitive Guide By Scott Oaks to learn more about troubleshooting Java Performance issues caused by String and optimizing the performance of Java applications.
4. Another thing to know about is that the intern() method is a non-static method and should be called using a String literal or String object in Java.
That's all about when to use String.intern() method in Java. The Java 8 update 20 also introduced a new feature called String deduplication, which can reduce memory footprint caused by duplicate String without writing a single line of code, but, unfortunately, it's only available for the G1 garbage collector and you cannot use it if you are using a ConcurrentMarkSweep garbage collector. You can also check out What's New in Java 8 on Pluralsight to learn more about G1 GC and other changes introduced in Java 8.
Other Java String concepts articles you may like
If you want to learn more about the String class in Java, don't forget to read the following articles:
- Why is String made final or Immutable in Java? (answer)
- How does the substring() method works in Java? (answer)
- Why char[] is more secure than String for storing a password in Java? (answer)
- How String in switch case internally implemented in Java 7? (answer)
- The right way to check if String is empty in Java? (answer)
- How to compare two String objects in Java? (answer)
- How does String concatenation work in Java? (answer)
- How to escape String literal in Java and Eclipse IDE? (tip)
- The real difference between String, StringBuffer, and StringBuilder in Java? (answer)
- What is String[] args argument in the main() method of Java program? (answer)
Thanks for reading this article so far. If you like this Java String article, then please share it with your friends and colleagues. If you have any questions or feedback then please drop a note.
Just to Add : -
ReplyDeleteWhen would I use this function in favor to String.equals()
when you need speed since you can compare strings by reference (== is faster than equals )
String interning is intended for saving memory if you have many strings with the same content in you application. By using String.intern() the application will only have one instance in the long run and a side effect is that you can perform fast reference equality comparison instead of ordinary string comparison (but this is usually not advisable because it is really easy to break by forgetting to intern only a single instance).
ReplyDeleteString s1 = "Hello".concat("World");
ReplyDeleteString s3 = new String("HelloWorld"); //Line-2
String s2 = s1.intern();
System.out.println(s1 == s2); //false
System.out.println(s1 == s3); //false
System.out.println(s2 == s3); //false
If I removed Line-2 and compare s1==s2, it will return true. Could anyone explain me what exactly happens in string pool after Line-2?
Thanks
Hello salman, intern() method put a String into String pool if it doesn't exist and return the reference of same String, but if a similar string exists e.g. which is equal using equals() method then reference of that String is returned from pool.
ReplyDeleteIn first case, because you have "HelloWorld" as literal, it already exists in pool before you call s1.intern() that's why reference of that String is returned and s1 == s2 return false because they both point to different object.
But in second case, "HelloWorld" doesn't exists in pool, hence a call to s1.intern() adds "HelloWorld" and return its reference, in this case both s1 and s2 pointing to same object, hence s1 == s2 is true.
In such case, why do i even need intern()? The best way to create a String object is by declaring it this way->
ReplyDeleteString a="abc";
instead of
String a = new String("abc");
Hello @Ana, if you programatically create string e.g. "abc" + "def" then it won't be created in the pool. In that case, if you want, you can add them into pool by using intern() method.
ReplyDeleteif use string.intern() in web frame, how to release the string constant, or the constant pool become very large.
ReplyDeleteDon't use it in java 8+, it clutters up internal JDK tables https://shipilev.net/jvm/anatomy-quarks/10-string-intern/
ReplyDeleteHow many object are created by this line String s = new String("abc");? Can anyone please explain it clearly?
ReplyDeleteTwo objects "abc" first object created in pool and "s" a new object created in heap.
ReplyDeleteFurther, to @Samlan-Khandu,
ReplyDeleteIf there is space between "Hello World", then the result is true, strangely:
String s1 = "Hello".concat("World");
String s3 = new String("Hello World"); // Line-2
String s2 = s1.intern();
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s2 == s3); // false