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

标签 java string jvm jvm-hotspot

是否有使用 java 或 native 代码的任何实用程序或脚本来查看 JDK 8 HotSpot JVM 中字符串池中存在的所有字符串的列表,而不会对 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 <PID>

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

还有一些可服务性代理示例here .

更新

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

更新 2

也可以使用 JVMTI 函数从 Java 进程中迭代 Java 堆 IterateThroughHeap .这将比可服务性代理更少干扰。

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);
}

完整的例子是here .

关于java - 用于访问 JDK 8 HotSpot JVM 中的字符串池内容的实用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35238902/

相关文章:

Python - 提取子串最优雅的方式,给定左右边界

java - Scala 的 Array[Int] 与 Java 中的 int[] 的内存比较?

java - 将结果写入 volatile 变量以防止测试中的死代码消除

Javadoc:package.html 或 package-info.java

java - 在JVM指令中,有些指令的前缀不同,但功能却非常相似。我们真的需要它们吗?如果是,为什么?

java - System.out 和 .err - 回到 future ?

python - 比较字符串中的各个字符并接受输入为真,即使拼写不准确

python - 消除 Pandas 索引字符串条目中的括号

java - 远程调试 Java - Solr

java - 如何在 netbeans 项目中导入库?