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,分析堆转储后,我发现分配了大约30MB的字符串(单个字符串为30MB)。 有没有办法在调试应用程序时设置断点,以便找到分配这些巨大字符串的代码? 由于在应用程序运行期间分配了数千个字符串,所以不可能只在每个字符串分配上设置断点。 我认为条件断点也会太慢。 如果可能的话,我想检查这些字符串内容,以了解这些分配的来源。 例如,它们可能是web服务调用的结果,web服务调用通常使用少量数据进行调用,但在极少数情况下使用大量输入进行调用(我希望找到这些情况) 将java.lang.String的源代码从

分析堆转储后,我发现分配了大约30MB的字符串(单个字符串为30MB)。
有没有办法在调试应用程序时设置断点,以便找到分配这些巨大字符串的代码? 由于在应用程序运行期间分配了数千个字符串,所以不可能只在每个字符串分配上设置断点。 我认为条件断点也会太慢。
如果可能的话,我想检查这些字符串内容,以了解这些分配的来源。
例如,它们可能是web服务调用的结果,web服务调用通常使用少量数据进行调用,但在极少数情况下使用大量输入进行调用(我希望找到这些情况)

  • java.lang.String
    的源代码从JDK源代码复制到 计划

  • String.java中创建一个方法,如下所示(count是
    java.lang.String
    的现有实例变量)

    private void checkSize(){
    如果(计数>1000000)//1MB
    系统输出打印项次(计数);
    }

  • 编辑
    java.lang.String
    以在每个构造函数的末尾调用此方法
    checkSize()

  • 在System.out.println(计数)行添加断点

  • 将新的
    java.lang.String
    添加到bootstrap类路径

  • 只有在创建大于1MB的字符串时,此断点才会中断


  • 我会尝试使用条件断点,即使这意味着让应用程序运行一两天。至少在它运行时,您可以继续进行其他操作。不管怎样,任何其他解决方案都可能需要一两天才能实现


    否则,您可以使用AspectJ将切入点添加到字符串构造函数中,并使用切入点记录消息、引发异常等。这与条件断点基本相同,但应该运行得更快。

    尽管您明确要求调试会话,我假设这主要是为了解决实际问题:分配了大字符串,而您不知道这在哪里发生

    分配可以通过以下方式进行跟踪。您可以启动jVisualVM和您的程序,并将jVisualVM连接到您的程序

    如果这不符合你的需要,我可以删除这个答案。否则,您可以这样做:

    在“探查器”选项卡中,您可以选中右上角的“设置”复选框,然后选择“内存设置”选项卡。您可以在此处设置“记录分配堆栈跟踪”复选框:

    然后,按下顶部的“内存”按钮后,探查器将收集有关字符串分配的信息。退出应用程序后(或拍摄快照后),您可以检查记录的堆栈跟踪,以找到分配大字符串的方法—在本例中为
    method4


    这可能很接近:继续监视字符串对象的堆,一旦看到spike,立即执行线程转储我猜理论上JVM可以在调试模式下运行,记录创建每个对象的
    新的
    的位置。。。但我不知道是否有这样的JVM。@Raedwald字符串是不可变的;只要有
    if(length()>300000)/*断点*/“大字符串”时,我遇到了大量内存消耗的问题。在Java6和更早版本中,保存在集合中的子字符串(几个字符)
    可能会占用大量空间。我喜欢在字符串构造函数中使用条件断点的方法但是OP建议这是不可行的,因为断点的开销。这会显示堆栈跟踪的总内存还是分配的巨大字符串的特定实例?(我正在寻找一个分配了30MB数据的单字符串实例)不完全清楚“特定实例”是什么意思。您将看不到字符串的内容。但是(如第二个屏幕截图所示),您将收到分配堆栈跟踪的可浏览视图。默认情况下,它们按字节数排序。因此,通过展开最大
    char[]
    chunk的前3级,您可能会找到“大型”分配的位置。(再次强调:这只是一种可能带来所需见解的方法,但我不能保证它适用于您的应用案例)