Использование памяти приложения Java - PullRequest
7 голосов
/ 30 июня 2010

Я пишу небольшое Java-приложение (мое первое!), Которое на данный момент выполняет лишь несколько вещей. В настоящее время он запускает класс Main, который запускает класс gui (класс, который я написал, расширяющий JFrame, который содержит только JTextArea), класс, который загружает локальный файл через BufferedInputStream, который составляет приблизительно 40 КБ, и класс, который загружает запись из Файл свойств Java.

Все работает чудесно, однако я смотрел диспетчер задач Windows и заметил кое-что, что показалось мне странным. Когда я запускаю приложение, использование оперативной памяти возрастает примерно до 40 МБ, пока оно загружает локальный файл и извлекает из него несколько значений для отображения в JTextArea, что мне кажется нормальным из-за JVM, базовых классов Java и т. Д. Тем не менее, когда приложение завершило загрузку файла, оно просто бездействует, так как в настоящее время у меня больше ничего нет. Пока он бездействует, пока окно активно, объем используемой памяти приложения начинает расти на 10-20 КБ каждую секунду. Это кажется мне странным. Если я нажму на другую программу, чтобы сделать ее неактивным, память все равно будет увеличиваться, но гораздо медленнее (примерно 10 КБ каждые 3-5 секунд).

Я не проверял, насколько далеко он пойдет, но это кажется мне очень странным поведением. Это нормальное поведение Java? Я предполагаю, что возможно, что мой код может быть утечка памяти, но я не уверен, как. Я действительно закрыл BufferedInputStream, который я использую, и я не вижу, что еще может вызвать это.

Извините, если мое объяснение не имеет смысла, но я был бы признателен за любые идеи и / или указатели, которые кто-либо может иметь.

UPDATE:

По предложению я в основном разложил свое приложение до класса Main, который просто вызывает класс gui. Класс gui только расширяет JFrame и устанавливает размер окна, операцию закрытия и видимые свойства. С этими изменениями память все еще растет на 10-20 КБ, но более медленными темпами. Это, в сочетании с другими советами, которые я получил, заставляет меня поверить, что это всего лишь Java. Я буду продолжать играть с ним и сообщу всем, если я найду что-нибудь еще интересное.

Ответы [ 5 ]

9 голосов
/ 30 июня 2010

Попробуйте отслеживать использование кучи с помощью jconsole вместо диспетчера задач Windows:

  • Запустите ваше приложение с опцией -Dcom.sun.management.jmxremote, например,

java -Dcom.sun.management.jmxremote -jar myapp.jar

  • Запустите jconsole из командной строки и подключитесь к локальному pid процесса Java, который вы запустили на последнем шаге.
  • Перейдите в память и просмотрите память кучи (дисплей по умолчанию)

Если вы посмотрите некоторое время, вы, вероятно, получите «пилообразный» паттерн, поскольку память со временем поднимается, но затем имеет резкие падения при работе сборщика мусора. Вы можете попытаться «предложить» сборку мусора, щелкнув так помеченную кнопку.

Когда вы это делаете, использование памяти снижается до того же минимального уровня, или общий минимум увеличивается в течение нескольких минут? Если минимальное использование увеличивается, то у вас утечка памяти. Если он всегда возвращается к одному и тому же минимальному уровню, тогда все в порядке.

2 голосов
/ 30 июня 2010

Поздравляем с первым приложением на Java!

Java-приложения запускаются на виртуальной машине.Виртуальной машине был назначен фиксированный объем памяти ОС, обычно 512 МБ.Пока приложение использует менее 512 МБ, сборщик мусора не запускается и не начинает поиск «мертвых» блоков памяти.Предел памяти JVM может быть изменен в большинстве операционных систем.Попробуйте, например, изменить ограничение памяти до 32 МБ.

2 голосов
/ 30 июня 2010

Поздравляю с первым приложением! Теперь пара вещей для размышления. Во-первых, диспетчер задач Windows не является хорошим ресурсом, чтобы понять, как быстро растет ваш виртуальный компьютер. Вместо этого вам следует отслеживать статистику сборки мусора в консоли (используйте параметр командной строки -verbose:gc). Во-вторых, если вас беспокоят потенциальные утечки и рост виртуальной машины, существует множество отличных профилировщиков, которые просты в использовании и могут помочь вам диагностировать проблемы с памятью. проверьте эти два сообщения для некоторых опций профилировщика.

1 голос
/ 30 июня 2010

это нормально. некоторые фоновые вычисления могут оставить вокруг мертвые объекты, которые JVM не спешит вычищать. в конце концов, они будут собирать мусор при приближении к max mem.

оставьте вашу программу работающей на ночь, и ваша машина не взорвется.

1 голос
/ 30 июня 2010

Это нормальное поведение Java?

номер

Я полагаю, что мой код может быть утечка памяти

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

Я заметил, что вы используете Swing, убедитесь, что вы запускаете JFrame в потоке диспетчеризации событий , используя метод invokeLater(Runnable).

Если вы используете какие-либо коллекции, убедитесь, что вы clear сделали их один раз.

Поскольку вы выполняете какой-либо файловый ввод-вывод, убедитесь, что вы закрыли все классы, участвующие в операциях ввода-вывода, после того, как вы закончили с ними.

Если вы используете какие-либо прослушиватели событий, не забудьте явно удалить прослушиватели событий, когда они больше не нужны.


Одна вещь, которую вы можете попробовать, это экспериментировать. Возьми заявку и удали файл IO, посмотри что получится. Использование памяти продолжает расти, как раньше? Теперь восстановите ваше приложение до нормального и удалите текстовую область - память продолжает расти, как раньше? И т. Д., И т. Д. Это поможет вам определить, что является источником, и вы можете сосредоточить свои усилия там. Скорее всего, вы узнаете, что вам нужно, выполнив это.

Еще один полезный инструмент диагностики - это использование System.gc() в определенные моменты времени, обычно после тяжелых блоков кода. Это скажет JVM выполнить сборку мусора в этот момент выполнения, а не в другое время, определяемое потреблением памяти. Это поможет вам учесть любые периодические колебания использования памяти вашего приложения.

В противном случае вы всегда можете использовать профилировщик памяти. Если вы используете среду IDE Netbeans, она встроена прямо в нее. Для Eclipse есть несколько плагинов, которые могут выполнять профилирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...