Спецификация виртуальной машины Java предусматривает, что память JVM делится на несколько блоков, таких как куча, стек, счетчик программы, область метода и т. Д. При реализации Hotspot JVM память кучи разделена на три части, новое поколение, старая возраста и постоянная полоса. Постоянная полоса реализует область метода, указанная в спецификации, и различные части модели памяти будут иметь соответствующие ошибки OutofmemoryError. Далее, давайте обсудим это отдельно. Я считаю, что большинство разработчиков столкнулись с этой ошибкой, и причины этой ошибки в основном вызваны следующими причинами:
Память JVM слишком мала, и программа не жесткая, что приводит к слишком большому количеству мусора.
Существует несколько общих причин исключений OutofmemoryError:
Общие подсказки по ошибке для этой ошибки:
Stackoverflowerror
Stack Overflow бросает ошибку java.lang.stackoverflowerror. Это происходит потому, что глубина стека превышает максимальную глубину, разрешенную виртуальной машиной при запуске метода. Эта ситуация обычно возникает из -за ошибок программы. Например, написание мертвой рекурсии может вызвать эту ситуацию. Давайте смоделируем переполнение памяти в этой ситуации через кусок кода.
Импорт java.util.*; импортировать java.lang.*; открытый класс oomtest {public void stackoverflowMethod () {stackoverflowMethod (); } public static void main (string ... args) {oomtest oom = new oomtest (); oom.stackoverflowMethod (); }} Запуск вышеупомянутого кода выставит следующее исключение:
Исключение в потоке "Main" java.lang.stackoverflowerror в oomtest.stackoverflowmethod (oomtest.java:6)
Переполнение кучи (OutofmemoryError: Java Heap Space)
Когда память кучи переполняется, виртуальная машина бросает java.lang.outofmemoryerror: java huep space. Когда это произойдет, нам нужно проанализировать его специально на основе файла дампа, сгенерированного при переполнении памяти (-xx: +HeapdumponoutofmemoryErrorjvm, необходимо добавить параметр запуска). Когда возникает такая проблема, это может быть утечка памяти или переполнение памяти.
Если утечка памяти нам нужно выяснить, как начитывается корень GC, а затем проанализировать причину утечки через эталонную цепь.
Если есть проблема переполнения памяти, это часто потому, что программа требует большей памяти, чем память, которую мы настраиваем для виртуальной машины. В этом случае мы можем использовать -xmx для решения этой проблемы.
Ниже мы демонстрируем переполнение этой ситуации через следующий код:
Импорт java.util.*; импортировать java.lang.*; открытый класс oomtest {public static void main (string ... args) {list <byte []> buffer = new ArrayList <byte []> (); buffer.add (новый байт [10*1024*1024]); }} Мы запускаем приведенный выше код через следующую команду:
java -verbose: gc -xmn10m -xms20m -xmx20m -xx:+printgc oomtest
Программа вводит следующую информацию:
[GC 1180K-> 366K (19456K), 0,0037311 Secs] [Полный GC 366K-> 330K (19456K), 0,0098740 с] [Полный GC 330K-> 292K (19456K), 0,0090244 Secs] Исключение в «Главном» java. Oomtest.main (oomtest.java:7)
Из результатов бега мы видим, что JVM выполнил второстепенный GC один раз и дважды мажор. Из вывода крупного GC можно увидеть, что скорость использования старой области после GC составляет 134 тыс., А массив байтов составляет 10 м, что составляет больше, чем пространство старого поколения, поэтому исключение. Если -xms21m и -xmx21m отрегулированы, то операция GC не будет инициирована и не будет исключения.
Благодаря вышеупомянутому эксперименту был проверен вывод со стороны: когда объект больше, чем оставшаяся память о новом поколении, он будет помещен непосредственно в старость. Когда оставшаяся память о старости до сих пор не может быть подавлена, сборы мусора будут запускаются. Если его все еще нельзя положить после сбора, будет брошено исключение переполнения памяти.
Персген пространство
Мы знаем, что Hotspot JVM реализует область метода в спецификации виртуальной машины Java через постоянные полосы, а пул постоянного времени выполняется в области метода. Следовательно, переполнение постоянной полосы может быть постоянным переполнением пула времени выполнения, или объекты класса, сохраненные в области метода, не переработаны во времени, или память, занятая информацией класса, превышает нашу конфигурацию. Когда группа постоянств переполняется, Java.lang.outofmemoryerror: Пространство пермина.
Я могу испытать эту проблему в следующих сценариях при работе.
При использовании горячего развертывания некоторых серверов приложений мы несколько раз столкнемся с горячим развертыванием и обнаружим, что переполнение памяти. Это потому, что после каждого горячего развертывания оригинальный класс не был удален.
Если само приложение больше и включает в себя больше библиотек классов, эта проблема также может возникнуть, когда память, которую мы выделяем на постоянную полосу (установленную By -xx: Permsize и -xx: maxpermsize), является относительно мала.
Некоторые сторонние фреймворки, такие как Spring и Hibernate, все реализуют некоторые расширенные функции с помощью технологии генерации байт-кодов (такого как CGLIB), которая может потребовать большей области метода для хранения динамически сгенерированных файлов класса.
Мы знаем, что константы струн в Java помещаются в постоянный бассейн. Когда запускается метод string.intern (), он проверит, хранятся ли объекты, равные этой строке в постоянном пуле. Если существует, непосредственно верните ссылку на объект в постоянном пуле. Если он не существует, сначала добавьте эту строку в постоянный пул, а затем верните ссылку на строку. Затем мы можем имитировать переполнение постоянной области во время выполнения через метод string.intern. Давайте смоделируем эту ситуацию через следующий код:
Импорт java.util.*; импортировать java.lang.*; открытый класс oomtest {public static void main (string ... args) {list <string> list = new ArrayList <string> (); while (true) {list.add (uuid.randomuuid (). }}}Мы запускаем приведенный выше код через следующую команду:
java -verbose: gc -xmn5m -xms10m -xmx10m -xx: maxpermsize = 1m -xx:+printgc oomtest
Вход после запуска показан на рисунке ниже:
Исключение в потоке "Main" java.lang.outofmemoryerror: Pertgen Space на java.lang.string.intern (нативный метод) на oomtest.main (oomtest.java:8)
Через приведенный выше код мы успешно смоделировали постоянный переполнение пула во время выполнения. Из пространства Pertgen в выводе мы видим, что постоянная полоса действительно переполнен, что также проверяет утверждение, что JVM Hotspot реализует область метода через постоянную полосу, как упоминалось ранее.
OutofmemoryError: Невозможно создать нативную ветку
Наконец, давайте посмотрим на ошибку java.lang.outofmemoryerror: невозможно создать нить Natvie. Когда это происходит, это обычно вызвано следующими двумя ситуациями:
Количество потоков, созданных программой, превышает предел операционной системы. Для систем Linux мы можем просмотреть это ограничение через Ulimit -u.
Память, выделенная на виртуальную машину, слишком велика, что приводит к слишком мало нативной памяти, требуемой при создании потоков. Мы все знаем, что операционная система имеет ограничение на память каждого процесса. При запуске JVM это эквивалентно запуску процесса. Если один из наших процессов занимает 4G памяти, то оставшаяся память, рассчитанная по следующей формуле, является памятью, которую можно использовать при создании стека потоков. Общая доступная память для стека потоков = 4G- (значение -xmx)-(-xx: значение maxpermsize)-память, занятая счетчиком программы, показана приведенной выше формулой, что чем больше значения -xmx и maxpermsize, тем меньше доступное пространство для стека потока. Когда емкость стека, настроенная параметром -XSS, остается неизменной, тем меньше количество потоков, которое может быть создано. Следовательно, если из -за этой ситуации невозможно создать нативный поток, то мы либо увеличиваем общую память, занятую процессом, либо уменьшаем -XMX или -XSS, чтобы достичь цели создания большего количества потоков.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.