Java子字符串内存泄漏 [英] Java Substring memory leak

查看:184
本文介绍了Java子字符串内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于有关获取字符串的子字符串的讨论,请参见:http://www.microsoft.com/technet/prodtechnol/windowsserver2003/default.aspx ??http://stackoverflow.com/questions/6056389/java-string-split-memory-leak\"> Java String.split内存泄漏?,我一直在分析两个示例子字符串的用法示例。



据说,如果调用方在字段中存储字段的子字符串,则对象不会被垃圾回收目的。
当我运行我得到的代码和OutofMemory异常,并通过VisualVM监视它时,查看char []分配的大小的增加。

  public class TestGC {
private String largeString = new String(new byte [100000]);
String getString(){
return this.largeString.substring(0,2);
//返回新的字符串(this.largeString.substring(0,2));


public static void main(String [] args){
java.util.ArrayList< String> list = new java.util.ArrayList< String>();
for(int i = 0; i <100000; i ++){
TestGC gc = new TestGC();
list.add(gc.getString());
}
}
}

用下面的代码,I没有得到一个错误,并在通过VisualVM分析内存使用情况后,我意识到分配的char []大小越来越大,然后在某个时候以某种程度降低,然后再次增加并在某个时间点下降(GC工作)。它继续永远。

  public class TestGC {
private String largeString = new String(new byte [100000]) ;

String getString(){
// return this.largeString.substring(0,2);
返回新的字符串(this.largeString.substring(0,2));


public static void main(String [] args){
java.util.ArrayList< String> list = new java.util.ArrayList< String>();
for(int i = 0; i <100000; i ++){
TestGC gc = new TestGC();
list.add(gc.getString());
}
}
}

我真的很想了解GC收集然后从第二个例子中的堆内存中删除?
为什么GC不能在第一个例子中收集同一个对象?

在第一个例子中,

largeString.substring(0,2)); 发送一个引用,并在第二个例子 new String(this.largeString.substring(0,2)); 创建新的对象。这两种情况都不应该成为GC行为的问题吗?

解决方案

在第一个例子中, TestGC对象,你也在创建一个从100000字节数组初始化的新字符串。当您调用String.substring时,您将返回相同的大长字符串,但偏移量设置为0并且计数设置为2.因此,所有数据仍在内存中,但是当您使用字符串时,您只会看到指定的2个字符在第二个例子中,你每次都在循环中创建新的String,但是通过调用新的String(String.substring),你将丢弃剩下的字符串,只保留内存中的2个字符,所以其余的可以被垃圾收集。



正如评论中的链接所言,这种行为在1.7 .0_06,以便由String.substring返回的字符串将不再共享相同的char []。


Based on the discussion about getting substring of String Java String.split memory leak? , I have been analyzing two sample substring examples of usage.

It is said that objects don't get garbage collected if the caller stores a substring of a field in the object. When I run the code I get and OutofMemory Exception, and see the incresing of char[] allocated size while monitoring it via VisualVM

public class TestGC {
    private String largeString = new String(new byte[100000]);    
    String getString() {
        return this.largeString.substring(0,2);     
        //return new String(this.largeString.substring(0,2));
    }

    public static void main(String[] args) {
        java.util.ArrayList<String> list = new java.util.ArrayList<String>();
        for (int i = 0; i < 100000; i++) {
            TestGC gc = new TestGC();            
            list.add(gc.getString());            
        }
    }
}

with the following code, I did not get an error and after analyzing memory usage via VisualVM I realized that allocated char[] size getting increasing then somehow decreased at some point , then increasing again and decreased at some point (GC works its job). And It continues forever.

public class TestGC {
    private String largeString = new String(new byte[100000]);

    String getString() {
        //return this.largeString.substring(0,2);       
        return new String(this.largeString.substring(0,2));
    }

    public static void main(String[] args) {
        java.util.ArrayList<String> list = new java.util.ArrayList<String>();
        for (int i = 0; i < 100000; i++) {
            TestGC gc = new TestGC();            
            list.add(gc.getString());            
        }
    }
}

I really want to understand what does GC collect then remove from heap memory in second example? Why GC cannot collect same object in the first example?

at the first example largeString.substring(0,2)); send a reference and at the second example new String(this.largeString.substring(0,2)); creates new objects. Both cases should not problem for behaviour of GC?

解决方案

In the first example, every time around the loop when you create a new TestGC object you are also creating a new String initialised from the 100000 byte array. When you call String.substring you are returning the same big long string but with the offset set to 0 and count set to 2. So all the data is still in memory but when you use the String you will only see the 2 characters specified in the substring call.

In the second example you are again creating the new String every time around the loop, but by calling new String(String.substring) you are discarding the rest of the String and only keeping the 2 characters in memory, so the rest can be garbage collected.

As the links in the comments say, this behaviour has changed in 1.7.0_06 so that the String returned by String.substring will no longer share the same char[].

这篇关于Java子字符串内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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