使用数组时Java内存泄漏

时间:2015-02-24 15:14:15

标签: java memory-leaks

想证实我的假设。我正在查看另一个使用数组(不是linkedhashset / sorted collection等)的开发人员的代码,并尝试根据插入对其进行排序,同时保持其固定大小。保持固定大小的逻辑是从数组中删除最旧的项目。但是,当从数组中删除最旧的项时,对象引用没有被删除,即只有数组索引被写入另一个对象。我认为这可能会让旧的(没有被淘汰的)对象在内存中停留的时间比需要的时间长(如果不是完全没有内存泄漏),除非我错过任何与范围有关的内容。任何想法(我试图通过快速测试和visualvm确认)。提前致谢。

public class MemTest {

     private TestBuffer testQuotes = new TestBuffer(10);  //static inner class 


     public static void main(String[] args) {

         System.out.println("Starting!");
         MemTest memTest = new MemTest();
        for (int j = 0; j < 10; j++) { 
             for (int i = 0; i < 2000000000; i++) {
                 memTest.testQuotes.push(1, 12.3);
             }

             try {
                 Thread.sleep(2000);
             }
             catch (InterruptedException e) {
                 System.out.println("exception:" + e);
             }
        }

     }


     private static class QuoteBuffer {
            private Object[] keyArr;  
            private Price[] testArr;  

            public TestBuffer(int size) {
                keyArr = new Object[size];
                testArr = new Price[size];
            }

            public Price get(Object key) {
                if (key != null) {
                    for (int i=0; i<keyArr.length; i++) {
                        if ( key.equals(keyArr[i]) )
                            return quoteArr[i];
                    }
                }
                return null;
            }

            private void _slideTestQuotes() {
                Object prevKey = null;
                Price prevQuote = null;
                Object tempKey;
                Price tempQuote;
                for (int i=0; i<keyArr.length; i++) {
                    // slide key to the next index
                    tempKey = keyArr[i];
                    keyArr[i] = prevKey;
                    prevKey = tempKey;
                   // tempKey = null;  //I am guessing uncommenting this should make a difference

                    // slide quote to the next index
                    tempQuote = quoteArr[i];
                    quoteArr[i] = prevQuote;
                    prevQuote = tempQuote;
                 //   tempQuote=  null;   //I am guessing uncommenting this should make a difference
                }
            }

            public void push(Object key, Double quote) {
                _slideTestQuotes();
                keyArr[0] = key;
                quoteArr[0] = new Price(quote); //quote;
            }
     }






       public class Price {

            Double price;
            Double a1;
            Double a2;
            Double a3;
            Double a4;
            Double a5;
            Double a6;

            Price(Double price) {
                this.price = price;
                this.a1 = price;
                this.a2 = price;;
                this.a3 = price;
                this.a4 = price;
                this.a5 = price;
                this.a6 = price;
            }

        }

3 个答案:

答案 0 :(得分:1)

您无需实际设置null引用以使其符合垃圾回收的条件。请考虑以下代码段:

Double d = new Double(1.1);  // (1)
d = new Double(2.2);         // (2)

在第2行,对象句柄“d”被赋予一个新值。这意味着现在不再以任何方式访问具有值1.1的原始Double,并且有资格进行垃圾回收。没有必要首先专门写“d = null”。

答案 1 :(得分:1)

Java垃圾收集器将收集所有不再可访问的对象。你不必废除引用;

ref = null;
ref = newRef;

ref = newRef;

具有完全相同的效果,如果没有对ref所指向的对象的其他引用,则会导致垃圾收集器收集该对象。

如果要丢弃对对象的引用但不为引用分配新值,则只需要使引用为空。在这种情况下,忘记将引用置空可能确实会导致内存泄漏,因为仍然存在对您可能不再需要的对象的引用。

答案 2 :(得分:0)

但是,从数组中删除最旧的项目时,对象引用没有被删除,即只有数组索引被写入另一个对象。 - 这是关键点。无论您是将引用设置为null还是将其设置为其他对象都无关紧要,如果没有对它的引用,则“原始”对象将无法访问。

示例:

arr[0] = new myObject();
MyObject my = arr[0];
arr[0]=null; // or arr[0] = new myObject(); makes no difference. Since The original MyObject is still reachable, it will not be considered for GC.

my=null; // or my=new MyObject() // now the original MyObject instance will be unreachable and hence ready for GC.