Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何打印整个字符串池?_Java_String - Fatal编程技术网

Java 如何打印整个字符串池?

Java 如何打印整个字符串池?,java,string,Java,String,我想打印整个字符串池,其中包含在垃圾收集之前使用intern()添加的文本和string对象 对于这种操作,JDK是否有一个隐式方法?如何检查字符串池?,因此GC在清理任何对象之前调用finalize方法 因此字符串中的finalize方法也被调用。但遗憾的是,String是最后一个类,您不能重写它。() 但是如果你真的想让这个东西工作起来,那么你需要创建你自己的字符串对象,命名为其他东西,但是内部行为将保留所有的字符串函数 为了保证GC的安全,请尝试以下内容:编辑:评论表明,对于这种“黑客”的

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

对于这种操作,JDK是否有一个隐式方法?如何检查字符串池?

,因此GC在清理任何对象之前调用finalize方法

因此字符串中的finalize方法也被调用。但遗憾的是,String是最后一个类,您不能重写它。()

但是如果你真的想让这个东西工作起来,那么你需要创建你自己的字符串对象,命名为其他东西,但是内部行为将保留所有的字符串函数

为了保证GC的安全,请尝试以下内容:

编辑:评论表明,对于这种“黑客”的作用可能存在误解。它打印通过(直接或间接)调用
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);
    }

}
可以安全地用

    h = 0;
4.更改新
String
类的
String#intern()
方法。最初,这是一种
本机
方法。它可以被以下内容替换

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;
导入javax.swing.JFrame;
导入javax.swing.JTable;
导入javax.swing.SwingUtilities;
公共类NewStringTest
{
公共静态void main(字符串[]args)
{
生成中间字符串();
System.out.println(StringPool.getPool());
}
私有静态void generateSomeString()
{
String s=“这是一些测试字符串”;

对于(int i=0;iOverride
String
并在实习前存储它们;)@NeplatnyUdaj:
String
final
。但是我们不能重写String?我以为interned String永远不会被GCed…那么创建一个新的String实现并通过
Xbootclasspath
提供它怎么样?我不知道是否可以加载不同的String…你的
intern()
replacement被破坏,因为它无条件返回
this
,不考虑映射中的现有实例。但更糟糕的是,此黑客显然只捕获
intern()
的显式调用-请注意,您的输出不包含文本
“这是一些测试字符串”
,但只有您手动实习的编号版本。当我使用
-XX:+PrintStringTableStatistics
在未经修改的环境中运行您的程序时,JVM说大约有4000个实习字符串…@Holger虽然标题更一般,但问题涉及
实习()
method。实习也发生在类加载和虚拟机启动级别,绕过
intern()
调用,这一事实使事情变得困难(在将此应用于时可以看出,这可能也导致您出现这种情况)。不过,我看不到访问字符串池的任何其他选项(手工定制的JVM黑客除外)。但请随意提供其他建议作为答案。这不仅仅是标题;问题的主体还说“整个字符串池包含使用
intern()
”添加的文本和字符串对象@Holger因此,答案是:“这是不可能的”。我想是的。JVMTI允许获取所有现有的
String
实例,但似乎无法检查某个特定实例是否已合并…
finalize()
方法与此无关,创建一个新的
String
类不会帮助您查看合并的文本。
java -Xbootclasspath:newString.jar;C:\jre\lib\rt.jar NewStringTest
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();
        }
    }
}