2

我是Java的大三学生,面临内存泄漏问题。我一直认为java不会有内存问题,但我有一个。下面是我的测试代码。

我在 getList() 方法中创建了一个大型 ArrayList,并在主线程中继续调用此方法。我想到了清单:

ArrayList<String> list = t.getList();

in loop 是一个本地变量,应该在下一轮释放,因为会创建一个新对象。但是jvm没有这样做。这个线程一直在吃掉所有的内存。有人能告诉我原因吗?谢谢!

测试代码:

package test;

import java.util.ArrayList;

public class test {


public static void main(String[] args){

    test t = new test();
    for(int k = 0; k < 10000; k ++){
        ArrayList<String> list = t.getList();

        System.out.println(k);
    }

}

public ArrayList<String> getList(){
    ArrayList<String> list = new ArrayList<String>();

    for(int i = 0; i < 100000; i ++){
        String a = "";
        for(int j = 0; j < 100; j++){
            a += "aaaa";
        }
        list.add(a);
    }

    return list;
}
}

修改题:在修改题中,线程也不停的吃内存。但我认为它应该在每一轮中释放内存,但事实并非如此。所以它占用了越来越多的内存。

public static void main(String[] args){

    test t = new test();
    for(int k = 0; k < 10000; k ++){
        String str1 = "string1";
        String str2 = "string2";
        double value = t.calculate(str1, str2);

        System.out.println(k + " " + value);
    }

}

public double calculate(String str1, String str2){
    double value = 0.0;

    ArrayList<String> list1 = getList(str1);
    ArrayList<String> list2 = getList(str2);

    value = cal(list1, list2); //will get the value based on lists

    return value;

}


public ArrayList<String> getList(String str1){
    ArrayList<String> list = new ArrayList<String>();

    //will generate  a long list

    return list;
}
4

3 回答 3

3

我猜这是因为迭代的字符串连接:

a += "aaaa";

不是因为List没有发布。

最后,a有 40,000,000 个字符。

于 2013-09-22T07:24:38.773 回答
3

一次调用getList将为 2000000000 个字符分配空间(这包括字符串连接的中间结果)。那是 4GB,不算开销。所有这些都在循环 10000 次中完成,总分配量为 40TB。

如果这个程序执行一段时间,GC 会做得很好。

于 2013-09-22T07:39:15.197 回答
1

常见的误解是 GC 会在不需要时立即释放内存。运行 GC 的成本很高,因此尽可能延迟(除非您使用 Azul 的 Zing 在这种情况下它始终是并发的)

这意味着随着您创建越来越多的垃圾,看到内存消耗增加是完全正常的,并且知道您是否有内存泄漏的唯一方法是查看 Full GC 之后的消耗。在运行 Full GC 之前,您可以确定某些可能已被清理的对象尚未被清理。

但我认为它应该在每一轮中释放内存,但事实并非如此。

GC 无法知道这是运行的好时机。如果你想确认这是个好时机,你可以做一个

System.gc();

运行之间。调用 this 后的内存使用应该相当稳定。不经常使用此调用的原因是它通常会使事情变得更糟,除非您知道例如,此时您已经转储了应用程序使用的几乎所有内存。

面临内存泄漏问题。我一直认为java不会有内存问题,但我有一个。

您可以在 Java 程序中发生内存泄漏,但我没有看到任何证据表明您有这种情况。

如果您想查看内存泄漏,请将所有 ArrayList 保存在 main 的 ArrayList 中。这应该会导致 OutOfMemoryError 并且您有泄漏。

于 2013-09-22T10:25:54.607 回答