java.lang.OutOfMemoryError: простір купи Java


96

Я отримую наступну помилку під час виконання багатопотокової програми

java.lang.OutOfMemoryError: Java heap space

Вищевказана помилка сталася в одному з потоків.

  1. Наскільки мені відомо, простір купи займають лише змінні екземпляра. Якщо це правильно, то чому ця помилка сталася після нормального запуску протягом деякого часу, оскільки простір для змінних екземпляра виділяється під час створення об'єкта.

  2. Чи є спосіб збільшити простір купи?

  3. Які зміни слід внести у свою програму, щоб вона зайняла менше місця?


Відповіді:


104

Якщо ви хочете збільшити простір купи, ви можете скористатися java -Xms<initial heap size> -Xmx<maximum heap size>командним рядком. За замовчуванням значення базуються на версії JRE та конфігурації системи. Ви можете дізнатись більше про параметри віртуальної машини на веб-сайті Java .

Однак я б порекомендував скласти профіль вашої програми, щоб з’ясувати, чому з’їдається ваш розмір купи. NetBeans має в своєму складі дуже хороший профайлер . Я вважаю, що він використовує jvisualvmпід капотом. За допомогою профілювача можна спробувати знайти, де створюється багато об’єктів, коли об’єкти збирають сміття тощо.


1
Я використовую Netbeans, але я не знаю, як користуватися профіліром. Я хотів би дізнатися більше про профайлер, щоб я міг використовувати його для виявлення витоків пам’яті в моїй програмі.
Ятендра Гоель,

Я додав посилання на сторінку на сайті NetBeans ( profiler.netbeans.org ), де є дуже хороша документація про профіль, починаючи від самих основ і закінчуючи більш просунутим використанням.
Томас Оуенс,

Значення за замовчуванням змінюються з версіями Java, було б непогано включити цю інформацію у свою відповідь.
Даріуш,

Просто вирішив подібну проблему і вперше спробував: java -jar division.jar -Xmx512m -Xms512m - це дає мені ту ж помилку, але коли я роблю це так: java -Xmx512m -Xms512m -jar division.jar - все добре. Тож порядок параметрів також важливий.
hipokito

@hipokito Аргументи після передачі файлу jar до методу main () jar-файлу як аргументи []
Asu,

29

1. - Так, але це в значній мірі стосується всієї пам'яті, що використовується вашою програмою.

2. - Так, див. Параметри Java VM

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

Тобто

java -Xmx2g призначте додатку максимум 2 гігабайти оперативної пам'яті

Але спочатку слід перевірити, чи не виникла пам’ять.

3. - Це залежить від програми. Спробуйте помітити витоки пам’яті. На це питання важко відповісти. Останнім часом ви можете створити профіль за допомогою JConsole, щоб спробувати з'ясувати, куди йде ваша пам'ять


while
which

8

Можливо, ви захочете заглянути на цей сайт, щоб дізнатись більше про пам’ять у JVM: http://developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage

Я знайшов корисним використання visualgc щоб спостерігати, як заповнюються різні частини моделі пам'яті, щоб визначити, що змінити.

Важко визначити, яка частина пам'яті була заповнена, отже, visualgc, оскільки вам може знадобитися просто змінити ту частину, яка має проблему, а не просто сказати:

Чудово! Я дам 1G оперативної пам'яті JVM.

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

Щоб визначити, де може бути витік пам’яті, ви можете використовувати для цього модульні тести, перевіривши, якою була пам’ять до тесту і після, і якщо є занадто великі зміни, можливо, ви захочете перевірити їх, але вам потрібно зробіть перевірку, поки тест ще працює.


6

Для збільшення розміру купи ви можете використовувати аргумент -Xmx під час запуску Java; напр

-Xmx256M

6

Ви можете отримати обсяг пам'яті купи за допомогою програми нижче.

public class GetHeapSize {
    public static void main(String[] args) {
        long heapsize = Runtime.getRuntime().totalMemory();
        System.out.println("heapsize is :: " + heapsize);
    }
} 

тоді відповідно можна збільшити розмір купи також за допомогою: java -Xmx2g http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html


6
  1. Наскільки мені відомо, простір купи займають лише змінні екземпляра. Якщо це правильно, то чому ця помилка сталася після нормального запуску протягом деякого часу, оскільки простір для змінних екземпляра виділяється під час створення об'єкта.

Це означає, що ви постійно створюєте більше об’єктів у своїй програмі. Нові об'єкти будуть зберігатися в купі пам'яті, і це є причиною зростання пам'яті купи.

Купа не тільки містить змінні екземпляра. Він буде зберігати всі непримітивні типи даних (Об'єкти). Час життя цих об'єктів може бути коротким (блок методів) або довгим (доти, доки на об'єкт не буде вказано посилання у вашій програмі)

  1. Чи є спосіб збільшити простір купи?

Так. Погляньте на цю статтю оракула щоб дізнатися більше.

Існує два параметри для встановлення розміру купи:

-Xms:, який встановлює початковий та мінімальний розмір купи

-Xmx:, який встановлює максимальний розмір купи

  1. Які зміни слід внести у свою програму, щоб вона зайняла менше місця?

Це залежить від вашої заявки.

  1. Встановіть максимальну пам’ять купи відповідно до вимог програми

  2. Не викликайте витоків пам’яті у вашій програмі

  3. Якщо ви виявили витоки пам'яті у вашому додатку, знайдіть основну причину за допомогою інструментів профілювання, таких як MAT , Visual VM , jconsole тощо. Як тільки ви знайдете першопричину, усуньте витоки.

Важливі примітки зі статті oracle

Причина: Детальне повідомлення Java heap space вказує на те, що об'єкт не міг бути виділений у купі Java. Ця помилка не обов'язково передбачає витік пам'яті.

Можливі причини:

  1. Неправильна конфігурація (не виділення достатньої пам'яті)
  2. Додаток ненавмисно утримує посилання на об’єкти, що запобігає збиранню сміття
  3. Програми, які надмірно використовують фіналізатори. Якщо клас має метод finalize, тоді об’єкти цього типу не відновлюють свій простір під час збирання сміття. Якщо потік фіналізатора не може встигати за чергою завершення, куча Java може заповнитись, і буде викинуто такий тип виключення OutOfMemoryError .

З іншого боку, використовуйте кращі алгоритми збору сміття ( CMS або G1GC )

Погляньте на це питання, щоб зрозуміти G1GC


5
  1. У більшості випадків код не оптимізований. Звільніть ті предмети, які, на вашу думку, не знадобляться далі. Уникайте створення об’єктів у вашому циклі кожного разу. Спробуйте використовувати кеші. Я не знаю, як працює ваша програма. Але в програмуванні також застосовується одне правило звичного життя

    Профілактика краще, ніж лікування. "Не створювати непотрібних об'єктів"


3
  1. Локальні змінні розміщені в стеку. Простір купи займають предмети.

  2. Ви можете скористатися цією -Xmxопцією.

  3. В основному куча місця використовується кожного разу, коли ви виділяєте новий об'єкт, newі звільняється через деякий час після того, як на об'єкт більше немає посилань. Тож переконайтесь, що ви не зберігаєте посилань на об’єкти, які вам більше не потрібні.


1

Ні, я думаю, ви думаєте про місце стеку. Простір купи займають предмети. Шлях його збільшення -Xmx256m, замінюючи 256 на потрібну суму в командному рядку.


1

Щоб уникнути цього винятку, якщо ви використовуєте JUnit і Spring, спробуйте додати це до кожного тестового класу:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)

0

У netbeans перейдіть до панелі інструментів "Виконати", -> "Встановити конфігурацію проекту" -> "Налаштувати" -> "запустити" його спливаюче віндо -> "Параметр VM" -> заповніть '-Xms2048m -Xmx2048м '. Це може вирішити проблему розміру купи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.