如何打印整个String池? [英] How to print the whole String pool?

查看:114
本文介绍了如何打印整个String池?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想打印包含文字的整个字符串池和字符串使用 intern()添加的对象垃圾收集。

I wanted to print the whole string pool which contains literals and String objects added using intern() just before garbage collection.

JDK是否存在隐含此类操作的方法?我们如何检查字符串池?

Is there a method implicit to JDK for such operation? How can we inspect the string pool?

推荐答案

编辑:评论表明可能存在误解关于这个黑客的作用。它打印已经(直接或间接)调用 intern()实习的字符串,如问题中所述。它不会打印整个字符串池,因为字符串池只驻留在JVM中,填充了在类加载和初始化期间出现的符号和字符串,并且无法从Java端访问。

The comment suggests that there may be a misunderstanding regarding what this "hack" does. It prints the strings that have been interned by (directly or indirectly) calling intern(), as described in the question. It will not print the "whole string pool", as the string pool only resides in the JVM, is filled with symbols and strings that appear during classloading and initialization, and not accessible from Java side.

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

NeplatnyUdaj mentioned in a comment that it might be possible to define a new java.lang.String class and sneak this into the JVM at startup. I was curious, and tried it out. And what should I say: It works!

1。创建一个包含 java.lang包的新项目

2. 将此类课程插入此套餐

2. Insert a class like this into this package

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 类粘贴到此包中。令人惊讶的是,这没有太多问题。它会抱怨一个函数,即调用

3. Copy & Paste the original java.lang.String class into this package. Surprisingly, this works without many problems. It will complain about a single function, namely a call to

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

可以安全地替换为

    h = 0;

4. 更改字符串#intern( ) String 类的方法。最初,这是一个原生方法。它可以替换为类似

4. Change the String#intern() method of the new String class. Originally, this is a native method. It can be replaced with something like

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

5. 从此创建.JAR文件项目,并存储,例如, newString.jar

5. Create a .JAR file from this project, and store it, for example, as newString.jar

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

6. Create another project with a test class that generates/contains/uses some strings. (that should be easy) and compile this class, which may be named NewStringTest

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

7. Launch the test program with the modified string class:

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

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

The StringPool#getPool() method can then be used to obtain the pool containing the interned strings.

我刚用下面的类测试了这个,它手动创建了一些字符串,以及一些Swing组件(可以预期包含一些字符串):

I just tested this with the following class, which manually creates some strings, and some Swing components (which can be expected to contain some strings):

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,
segment,state,head,tail ,waitStatus,next,Ljava / lang / String;,
I,[C,[J,Ljava / util / Hashtable;,Ljava / security / PermissionCollection;,
Ljava / util / Vector;,Ljava / lang / Class;,main,这是一些测试string0,
这是一些测试string1,这是一些测试string2,
这是一些测试string3,这是一些测试string4,
这是一些测试string5,这是一些测试string6,
这是一些测试string7,这是一些测试string8,
这是一些测试string9,INSTANCE,es,ES,sv,SE,
值,Ljava / lang / Object;,[Ljava / awt / Component;,
Ljava / awt / LayoutManager;,Ljava / awt / LightweightDispatcher;,
Ljava / awt / Dimension;,createUI ,调用,VK_F10,
VK_CONTEXT_MENU,VK_SPACE,VK_LEFT,VK_KP_LEFT,
VK_RIGHT,VK_KP_RIG HT,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]

[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]

这篇关于如何打印整个String池?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆