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

标签 java string

我想打印整个字符串池,其中包含在垃圾回收之前使用 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/

相关文章:

java - 数字计数功能

java - 从 xml 延迟加载 View

android - 1 MB .txt 文件中有多少个字符?

c# - String.Format 在这种情况下如何工作?

java - StringBuilder 追加与 +

java - 如果 Android 服务在库项目中,则不会启动

java - 为什么我的文本文件总是空的?

java - 尝试从文本文件打印列表?

c - 将文件中的行保存到新字符串中。 C

python - 有没有办法增加字符串变量中的数值? [Python]