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/22094111/

相关文章:

Java检查字符串中的所有字符是否存在于给定的字符串数组中

java - 如何使用 spring boot 2 和千分尺测量服务方法

c++ - 来自资源数据的 C/C++ 消息框

java - 使用正则表达式将字符串拆分为 3 部分

java - 是否可以在 java 中创建一个包含多个数据类型的数组?如果可能的话,怎么做?

java - com.mysql.jdbc.exceptions.jdbc4.CommunicationsException : Communications link failure

VB.net 在非字母数字、非连字符上分割字符串

arrays - 将长字符串转换为数组中均匀分割的索引

python - 打印格式化的元组值

java - 将 char 与数字相乘并与 char 相加时出错(Big Java Ex 6.2)