简体   繁体   English

为什么Java不释放内存

[英]why Java not release memory

I'm a junior in Java, facing a memory leaking problem. 我是Java的大三学生,面临内存泄漏问题。 I always thought java won't have a memory problem but I got one. 我一直以为java不会有内存问题,但我有一个。 Below is my testing code. 以下是我的测试代码。

I create a large ArrayList in getList() method, and keep calling this method in the main thread. 我在getList()方法中创建了一个大型ArrayList,并继续在主线程中调用此方法。 I thought the list: 我认为清单:

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

in loop is a local var, and should be released in the next round because a new object would be created. in loop是一个局部变量,应在下一轮释放,因为将创建一个新对象。 But jvm didn't do that. 但是jvm并没有这样做。 This thread keep eating all the memory. 该线程继续占用所有内存。 Would anyone tell me the reason? 谁能告诉我原因? Thanks! 谢谢!

Testing code: 测试代码:

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;
}
}

Modified Problem: in the modified problem, the thread also keep eating memory. 修改问题:在修改过的问题中,线程也会继续吃掉内存。 But I thought it should release the memory during each round, but it didn't. 但我认为它应该在每一轮中释放记忆,但事实并非如此。 So it occupied more and more memory. 因此它占用了越来越多的内存。

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;
}

I'm guessing that it's because of the iterated string concatenation: 我猜这是因为迭代的字符串连接:

a += "aaaa";

Not because the List isn't being released. 不是因为List没有被释放。

At the end of it all, a has 40,000,000 characters in it. 在这一切结束时, a中有4000万个字符。

One call to getList will allocate space for 2000000000 characters (this includes the intermediate results for the string concatenations). 一次对getList调用将为2000000000个字符分配空间(其中包括字符串连接的中间结果)。 Thats 4GB, not counting overhead. 这是4GB,不算开销。 All this is done in a loop 10000 times giving total allocations of 40TB. 所有这些都是在10000次循环中完成的,总共分配了40TB。

GC is doing a good job if this program executes for a while. 如果该程序执行一段时间,GC正在做得很好。

Common misconception is that the GC releases memory as soon at it not needed. 常见的误解是GC会在不需要时立即释放内存。 The cost of running the GC is high, and so it is delayed as long as possible (Unless you use Azul's Zing in which case it is always concurrent) 运行GC的成本很高,因此会尽可能延迟(除非您使用Azul's Zing,在这种情况下,它始终是并发的)

This means it is completely normal to see memory consumption increase as you create more and more garbage and the ONLY way to know if you have a memory leak is to look at consumption AFTER a Full GC. 这意味着,当您创建越来越多的垃圾时,看到内存消耗增加是完全正常的,并且知道您是否有内存泄漏的唯一方法是查看完整GC之后的消耗。 Until a Full GC is run you can be sure that some objects which might have been cleaned up have not been. 在运行Full GC之前,您可以确定某些可能已清理过的对象尚未清除。

But I thought it should release the memory during each round, but it didn't. 但我认为它应该在每一轮中释放记忆,但事实并非如此。

There is no way for the GC to know this is a good time to run. GC无法知道这是运行的好时机。 If you want to confirm this would be a good time, you can do a 如果您想确定这是个好时机,则可以

System.gc();

between runs. 运行之间。 The memory usage after call this should be pretty stable. 调用此后的内存使用情况应该非常稳定。 The reason this call is not used more often is that usually it makes things worse, unless you know for example, that at that point you have dumped almost all the memory the application has used. 之所以不经常使用这个调用的原因是通常它会使事情变得更糟,除非你知道,例如,那时你已经倾倒了应用程序使用的几乎所有内存。

facing a memory leaking problem. 面临内存泄漏问题。 I always thought java won't have a memory problem but I got one. 我一直以为java不会有内存问题,但我有一个。

You can have a memory leak in a Java program, but I don't see any evidence you have one. 您可以在Java程序中发生内存泄漏,但我没有看到任何证据。

If you want to see a memory leak save all the ArrayList in an ArrayList in main. 如果要查看内存泄漏,请保存main中ArrayList中的所有ArrayList。 This should lead to an OutOfMemoryError and you have a leak. 这应该导致OutOfMemoryError并且您有泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM