Ловля java.lang.OutOfMemoryError?


101

Документація для java.lang.Errorтверджень:

Помилка - це підклас Throwable, який вказує на серйозні проблеми, які розумна програма не повинна намагатися наздогнати

Але оскільки java.lang.Errorце підклас java.lang.Throwable, я можу зловити цей тип Throwable.

Я розумію, чому не дуже вдало виловлювати такий виняток. Наскільки я розумію, якщо ми вирішимо її зловити, обробник лову не повинен виділяти ніякої пам'яті сам по собі. Інакше OutOfMemoryErrorбуде кинутий знову.

Отже, моє питання:

  1. Чи існують якісь реальні сценарії, коли лов java.lang.OutOfMemoryErrorможе бути гарною ідеєю?
  2. Якщо ми вирішимо зловити java.lang.OutOfMemoryError, як ми можемо переконатися, що обробник улову не виділяє будь-яку пам'ять самостійно (будь-які інструменти та найкращі практики)?


Для вашого першого питання я додам, що я зловлю OutOfMemoryError, щоб (принаймні спробувати) повідомити користувача про проблему. Раніше помилка не була зафіксована в пункті вилову (виняток e), і користувачеві не було показано зворотного зв'язку.
Хосеп Родрігес Лопес

1
Є конкретні випадки, наприклад, виділення гігантського масиву, де можна виявити помилку OOM навколо цієї операції та відновити досить добре. Але розмістити спробу / зловити навколо великого коду та спробувати відновити та продовжувати, ймовірно, погана ідея.
Гарячі лизання

Відповіді:


85

Я згоден і не згоден з більшістю відповідей тут.

Існує ряд сценаріїв, за яких ви, можливо, захочете впіймати OutOfMemoryErrorі, на мій досвід (у Windows та Solaris JVM), лише дуже рідко є OutOfMemoryErrorсмертельна коліна для СП.

Є лише одна вагома причина зловити, OutOfMemoryErrorа це - граціозно закрити, чисто вивільнити ресурси та записати причину невдачі якнайкраще (якщо це все-таки можливо).

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

Коли Errorвикинуто, купу містить ту саму кількість виділених об'єктів, що і до невдалого розподілу, і тепер настав час скинути посилання на об'єкти, які виконуються, щоб звільнити ще більше пам'яті, яка може знадобитися для очищення. У цих випадках це може бути навіть можливим продовженням, але це, безумовно, буде поганою ідеєю, оскільки ви ніколи не можете бути впевнені на 100%, що JVM знаходиться в стані, що підлягає ремонту.

Демонстрація, OutOfMemoryErrorяка не означає, що JVM не має пам’яті в блоці захоплення:

private static final int MEGABYTE = (1024*1024);
public static void runOutOfMemory() {
    MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
    for (int i=1; i <= 100; i++) {
        try {
            byte[] bytes = new byte[MEGABYTE*500];
        } catch (Exception e) {
            e.printStackTrace();
        } catch (OutOfMemoryError e) {
            MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
            long maxMemory = heapUsage.getMax() / MEGABYTE;
            long usedMemory = heapUsage.getUsed() / MEGABYTE;
            System.out.println(i+ " : Memory Use :" + usedMemory + "M/" + maxMemory + "M");
        }
    }
}

Вихід цього коду:

1 : Memory Use :0M/247M
..
..
..
98 : Memory Use :0M/247M
99 : Memory Use :0M/247M
100 : Memory Use :0M/247M

Якщо я запускаю щось критичне, я зазвичай Errorвловлюю його, записую його до syserr, а потім реєструю його за допомогою моєї системи журналу вибору, а потім переходжу до звільнення ресурсів і закриваюсь чисто. Що найгірше, що може статися? JVM в будь-якому випадку гине (або вже мертвий), і вловлюючи його Error, є принаймні шанс очищення.

Застереження полягає в тому, що вам потрібно націлитись на усунення цих типів помилок лише в тих місцях, де можлива чистка. Не catch(Throwable t) {}скрізь ковдри та дурниць.


Погодьтеся, я опублікую свій експеримент на нову відповідь.
Містер Сміт

4
"ви ніколи не можете бути впевнені на 100%, що JVM перебуває у OutOfMemoryErrorстані, що підлягає ремонту": тому що це може бути кинуто з точки, яка поставила вашу програму в непослідовний стан, тому що її можна кинути в будь-який час. Див stackoverflow.com/questions/8728866 / ...
Raedwald

У OpenJdk1.7.0_40 я не отримую жодної помилки чи винятку, коли запускаю цей код. Навіть я змінив MEGABYTE на GIGABYTE (1024 * 1024 * 1024). Це через оптимізатор видаляє змінну 'байт [] байтів', оскільки вона не використовується в решті коду?
RoboAlex

"Існує ряд сценаріїв, за яких ви хочете зловити OutOfMemoryError" проти "Є лише одна вагома причина - зловити OutOfMemoryError" . Приведи мозок у порядок!!!
Stephen C

3
Справжній сценарій, коли ви МОЖЕТЕ захопити помилку OutOfMemory: коли це викликано спробою виділити масив з більш ніж 2G елементами. Назва помилки є дещо помилковим у цьому випадку, але це все-таки OOM.
Чарльз Рот

31

Ви можете відновити його:

package com.stackoverflow.q2679330;

public class Test {

    public static void main(String... args) {
        int size = Integer.MAX_VALUE;
        int factor = 10;

        while (true) {
            try {
                System.out.println("Trying to allocate " + size + " bytes");
                byte[] bytes = new byte[size];
                System.out.println("Succeed!");
                break;
            } catch (OutOfMemoryError e) {
                System.out.println("OOME .. Trying again with 10x less");
                size /= factor;
            }
        }
    }

}

Але чи є сенс? Що ще ви хотіли б зробити? Чому б ви спочатку виділили стільки пам’яті? Чи менше ОК також? Чому ви все одно не скористаєтесь цим? Або якщо це неможливо, то чому б просто не дати JVM більше пам’яті від початку?

Назад до запитань:

1: Чи є якісь реальні сценарії слова при лові java.lang.OutOfMemoryError може бути хорошою ідеєю?

Ніхто не спадає на думку.

2: якщо ми ловимо java.lang.OutOfMemoryError, як ми можемо впевнитись, що обробник лову не виділяє жодної пам’яті самостійно (будь-які інструменти та найкращі практики)?

Залежить від того, що спричинило ДОБРЕ. Якщо це оголошено поза tryблоком, і це сталося поетапно, то ваші шанси невеликі. Ви можете заздалегідь зарезервувати трохи пам’яті:

private static byte[] reserve = new byte[1024 * 1024]; // Reserves 1MB.

а потім встановіть його на нуль протягом OOME:

} catch (OutOfMemoryException e) {
     reserve = new byte[0];
     // Ha! 1MB free!
}

Звичайно, це не має сенсу;) Просто дайте JVM достатньо пам'яті, як цього вимагає ваша заявка. За необхідності запустіть профілер.


1
Навіть резервуючи простір, це не є гарантією робочого рішення. Цей простір може бути зайнятий і якоюсь іншою темою;)
Вольф

@Wolph: Тоді надайте JVM більше пам’яті! O_o Все з усім, що справді не має сенсу;)
BalusC

2
Перший фрагмент працює, тому що об'єкт, який викликав помилку, є єдиним великим об'єктом (масивом). Коли буде досягнуто застереження про вилучення, воно було зібране голодним пам'яттю JVM. Якщо ви використовували один і той же об'єкт поза блоком спробу, або в іншій потоці, або в тому ж улові, JVM не збирає його, що робить неможливим створення нового єдиного об'єкту будь-якого типу. наприклад, другий фрагмент може не працювати.
Містер Сміт

3
чому б просто не встановити його null?
Pacerier

1
@MisterSmith Ваш коментар не має сенсу. Великого об'єкта не існує. Він не був виділений в першу чергу: він запустив OOM, тому він, звичайно, не потребує GC.
Маркіз Лорн

15

Взагалі, це погана ідея, щоб спробувати зловити та відновитись з OOM.

  1. OOME також може бути перекинутий на інші теми, включаючи теми, про які ваша програма навіть не знає. Будь-які такі нитки тепер будуть мертвими, і все, що чекало на сповіщення, може застрягнути назавжди. Коротше кажучи, ваш додаток може бути остаточно зламано.

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

Найкраще, що можна зробити з OOME - це дозволити померти JVM.

(Це передбачає , що JVM робить вмирають. Наприклад OOMS на сервлетів Tomcat нитка не вбити JVM, і це призводить до Tomcat вдаючись в нерухоме стані , в якому він не буде реагувати на будь-які запити ... навіть не просить перезапустити.)

EDIT

Я не кажу, що це погана ідея спіймати ООМ. Проблеми виникають, коли ви намагаєтесь відновитись із OOME, навмисно чи за допомогою нагляду. Щоразу, коли ви ловите OOM (безпосередньо, або як підтип Помилки або Throwable), вам слід або повторно скинути його, або домовитись про те, що програма / JVM закривається.

Убік: Це говорить про те, що для досягнення максимальної надійності перед обличчям OOM додаток повинен використовувати Thread.setDefaultUncaughtExceptionHandler (), щоб встановити обробник, який призведе до виходу програми у випадку наявності OOME, незалежно від того, на яку нитку накидається OOME. Мені будуть цікаві думки з цього приводу ...

Єдиний інший сценарій - це коли ви точно знаєте , що ООМ не призвело до заподіяння шкоди; тобто ви знаєте:

  • що конкретно спричинило ДОЧЕГО,
  • що програма робила у той час, і що добре просто відмовитися від обчислень та
  • що (приблизно) одночасне OOME не могло статися в іншому потоці.

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

(Проблема полягає в тому, що потрібен офіційний доказ, який свідчить про те, що наслідки "очікуваних" OOME є безпечними, і що "непередбачені" OOME не можуть виникнути під контролем спроби / зловити OOME.)


Так, я згоден з вами. Взагалі це погана ідея. Але чому тоді я маю можливість це зловити? :)
Денис Баженов

@dotsid - 1) тому, що є випадки, коли ви повинні зловити його, і 2) тому, що унеможливити ловити OOM, це негативно вплине на мову та / або інші частини часу виконання Java.
Стівен C

1
Ви кажете: "тому що є випадки, коли вам слід це зловити". Тож це було частиною мого оригінального запитання. Які випадки, коли ви хочете зловити OOME?
Денис Баженов

1
@dotsid - дивіться мою відредаговану відповідь. Єдиний випадок, який я можу придумати, щоб зловити OOM, - це коли вам потрібно зробити це, щоб змусити багатопотокове додаток вийти в разі наявності OOM. Можливо, ви хочете зробити це для всіх підтипів Error.
Стівен C

1
Справа не в тому, щоб просто зловити OOMES. Вам також потрібно відновитись після них. Як нитка відновити , якщо він повинен був (скажімо) повідомить іншу нитку ... але отримав OOME? Звичайно, JVM не помре. Але програма, ймовірно, перестане працювати через потоки, застряглі в очікуванні сповіщень від потоків, які перезапущені через ловлі OOME.
Stephen C

14

Так, існують реальні сценарії. Ось моя: мені потрібно обробити набори даних дуже багатьох елементів на кластері з обмеженою пам’яттю на вузол. Дані екземпляри JVM проходять через багато елементів один за одним, але деякі елементи занадто великі, щоб обробити кластер: Я можу OutOfMemoryErrorзафіксувати та відзначити, які елементи занадто великі. Пізніше я можу повторно запустити лише великі предмети на комп'ютері з більшою кількістю оперативної пам’яті.

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


Так у вас є код, як byte[] bytes = new byte[length]? Чому б просто не перевірити sizeв більш ранній момент?
Raedwald

1
Тому що те саме sizeбуде добре з більшою кількістю пам’яті. Я виходжу через виняток, тому що в більшості випадків все буде добре.
Майкл Кун

10

Однозначно є сценарії, коли ловити OOME має сенс. IDEA перехоплює їх і спливає діалогове вікно, щоб ви могли змінити налаштування пам'яті запуску (а потім виходите, коли закінчите). Сервер додатків може захопити та повідомити про них. Ключовим для цього є зробити це на високому рівні під час відправки, щоб у вас був розумний шанс звільнити купу ресурсів у місці, коли ви ловите виняток.

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

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


8

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

У будь-якому разі я працюю над додатком Android, який можна запускати на різних пристроях з різним розміром пам'яті. Небезпечна частина - це розшифровка растрової карти з файлу та передача її в екземпляр ImageView. Я не хочу обмежувати більш потужні пристрої за розміром декодованої растрової карти, не можу бути впевненим, що додаток не буде запускатися на старовинному пристрої, на який я ніколи не стикався з дуже низькою пам’яттю. Отже, я роблю це:

BitmapFactory.Options bitmapOptions = new BitmapFactory.Options(); 
bitmapOptions.inSampleSize = 1;
boolean imageSet = false;
while (!imageSet) {
  try {
    image = BitmapFactory.decodeFile(filePath, bitmapOptions);
    imageView.setImageBitmap(image); 
    imageSet = true;
  }
  catch (OutOfMemoryError e) {
    bitmapOptions.inSampleSize *= 2;
  }
}

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


1
Іншим варіантом було б обчислити, наскільки великі растрові карти ви можете обробляти, а не намагатися та не вдається. "Винятки слід використовувати для виняткових випадків", - думаю, хтось сказав. Але я скажу, ваше рішення здається найлегшим виходом, можливо, не найкращим, але, мабуть, найлегшим.
jontejj

Це залежить від кодека. Уявіть, що bmp 10MB, ймовірно, призводить до лише трохи більше 10MB купи, тоді як JPEG у 10MB "вибухне". Те саме в моєму випадку, коли я хочу проаналізувати XML, який може значно змінюватися залежно від складності вмісту
Даніель Олдер

5

Так, справжнє питання - "що ти збираєшся робити в обробці винятків?" Майже на все корисне, ви виділите більше пам’яті. Якщо ви хочете виконати деяку діагностичну роботу, коли виникає OutOfMemoryError, ви можете використовувати -XX:OnOutOfMemoryError=<cmd>гачок, який постачає HotSpot VM. Він виконає ваші команди (и), коли відбудеться OutOfMemoryError, і ви можете зробити щось корисне поза купою Java. Ви дійсно хочете, щоб програма не втрачала пам'яті в першу чергу, тому з'ясування причини цього відбувається - це перший крок. Тоді ви можете збільшити розмір купи MaxPermSize у відповідних випадках. Ось деякі інші корисні гачки HotSpot:

-XX:+PrintCommandLineFlags
-XX:+PrintConcurrentLocks
-XX:+PrintClassHistogram

Повний список дивіться тут


Це навіть гірше, ніж ти думаєш. Оскільки OutOfMemeoryError може бути викинуто в будь-яку точку вашої програми (не тільки з newзаяви), ваша програма буде в невизначеному стані, коли ви ловите екзакцію.
Raedwald

5

У мене є додаток, який потребує відновлення після збоїв у OutOfMemoryError, і в однопотокових програмах він завжди працює, але іноді не працює у багатопотокових програмах. Додаток - це автоматизований інструмент тестування Java, який виконує згенеровані тестові послідовності на максимально можливу глибину на тестових класах. Тепер користувальницький інтерфейс повинен бути стабільним, але тестовий двигун може втратити пам'ять під час вирощування дерева тестових випадків. Я вирішую це за допомогою наступної ідіоми коду в тестовій машині:

булева isOutOfMemory = хибна; // прапор, який використовується для звітування
спробуйте {
   ДеякіТипи великихVar;
   // Основний цикл, що виділяє все більше і більше для великихВар
   // може припинити OK або підняти OutOfMemoryError
}
улов (OutOfMemoryError ex) {
   // LargeVar зараз поза сферою, так само сміття
   System.gc (); // очищення даних великихVar
   isOutOfMemory = true; // прапор, доступний для використання
}
// Прапор програмних тестів для повідомлення про відновлення

Це працює щоразу в однопотокових програмах. Але я нещодавно помістив свій тестовий двигун в окрему робочу нитку від інтерфейсу користувача. Тепер поза пам'яті може виникнути довільно в будь-якому потоці, і мені незрозуміло, як її вловити.

Наприклад, у мене виникло OOME, коли кадри анімованого GIF у моєму інтерфейсі циклізувались власним потоком, який створюється поза кадром класом Swing, який знаходиться поза моїм контролем. Я думав, що я виділив усі необхідні ресурси заздалегідь, але чітко аніматор виділяє пам'ять щоразу, коли отримує наступне зображення. Якщо хтось має уявлення про те, як поводитися з OOMEs, піднятим у будь-якій нитці, я хотів би почути.


Якщо в одному додатку з потоковим потоком ви більше не використовуєте деякі проблемні нові об’єкти, створення яких винищило помилку, вони можуть бути зібрані в пункті вилучення. Однак якщо JVM виявить, що об’єкт може бути використаний пізніше, він не може бути зібраний, і додаток підірветься. Дивіться мою відповідь у цій темі.
Містер Сміт

4

НАДЕЙ можна наздогнати, але це буде взагалі марно, залежно від того, чи зможе JVM зібрати сміття з якихось предметів, коли буде досягнуто вилову, і скільки пам’ятної пам’яті залишилось до цього часу.

Приклад: у моєму JVM ця програма працює до завершення:

import java.util.LinkedList;
import java.util.List;

public class OOMErrorTest {             
    public static void main(String[] args) {
        List<Long> ll = new LinkedList<Long>();

        try {
            long l = 0;
            while(true){
                ll.add(new Long(l++));
            }
        } catch(OutOfMemoryError oome){         
            System.out.println("Error catched!!");
        }
        System.out.println("Test finished");
    }  
}

Однак лише додавання одного рядка в улові покаже вам, про що я говорю:

import java.util.LinkedList;
import java.util.List;

public class OOMErrorTest {             
    public static void main(String[] args) {
        List<Long> ll = new LinkedList<Long>();

        try {
            long l = 0;
            while(true){
                ll.add(new Long(l++));
            }
        } catch(OutOfMemoryError oome){         
            System.out.println("Error catched!!");
            System.out.println("size:" +ll.size());
        }
        System.out.println("Test finished");
    }
}

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

Однак якщо такий код розташований таким чином, як список llвикористовується після того, як OOME був зчеплений, JVM не може його зібрати. Це відбувається у другому фрагменті. OOME, викликаний новим створенням Long, потрапляє, але незабаром ми створюємо новий Об'єкт (String у System.out,printlnрядку), і купа майже повна, тому нове OOME кидається. Це найгірший випадок: ми намагалися створити новий об’єкт, нам не вдалося, ми схопили OOME, так, але тепер перша інструкція, яка вимагає нової купи пам’яті (наприклад: створення нового об’єкта), викине новий OOME. Подумайте над тим, що ще ми можемо зробити в цей момент з таким мало пам’яті ?. Напевно, просто виходить. Звідси марне.

Серед причин того, що JVM не збирає ресурси, одна справді страшна: спільний ресурс з іншими потоками також використовує його. Кожен, хто має мозок, може побачити, наскільки небезпечним може бути ловити OOME, якщо його вставити у будь-який неекспериментальний додаток будь-якого типу.

Я використовую 32-бітний JVM (JRE6) для Windows x86. Пам'ять за замовчуванням для кожного додатка Java становить 64 Мб.


Що робити, якщо я ll=nullвсередині блоку лову?
Naanavanalla

3

Єдиною причиною, з якої я можу подумати, чому ловити помилки OOM, може бути те, що у вас є масивні структури даних, які ви більше не використовуєте, і можете встановити на нуль і звільнити деяку кількість пам'яті. Але (1) це означає, що ви витрачаєте пам’ять, і вам слід виправити код, а не просто кульгати після OOME, і (2) навіть якщо ви його зловили, що б ви зробили? OOM може статися в будь-який час, потенційно залишаючи все наполовину готовим.


3

Для питання 2 я вже бачу рішення, яке я запропонував би, BalusC.

  1. Чи є якісь реальні сценарії слів під час лову на java.lang.OutOfMemoryError?

Я думаю, що я просто натрапив на хороший приклад. Коли додаток awt розсилає повідомлення, на stderr відображається незахований OutOfMemoryError, а обробка поточного повідомлення припиняється. Але додаток продовжує працювати! Користувач може видавати інші команди, не знаючи про серйозні проблеми, що трапляються поза сценою. Особливо, коли він не може або не дотримується стандартної помилки. Тож знайти виняток oom та забезпечити (або принаймні запропонувати) перезапуск програми - щось бажане.


3

У мене просто є сценарій, коли ловити OutOfMemoryError, здається, має сенс і, здається, працює.

Сценарій: в додатку для Android я хочу відображати декілька растрових зображень з максимально можливою роздільною здатністю, і я хочу мати можливість їх масштабного масштабування.

Через плавне збільшення я хочу мати растрові карти в пам'яті. Однак Android має обмеження в пам'яті, які залежать від пристрою і які важко контролювати.

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


0
  1. Залежить від того, як ви визначаєте "добре". Ми робимо це у нашому баггі-веб-додатку, і він працює більшу частину часу (на щастя, зараз OutOfMemoryце не відбувається через непов'язане виправлення). Однак, навіть якщо ви його схопили, він все-таки може порушити якийсь важливий код: якщо у вас є кілька потоків, розподіл пам’яті може не вдатися до жодної з них. Отже, залежно від вашої заявки, все ж є 10–90% шансів, що вона буде незворотно зламана.
  2. Наскільки я розумію, важкі розмотування стека на шляху призведе до втрати такої кількості посилань і, таким чином, звільнить стільки пам’яті, що вам не варто про це турбуватися.

EDIT: Я пропоную спробувати. Скажімо, написати програму, яка рекурсивно викликає функцію, яка поступово виділяє більше пам'яті. Ловіть OutOfMemoryErrorі подивіться, чи можете ви змістовно продовжувати з цього моменту. Згідно з моїм досвідом, ви зможете, хоч у моєму випадку це сталося на сервері WebLogic, тому, можливо, була якась чорна магія.


-1

Ви можете зловити що завгодно під Throwable, загалом кажучи, вам слід виловлювати лише підкласи винятку, виключаючи RuntimeException (хоча значна частина розробників також ловить RuntimeException ... але це ніколи не було наміром мовних дизайнерів).

Якби ви зловили OutOfMemoryError, що б ви зробили? У VM немає пам’яті, в основному все, що ви можете зробити, це вихід. Напевно, ви навіть не можете відкрити діалогове вікно, щоб сказати їм, що у вас немає пам’яті, оскільки це займе пам’ять :-)

ВМ викидає OutOfMemoryError, коли він справді не з пам’яті (насправді всі Помилки повинні вказувати на невиправні ситуації), і ви справді нічого не можете зробити з цим.

Що потрібно зробити, це з’ясувати, чому у вас не вистачає пам’яті (використовуйте профілер, як у NetBeans), і переконайтеся, що у вас немає витоків пам’яті. Якщо у вас немає витоків пам’яті, тоді збільште пам'ять, яку ви виділяєте для VM.


7
Помилковим уявленням, яке ваша публікація увічнює, є те, що OOM вказує на те, що JVM втрачено в пам'яті. Натомість це фактично вказує на те, що JVM не міг виділити всю пам'ять, якій йому було доручено. Тобто, якщо у JVM є 10B простору, а ви 'новим' об'єктом 100B, він вийде з ладу, але ви зможете розвернутися та 'new up' об'єкт 5B і бути добре.
Тім Бендер

1
А якщо мені потрібно лише 5В, то чому я прошу 10В? Якщо ви робите розподіл на основі проб і помилок, ви робите це неправильно.
TofuBeer

2
Я думаю, що Тим означав, що ти можеш виконати якусь роботу навіть у ситуації OutOfMemory. Наприклад, може бути достатньо пам'яті для відкриття діалогового вікна.
Стівен Ейлерт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.