问题描述
是否有任何实用程序或脚本(使用java或本机代码)查看JDK 8 HotSpot JVM中字符串池中存在的所有字符串的列表,而不会对JVM产生很多性能影响?
Is there any utility or script, either using java or native code, to see list of all strings present in String Pool in JDK 8 HotSpot JVM, without having lot of performance impact on JVM?
或者,只要将新字符串添加到JVM中,我就可以将侦听器连接起来吗?
Alternatively can I have a listener hooked up whenever a new string is being added into JVM?
谢谢,
Harish
Thanks,Harish
推荐答案
您可以使用默认包含在JDK中的 HotSpot Serviceability Agent 轻松实现自己的实用程序。
You can easily make such yourself utility using HotSpot Serviceability Agent which is included in JDK by default.
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< PID>
警告:这是一个在执行时暂停目标JVM进程的外部工具。
Warning: this an external tool that pauses target JVM process for the time of execution.
更多可维护性代理示例。
更新
如果您愿意扫描所有字符串,不仅是字符串池中的字符串,您可以使用类似的方法;只需将 getStringTable()。stringsDo()
替换为 getObjectHeap()。iterateObjectsOfKlass()
。 。
If you wish to scan through all strings, not only those in String Pool, you may use a similar approach; just replace getStringTable().stringsDo()
with getObjectHeap().iterateObjectsOfKlass()
. Example.
UPDATE 2
也可以使用JVMTI函数从一个Java进程中迭代Java Heap 。这将比可维护性代理更少侵入。
It is also possible to iterate through Java Heap from within Java process using JVMTI function IterateThroughHeap. This is going to be less intrusive than Serviceability Agent.
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);
}
完整的例子是。
这篇关于用于访问JDK 8 HotSpot JVM中的字符串池内容的实用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!