gpt4 book ai didi

java - 如何打印整个字符串池?

转载 作者:行者123 更新时间:2023-12-05 00:07:19 25 4
gpt4 key购买 nike

我想打印整个字符串池,其中包含在垃圾回收之前使用 intern() 添加的文字和 String 对象。

对于这样的操作,JDK 是否有隐含的方法?我们如何检查字符串池?

最佳答案

编辑:该评论表明,对于此“hack”的作用可能存在误解。它打印已通过(直接或间接)调用 intern() 进行实习的字符串,如问题中所述。它不会打印“整个字符串池”,因为字符串池仅驻留在 JVM 中,充满了在类加载和初始化期间出现的符号和字符串,并且无法从 Java 端访问。


NeplatnyUdaj 在评论中提到,可以定义一个新的 java.lang.String 类,并在启动时将其潜入 JVM。我很好奇,试了一下。我应该怎么说:它有效!

1. 创建一个包含包 java.lang

的新项目

2.将这样的类插入到这个包中

package java.lang;

import java.util.LinkedHashSet;
import java.util.Set;

public class StringPool {

private static Set<String> pool = null;
public static synchronized void store(String string)
{
try
{
if (pool == null)
{
pool = new LinkedHashSet<String>();
}
pool.add(string);
}
catch (Exception e)
{
// Ignore
}
}

public static synchronized Set<String> getPool()
{
return new LinkedHashSet<String>(pool);
}

}

3. 将原始的 java.lang.String 类复制并粘贴到此包中。令人惊讶的是,这没有很多问题。它会提示一个函数,即对

的调用
    h = sun.misc.Hashing.murmur3_32(HASHING_SEED, value, 0, value.length);

可以安全地替换为

    h = 0;

4. 更改新String 类的String#intern() 方法。最初,这是一个 native 方法。可以用类似的东西代替

public String intern()
{
StringPool.store(this);
return this;
}

5. 从该项目创建一个 .JAR 文件,并将其存储为例如 newString.jar

6. 使用生成/包含/使用一些字符串的测试类创建另一个项目。 (这应该很容易)并编译这个类,它可以命名为 NewStringTest

7. 使用修改后的字符串类启动测试程序:

java -Xbootclasspath:newString.jar;C:\jre\lib\rt.jar NewStringTest

然后可以使用 StringPool#getPool() 方法获取包含驻留字符串的池。



我刚刚使用以下类对此进行了测试,该类手动创建一些字符串和一些 Swing 组件(可以预期包含一些字符串):

import java.lang.reflect.InvocationTargetException;

import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.SwingUtilities;


public class NewStringTest
{
public static void main(String[] args)
{
generateSomeStrings();
System.out.println(StringPool.getPool());
}

private static void generateSomeStrings()
{
String s = "This is some test string";
for (int i=0; i<10; i++)
{
String t = s + i;
t.intern();
}
try
{
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run() {
JFrame frame = new JFrame();
JTable table = new JTable();
}
});
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}

输出是

[hashSeed, value, buf, J, D, Z, seed, segmentShift, segmentMask, segments, state, head, tail, waitStatus, next, Ljava/lang/String;, I, [C, [J, Ljava/util/Hashtable;, Ljava/security/PermissionCollection;, Ljava/util/Vector;, Ljava/lang/Class;, main, This is some test string0, This is some test string1, This is some test string2, This is some test string3, This is some test string4, This is some test string5, This is some test string6, This is some test string7, This is some test string8, This is some test string9, INSTANCE, es, , ES, sv, SE, values, Ljava/lang/Object;, [Ljava/awt/Component;, Ljava/awt/LayoutManager;, Ljava/awt/LightweightDispatcher;, Ljava/awt/Dimension;, createUI, invoke, VK_F10, VK_CONTEXT_MENU, VK_SPACE, VK_LEFT, VK_KP_LEFT, VK_RIGHT, VK_KP_RIGHT, VK_ESCAPE, VK_C, VK_V, VK_X, VK_COPY, VK_PASTE, VK_CUT, VK_INSERT, VK_DELETE, VK_DOWN, VK_KP_DOWN, VK_UP, VK_KP_UP, VK_HOME, VK_END, VK_PAGE_UP, VK_PAGE_DOWN, VK_TAB, VK_ENTER, VK_A, VK_SLASH, VK_BACK_SLASH, VK_F2, VK_F8]

关于java - 如何打印整个字符串池?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29884387/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com