2016-02-26 4 views
2

Мне интересно, почему полная свободная память не меняется после создания большой таблицы. Но когда я использую сборщик мусора, увеличивается полная свободная память.Общая свободная память java

import java.util.Random; 

public class Main{ 
public static void main(String[] args) throws Exception 
{ 
    C c = new C(); 

    System.out.println("Free memory: "+Runtime.getRuntime().freeMemory()); 
    c.CreateTable(); 
    System.out.println("Free memory: "+Runtime.getRuntime().freeMemory()); 
    System.gc(); 
    System.out.println("Free memory: "+Runtime.getRuntime().freeMemory()); 
} 
} 


class C{ 
public void createTable() 
{ 
    int[] ar = new int[70000]; 
    Random r = new Random(); 
    for(int i = 0; i<ar.length;i++) 
    { 
     ar[i]=r.nextInt(99); 
    } 
} 
} 
+3

Вот некоторые интересные статьи о [Garbage Collector] (http://www.cubrid.org/blog/dev-platform/understanding-java- вывоз мусора/). Может дать вам немного понять, как работает GC. – AndrewMcCoist

+3

70k 'int' insnt't точно, что я бы назвал «большой таблицей» с точки зрения использования памяти. – ChiefTwoPencils

ответ

2

Это потому, что JVM создал ИНТ [] аг в TLAB (токарно-местное выделение буфер). Позвольте мне объяснить это следующим примером:

1) Предположим, что общая память в системе составляла 100 единиц.

2) В текущем потоке уже создан TLAB, хотя даже одна строка кода запускается.

3) память TLAB в (скажем, 10 единиц) уже вычитается из общей памяти т.е. (Runtime.freeMemory показывает 90 единиц)

4) INT [] ар создается внутри TLAB, как TLAB имеет свободное место.

5) После создания int [] ar running Runtime.freeMemory показало 90 единиц (поскольку они созданы внутри TLAB).

6) Теперь делать GC вы можете видеть 100 единиц снова

+0

Вы имеете в виду, когда gc вызывается в конце, TLAB удаляется? –

1

Я не могу воспроизвести поведение по вашему мнению, происходит:

$ java Main 
Free memory: 126206592 
Free memory: 125535432 
Free memory: 125943720 

Как вы можете видеть, свободная память уменьшается после вызова createTable(), а затем снова увеличивается после вызова System.gc().

Теперь вы не получите все выделенной памяти обратно , но есть много возможных объяснений для этого, включая:

  • дополнительных классов могут быть загружены в результате увеличения использования кучи
  • Некоторый код, возможно, был составлен JIT, что привело к увеличению использования кучи
  • Объекты, возможно, были выделены в области кучи, которая собирается нечасто. Например, большой массив может быть выделен непосредственно в штатное пространство ...

Резюме: Сбор выделения памяти/мусор Java является сложным ... и начинающими лучше не пытаюсь выяснить, как это работает с использованием простых (наивных) тестов «черного ящика». Вы узнаете больше, найдя/прочитав статьи.


1 - Чтобы быть точными, GC может быть освоения всей памяти о том, что вызов явно выделенный ... но есть и другие вещи происходят, что означает, что это не отражено в " свободного пространства ".

2 - Если ваша голова взрывается, он оставит неприятные пятна на ковре ..... :-)