What’s the Relationship Between the JVM Runtime Constant Pool and the String Constant Pool?
This article explains the three Java constant pools—class file, runtime, and string—detailing their evolution from compilation to execution, their memory locations across JDK versions, how string literals are interned, code examples illustrating their behavior, common misconceptions, and typical interview follow‑up questions.
Interview Focus
Concept distinction ability : differentiate class file constant pool, runtime constant pool, and string constant pool.
JVM memory model understanding : know where each pool resides in JVM memory and how its location changes across JDK versions.
Actual behavior understanding : explain the underlying actions of String s = "hello" and String s = new String("hello") and the role of the constant pools.
Core Answer
Class file constant pool is static and stored in the .class file. When the class is loaded it becomes the runtime constant pool located in the method area (Metaspace in JDK 8). String literals in the runtime constant pool are referenced by the string constant pool , a global hash table dedicated to String objects.
Class file constant pool
Location: .class file
Content: literals, symbolic references (class, method, field names)
Lifecycle: static, generated at compile time
Runtime constant pool
Location: method area (Metaspace in JDK 8)
Content: runtime representation of the class file constant pool plus dynamic constants
Lifecycle: created with class loading, reclaimed with class unloading
String constant pool
Location: heap (JDK 7+)
Content: references to String objects
Lifecycle: global, lives for the whole JVM process
Deep Analysis
1. Evolution of the Three Constant Pools
The transformation chain consists of three stages:
Stage 1 – Compilation : javac generates a .class file containing a Constant Pool Table with all literals (strings, numbers) and symbolic references (fully‑qualified class, method, field names). These entries are static and stored on disk.
Stage 2 – Class Loading : The JVM loads the class, copies the class file constant pool into memory as the runtime constant pool . Symbolic references are resolved to direct memory addresses. Each class gets its own runtime constant pool.
Stage 3 – String Interning : String literals in the runtime constant pool are automatically "interned" into the string constant pool , a global hash table ( StringTable) shared by all threads.
2. Runtime Constant Pool vs String Constant Pool – Relationship
The relationship can be understood from three dimensions:
Dimension 1: Inclusion
The runtime constant pool is broader; it holds strings, numeric constants, class/method/field references, etc. The string constant pool stores only String objects.
Dimension 2: Association
When a class is loaded, a string literal such as "hello" triggers a lookup in the string constant pool:
If the literal already exists, the runtime constant pool points directly to that reference.
If not, a new String object is created on the heap, its reference is stored in the string constant pool, and the runtime constant pool points to it.
Dimension 3: Memory Location Changes
JDK 7 moved the string constant pool from the permanent generation (PermGen) to the heap because PermGen is limited (default 82 MB) and string literals can easily cause java.lang.OutOfMemoryError: PermGen space. The heap provides much larger space and more flexible GC. JDK 8 removed PermGen entirely and introduced Metaspace, which uses native memory.
3. Code Examples to Understand Constant‑Pool Behavior
Classic example:
public class StringPoolDemo {
public static void main(String[] args) {
// Case 1: literal creation (automatically interned)
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true
// Case 2: new String() (creates a new object on the heap)
String s3 = new String("hello");
System.out.println(s1 == s3); // false
// Case 3: intern() manually interns
String s4 = s3.intern();
System.out.println(s1 == s4); // true
}
}Concatenation example that shows JDK‑dependent results:
String s1 = new String("he") + new String("llo");
// 1. "he" and "llo" are literals, loaded into the string pool at class load time.
// 2. new String("he") creates a heap object.
// 3. new String("llo") creates another heap object.
// 4. '+' uses StringBuilder, producing a new heap object "hello".
// 5. "hello" is NOT in the string pool yet.
s1.intern(); // puts the heap "hello" into the string pool (JDK 7+ stores the reference).
String s2 = "hello";
System.out.println(s1 == s2); // JDK 7+: true, JDK 6: falseIn JDK 6 the intern() call copies the String object into PermGen, so the reference differs from the heap object. In JDK 7+ the pool records the heap reference directly, making the references equal.
4. Common Misconceptions
Misconception 1 : The string constant pool stores the String objects themselves. Reality : Since JDK 7 it stores only references to heap objects; JDK 6 stored the objects in PermGen.
Misconception 2 : The runtime constant pool and the string constant pool are the same. Reality : The runtime constant pool is per‑class and holds many kinds of constants; the string constant pool is global and dedicated to strings.
Misconception 3 : String.intern() always creates a new object. Reality : It first checks the string pool; if the literal already exists, it returns the existing reference without creating a new object.
High‑Frequency Follow‑Up Questions
How many objects are created by String s = new String("abc") ? At most two: one for the literal "abc" (if not already in the pool) and one for the heap object created by new. If the literal is already pooled, only the heap object is created.
Why did JDK 7 move the string constant pool to the heap? The permanent generation is limited (≈82 MB) and heavy string usage can cause PermGen OOM. Moving to the heap provides gigabytes of space and more flexible GC.
What is the practical use of intern() in production? It deduplicates identical strings to reduce memory consumption, e.g., when many duplicate strings are read from a database. Overuse can bloat the pool (especially in JDK 6), so alternatives like a custom string pool or Set are preferred.
Typical Interview Variants
" String s = new String("abc") creates how many objects?"
"Differences between JDK 6 and JDK 7 string constant pools?"
"What does String.intern() do?"
"What is string interning?"
Mnemonic Summary
Three‑pool evolution : class constant pool (static, in .class) → runtime constant pool (live, in method area/Metaspace) → string constant pool (global StringTable, in heap for JDK 7+).
Key distinction : runtime constant pool is per‑class; string constant pool is JVM‑wide and only handles String objects.
Overall Summary
The runtime constant pool is the live incarnation of the class file constant pool (one per class). The string constant pool is a JVM‑wide hash table that de‑duplicates String objects; string literals in the runtime pool are linked to the string pool to achieve reuse. Explaining the three‑pool evolution chain and demonstrating new String() and intern() code examples covers the core interview discussion.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architect Handbook
Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
