Why YGC Slows Down: The Impact of String.intern and StringTable on Young Generation GC
This article explains how excessive use of String.intern can enlarge the JVM's StringTable, causing the Young Generation Garbage Collection (YGC) to take longer, and provides a demo, code analysis, and practical tips for diagnosing and mitigating the slowdown.
The author writes this article because the YGC process often appears as a black box; ordinary GC logs only show total pause time without revealing which phase consumes the time, making root‑cause analysis difficult without deep JVM knowledge.
A simple demo is presented where a program repeatedly creates UUID strings and calls intern() on each, using JVM options -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -Xmx2G -Xms2G -Xmn100M to force a small young generation and a large old generation, thereby highlighting the problem.
The demo output shows YGC events occurring continuously, with pause times growing from about 10 ms to 40 ms and beyond, indicating a performance degradation linked to the interned strings.
The article then explains the String.intern() method: it is a native call that ensures only one copy of a given string value exists in the JVM. The implementation uses a global StringTable , which is essentially a hash table storing interned strings.
oop StringTable::intern(oop string, TRAPS) {
if (string == NULL) return NULL;
ResourceMark rm(THREAD);
int length;
Handle h_string(THREAD, string);
jchar* chars = java_lang_String::as_unicode_string(string, length);
oop result = intern(h_string, chars, length, CHECK_NULL);
return result;
}
oop StringTable::intern(Handle string_or_null, jchar* name, int len, TRAPS) {
unsigned int hashValue = hash_string(name, len);
int index = the_table()->hash_to_index(hashValue);
oop found_string = the_table()->lookup(index, name, len, hashValue);
if (found_string != NULL) return found_string;
// ... create or reuse string and add to table ...
MutexLocker ml(StringTable_lock, THREAD);
return the_table()->basic_add(index, string, name, len, hashValue, CHECK_NULL);
}When intern() is called, the JVM first checks the StringTable for an existing entry; if none is found, a new entry is added. The size of this table can be tuned with the JVM flag -XX:StringTableSize , whose default is 1009 on 32‑bit and 60013 on 64‑bit platforms.
During a YGC, the garbage collector scans the StringTable because the table resides in the heap (unless JavaObjectsInPerm is true). The scanning code looks like:
if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) {
if (so & SO_Strings || (!collecting_perm_gen && !JavaObjectsInPerm)) {
StringTable::oops_do(roots);
}
if (JavaObjectsInPerm) {
NOT_PRODUCT(StringTable::oops_do(&assert_is_perm_closure));
}
}Because YGC does not collect the permanent generation, the collecting_perm_gen flag is false, and by default JavaObjectsInPerm is also false, meaning the strings interned by String.intern() are allocated on the heap and must be scanned during each YGC. A larger StringTable therefore directly increases the time spent in the YGC pause.
The CPU impact of this scanning is limited to a single GC thread, so on machines with many cores the overhead may appear negligible; however, the pause time still grows linearly with the amount of work the thread must do.
YGC never cleans the StringTable . Only Full GC or CMS cycles perform cleanup, which can be verified by running jmap -histo:live <pid> before and after a Full GC to see the table size drop.
In summary, excessive interning creates a bloated StringTable , which prolongs YGC pauses because the collector must scan the table each young‑generation collection; adjusting -XX:StringTableSize or reducing unnecessary interning can mitigate the issue.
Qunar Tech Salon
Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.
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.