用于访问JDK 8 HotSpot JVM中的字符串池内容的实用程序

是否有任何实用程序或脚本(使用java或本机代码)查看JDK 8 HotSpot JVM中String Pool中存在的所有字符串的列表,而不会对JVM产生很多性能影响?

或者,只要将新字符串添加到JVM中,我是否可以将侦听器连接起来?

谢谢,哈里什

您可以使用默认包含在JDK中的HotSpot Serviceability Agent轻松地创建自己的实用程序。

 import sun.jvm.hotspot.memory.SystemDictionary; import sun.jvm.hotspot.oops.InstanceKlass; import sun.jvm.hotspot.oops.OopField; import sun.jvm.hotspot.runtime.VM; import sun.jvm.hotspot.tools.Tool; public class InternedStrings extends Tool { @Override public void run() { // Use Reflection-like API to reference String class and String.value field SystemDictionary dict = VM.getVM().getSystemDictionary(); InstanceKlass stringKlass = (InstanceKlass) dict.find("java/lang/String", null, null); OopField valueField = (OopField) stringKlass.findField("value", "[C"); // Counters long[] stats = new long[2]; // Iterate through the String Pool printing out each String object VM.getVM().getStringTable().stringsDo(s -> { s.printValueOn(System.out); System.out.println(); stats[0]++; stats[1] += s.getObjectSize() + valueField.getValue(s).getObjectSize(); }); System.out.printf("%d strings with total size %d\n", stats[0], stats[1]); } public static void main(String[] args) { // Use default SA tool launcher new InternedStrings().execute(args); } } 

运行该工具:
java -cp $JAVA_HOME/lib/sa-jdi.jar:. InternedStrings

警告:这是一个外部工具,用于在执行时暂停目标JVM进程。

这里还有一些可维护性代理示例。

UPDATE

如果您希望扫描所有字符串,不仅是字符串池中的字符串,您可以使用类似的方法; 用getObjectHeap().iterateObjectsOfKlass()替换getStringTable().stringsDo() getObjectHeap().iterateObjectsOfKlass() 。 例子 。

更新2

也可以使用JVMTI函数IterateThroughHeap在Java进程内迭代Java Heap。 这将比可维护性代理更少侵入。

 jint JNICALL stringCallback(jlong class_tag, jlong size, jlong* tag_ptr, const jchar* value, jint value_length, void* user_data) { wprintf(L"%.*s\n", value_length, value); return 0; } JNIEXPORT void JNICALL Java_HeapIterator_printStrings(JNIEnv* env, jclass cls) { jvmtiHeapCallbacks callbacks = {NULL, NULL, NULL, NULL, stringCallback}; (*jvmti)->IterateThroughHeap(jvmti, 0, NULL, &callbacks, NULL); } 

完整的例子就在这里 。