Fundamentals 15 min read

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.

Java Architect Handbook
Java Architect Handbook
Java Architect Handbook
What’s the Relationship Between the JVM Runtime Constant Pool and the String Constant Pool?

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.

Constant pool evolution diagram
Constant pool evolution diagram

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.

JDK version memory layout
JDK version memory layout

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: false

In 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaJVMMemory ManagementInterviewConstant PoolString Interning
Java Architect Handbook
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.