Java без запроса выделения памяти - PullRequest
1 голос
/ 19 января 2010

Следующий фрагмент кода, наблюдаемый в JConsole, показывает постоянное увеличение размера кучи.Куча достигает максимум 25 МБ, а затем запускается сборщик мусора и уменьшает размер кучи почти до 3 МБ.Это ожидаемое поведение?Я очень удивлен!

public class Dummy {
    public static void main(String[] args) {
        System.out.println("start");
        while(true){
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Я использую Snow Leopard.

Ответы [ 5 ]

8 голосов
/ 19 января 2010

Связь с jconsole приводит к выделению объектов. Я считаю, что то, что вы видите здесь, является артефактом вашего метода измерения. HotSpot может также немного выделяться при компиляции кода. Если вы беспокоитесь, используйте профилировщик, чтобы увидеть, что выделяется (опять же, следите за распределением через интерфейс профилировщика).

Нормальное поведение ГХ - избегать ненужного запуска. Вы увидите повсюду веб-графики использования памяти. Здесь есть некоторый компромисс между дружелюбностью кеша и свопинга и отказом от работы. Также сервер HotSpot более агрессивен в использовании памяти, чем клиент HotSpot.

4 голосов
/ 19 января 2010

Да, это должно быть ожидаемое поведение. Хотя вы ничего не делаете для распределения объектов, реализация сна может быть, и даже если это не так, в JVM работают другие потоки, которые вполне могут быть.

3 голосов
/ 19 января 2010

Да, это нормально. Вы явно не создаете никаких объектов, но вы вызываете методы, которые, вероятно, создают некоторые временные объекты как часть их реализации. Эти временные объекты накапливаются до тех пор, пока не наступит время для запуска ГХ для их очистки.

2 голосов
/ 19 января 2010

Файлы классов выглядят так, код переходит с 8 на 14, а java.lang.Thread.sleep () является нативным. Поэтому нет оснований для создания МБ объектов

 public static void main(java.lang.String[] args);
     0  getstatic java.lang.System.out : java.io.PrintStream [16]
     3  ldc <String "start"> [22]
     5  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
     8  ldc2_w <Long 5000> [30]
    11  invokestatic java.lang.Thread.sleep(long) : void [32]
    14  goto 8
    17  astore_1 [e]
    18  aload_1 [e]
    19  invokevirtual java.lang.InterruptedException.printStackTrace() : void [38]
    22  goto 8

Боюсь, то, что вы видите, получено от самого JProfiler (я не знаю, как вы подключили его к своему тестовому приложению Dummy) или других вещей, запущенных в этом виртуальном компьютере. Чтобы узнать, какие объекты были созданы, вы должны сделать дамп кучи, если JProfiler не показывает эту информацию.

1 голос
/ 19 января 2010

Ясно, что есть две теории относительно причины, и их невозможно различить на основе эмпирических рассуждений. Могу ли я предложить простой эксперимент.

  1. Переведите программу в спящий режим на 1 миллисекунду вместо 5000. (Фактическое число не имеет значения ... это сделано для того, чтобы гипотетическое распределение памяти происходило как можно быстрее. Вы также можете попробовать 0 миллисекунд, но поведение сна вполне может быть другим ...)

  2. Запустить программу, используя текущий подход; например с jconsole.

  3. Запустите программу без jconsole и т. Д., Но с опцией «-verbose: gc», чтобы вы могли видеть, когда запускается GC.

Я подозреваю, что вам не хватит терпения ждать, пока GC запустится в последнем случае ... даже вызывать sleep как можно быстрее.

...