当前位置: 首页 > 面试题库 >

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

苍烨然
2023-03-14
问题内容

是否有任何实用程序或脚本(使用Java或本机代码)来查看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进程。

一些更多 的可维护性代理 的例子在这里。

更新

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

更新2

也可以使用JVMTI函数IterateThroughHeap从Java进程中遍历Java
Heap 。这将不会比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);
}

完整的示例在这里。



 类似资料:
  • 本文向大家介绍Java程序访问字符串字符,包括了Java程序访问字符串字符的使用技巧和注意事项,需要的朋友参考一下 要在Java中访问字符串的字符,请使用方法。该位置将作为参数添加。 假设我们有以下字符串- 让我们使用method在第4个位置找到字符。 以下是最后一个示例。 示例 输出结果

  • 每个人都知道这一点。Net framework字符串对象直接存储在堆内存中 我只是想弄清楚里面是否有保留的记忆。Net字符串框架。在java中,有一个为字符串保留的内存,称为SCMP(字符串常量内存池),在这里字符串被初始化和垃圾收集,就像堆内存中的其他对象一样。

  • 问题内容: 我要执行以下操作。 我想要所有超链接的行为进行ajax调用并检索html。 不幸的是,您不能简单地用ajax响应中收到的html替换当前的html。 如何仅获取ajax响应的标记中的内容,以便 仅 替换现有html中正文的内容。 编辑:开始标记并不总是这样,有时可能会有一个类,例如 问题答案: 如果我对您的理解正确,请使用正则表达式在body标签之间获取内容。 编辑 根据您在下面的评论

  • 当使用文字创建字符串时,它会存储在池中。但当使用new运算符创建字符串对象时,它会将对象存储在堆中。 但是,堆中的对象只是一个指向存储在池中的文本的指针,还是一个存储在堆中的简单字符串对象,符合GC的条件?

  • 我一直在尝试从一个有一万亿个字符的字符串中访问一个字符。我使用BigInteger从字符串中获取索引号,并使用charAt方法从字符串中访问字符。 我试图做的是计算给定字符串中特定字符的出现次数。 例如,字符串:

  • 问题内容: 考虑以下代码: 使用new关键字时,Java会 再次创建吗?这将存储在常规堆还是池中?多少人在将s结尾池? 问题答案: 如果使用关键字,将创建一个新对象。请注意,对象始终在堆上-字符串池不是与堆分开的独立内存区域。 字符串池就像一个缓存。如果你这样做: 那么Java编译器是聪明足以让只有一个对象,并且将两者指的是同一个String对象。如果你这样做: 那么池中将有一个对象,该对象代表文