2008-09-15 3 views
114

Я читал книгу о навыках программирования, в которой автор спрашивает собеседника: «Как вы врежете JVM?» Я думал, что вы можете сделать это, написав бесконечный цикл for, который в конечном итоге будет использовать всю память.Как вы разбиваете JVM?

У кого-нибудь есть идеи?

+16

Страстный программист, да, отличная книга;) – dolzenko 2011-12-08 19:48:00

+1

Возможный superset of: http://stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java – 2015-03-18 13:13:56

+0

https://stackoverflow.com/questions/30072883/java-swing-jwindow-application-crash «Если я использую JDK1.8_40 или новее (Oracle или OpenJDK сделайте то же самое), следующий код вместе с изменением размера диалогового окна приведет к сбою приложения (попробовал Windows 7, x64, 64-битный JDK) ». Код составляет всего 40 строк, и это приводит к * правильному сбою * JVM. – 2016-01-06 11:09:35

ответ

6

Ближе всего к одному «ответ» является System.exit() который немедленно прекращает работу JVM без надлежащей очистки. Но кроме этого, наиболее вероятным ответом являются нативный код и исчерпание ресурсов. В качестве альтернативы вы можете смотреть на отслеживание ошибок Sun на ошибки в вашей версии JVM, некоторые из которых позволяют использовать повторяющиеся сценарии сбоя. Раньше мы получали полурегулярные сбои при приближении к пределу памяти 4 Гб в 32-битных версиях (обычно мы используем 64-битные версии).

+59

без надлежащей очистки? ты уверен? В документации говорится: «Завершает работу текущей виртуальной машины Java, инициировав ее последовательность выключения ... все запущенные крючки завершения работы, если они есть, запущены ... все неинвинированные финализаторы запускаются» - разве это не правильная очистка? – 2009-04-29 13:10:13

+46

Это не сбой JVM, он целенаправленно и явно начинает упорядоченное закрытие исполнения. – BenM 2010-05-17 14:04:42

+8

Ближе к сбою jvm - Runtime.getRuntime(). halt (status). В соответствии с документами «этот метод не запускает крючки остановки, которые нужно запустить, и не запускает неинвинированные финализаторы, если включен финализация при выходе». Все еще не крушение, но ближе, чем System.exit. – henry 2012-04-18 12:01:32

114

JNI. Фактически, с JNI сбой - это режим работы по умолчанию. Вы должны усердно работать, чтобы он не разбился.

+49

+1 «с JNI, сбой - это режим работы по умолчанию« Отлично, и это очень верно! – 2009-09-04 10:42:23

+5

* Bigbadaboom * !! – 2009-10-30 13:42:48

+2

Возможно, дизайнеры JNI слышали о [программном обеспечении только для краш-тестов] (http://en.wikipedia.org/wiki/Crash-only_software), но не совсем поняли эту идею. – 2012-08-31 20:56:06

9

Зависит от того, что вы подразумеваете под авариями.

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

Вы также можете использовать JNI для вызова собственного кода. Если вы не сделаете это прямо сейчас, вы можете заставить его крушить. Отладка этих сбоев «весело» (поверьте мне, мне пришлось написать большую C++ DLL, которую мы вызываем из подписанного java-апплета). :)

-1

Если вы изменяете, что бесконечное цикл для рекурсивного вызова к одной и той же функции, то вы получите исключение переполнения стека:

public static void main(String[] args) { 
    causeStackOverflow(); 
} 

public void causeStackOverflow() { 
    causeStackOverflow(); 
} 
12

Идеальная реализация JVM никогда не сбой.

Чтобы свернуть JVM, помимо JNI, вам нужно найти ошибку в самой виртуальной машине. Бесконечный цикл просто потребляет процессор. Бесконечно распределяющая память должна просто вызывать OutOfMemoryError в хорошо построенной JVM. Это, вероятно, вызовет проблемы для других потоков, но хорошая JVM по-прежнему не должна терпеть крах.

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

5

В книге Java Virtual Machine от Jon Meyer приведен пример последовательности инструкций байткода, которые вызвали JVM к дампу ядра. Я не могу найти свою копию этой книги. Если кто-нибудь там есть, пожалуйста, найдите его и отправьте ответ.

157

Я бы не назвал выброс OutOfMemoryError или StackOverflowError сбоем. Это просто нормальные исключения. Чтобы действительно свернуть виртуальную машину, есть 3 способа:

  1. Используйте JNI и выполните сбой в собственном коде.
  2. Если менеджер безопасности не установлен, вы можете использовать отражение для сбоя виртуальной машины. Это VM специфично, но обычно VM хранит кучу указателей на собственные ресурсы в частных полях (например, указатель на собственный объект потока хранится в длинном поле в java.lang.Thread). Просто измените их с помощью отражения, и VM рано или поздно рухнет.
  3. Все виртуальные машины имеют ошибки, поэтому вам просто нужно вызвать один.

Для последнего метода у меня есть небольшой пример, который будет врезаться в тихом ВС Hotspot VM красиво:

public class Crash { 
    public static void main(String[] args) { 
     Object[] o = null; 

     while (true) { 
      o = new Object[] {o}; 
     } 
    } 
} 

Это приводит к переполнению стека в GC, так что вы не получите StackOverflowError, но в реальный сбой, включая файл hs_err *.

+8

звучит как очень разбитой GC ... – leppie 2008-09-30 09:04:42

+7

Ничего себе! Это приводит к сбоям Sun Java 5, Sun Java 6 и OpenJDK 6 (на Ubuntu 9.04) без файла hs_err *, а только «Ошибка сегментации!». ... – 2009-09-04 10:25:12

+0

System.exit() - это гораздо более простой способ свернуть JVM (если не установлен диспетчер безопасности) – instantsetsuna 2010-08-18 05:05:03

4

Если вы определили сбой как процесс прерывания из-за необработанной ситуации (то есть без исключения или ошибки Java), то это невозможно сделать изнутри Java (если у вас нет разрешения использовать класс sun.misc.Unsafe). Это целая точка управляемого кода.

Типичные сбои в собственном коде происходят путем удаления указателей на неправильные области памяти (нулевой адрес или пропускная способность). Другим источником могут быть незаконные машинные инструкции (коды операций) или необработанные сигналы из вызовов библиотеки или ядра. Оба могут запускаться, если JVM или системные библиотеки имеют ошибки.

Например, код JITed (сгенерированный), собственные методы или системные вызовы (графический драйвер) могут иметь проблемы, приводящие к реальным сбоям (довольно часто возникали сбои при использовании функций ZIP, и у них не хватало памяти). В этих случаях обработчик сбоев JVM запускает и сбрасывает состояние. Он также может генерировать основной файл ОС (Dr. Watson на Windows и core dump on * nix).

В Linux/Unix вы можете легко сделать JVM-крах, отправив ему сигнал на текущий процесс. Примечание: вы не должны использовать для этого SIGSEGV, так как Hotspot ловит этот сигнал и перебрасывает его как исключение NullPointerException в большинстве мест. Поэтому лучше отправить SIGBUS, например.

5

на winxpsp2 ж/WMP10 jre6.0_7

Desktop.open (uriToAviOrMpgFile)

Это вызывает порождал нить бросить неперехваченное Throwable и аварий HotSpot

YMMV

0

Я делаю это сейчас, но не совсем уверен, как ... :-) JVM (и мое приложение) иногда просто полностью исчезают. Ошибок не было, ничего не записано. Переход от работы к немедленному запуску без предупреждения.

3

Если вы хотите сделать вид, вы бежите из памяти вы можете сделать

public static void main(String[] args) { 
    throw new OutOfmemoryError(); 
} 

Я знаю пару способа вызвать JVM дамп файл ошибок, вызвав собственные методы (те, которые построены в) , но, скорее всего, вы не знаете, как это сделать. ;)

3

JNI - большой источник аварий. Вы также можете сбой с использованием интерфейса JVMTI, так как это также должно быть написано на C/C++.

5

Сломанные аппаратные средства могут вывести из строя любую программу. У меня когда-то был случайный сбой приложения на конкретной машине, когда он работал нормально на других машинах с одинаковой настройкой. Оказывается, у машины была неисправная оперативная память.

49

Используйте это:

import sun.misc.Unsafe; 

public class Crash { 
    private static final Unsafe unsafe = Unsafe.getUnsafe(); 
    public static void crash() { 
     unsafe.putAddress(0, 0); 
    } 
    public static void main(String[] args) { 
     crash(); 
    } 
} 

Этот класс должен быть на загрузочном классам, поскольку он использует доверенный код, так работать, как это:

java -Xbootclasspath/p:. Crash

18

Этот код будет врезаться виртуальная машина в противных способами

import sun.dc.pr.PathDasher; 

public class Crash 
{ 
    public static void main(String[] args) 
    {  
     PathDasher dasher = new PathDasher(null) ; 
    } 
} 
8

Если вы хотите врезаться JVM - используйте следующее в Sun JDK 1.6_23 или ниже:

Double.parseDouble("2.2250738585072012e-308"); 

Это связано с bug в Sun JDK - также найдено в OpenJDK. Это исправлено с Oracle JDK 1.6_24 и далее.

28

Я пришел сюда, потому что я также столкнулся с этим вопросом в The Passionate Programmer, Чадом Фаулером. Для тех, кто не имеет доступа к копии, вопрос оформляется как своего рода фильтр/тест для кандидатов, которые берут интервью для позиции, требующей «действительно хороших Java-программистов».

В частности, он спрашивает:

How would you write a program, in pure Java, that would cause the Java Virtual Machine to crash?

Я запрограммирован на Java более 15 лет, и я нашел этот вопрос, чтобы быть как загадочно и несправедливо. Как указывали другие, Java, как управляемый язык, специально разработан , чтобы не разбивать. Конечно, всегда есть ошибки JVM, но:

  1. После 15 лет работы на JRE-уровне производства это редкость.
  2. Любые такие ошибки, скорее всего, будут исправлены в следующей версии, так как, вероятно, вы, как программист, можете запустить и вспомнить детали текущего набора шоу-стопов JRE?

Как уже упоминалось, некоторый собственный код через JNI - это верный способ разрушить JRE. Но автор специально упомянул в чистой Java, так что это не так.

Другим вариантом будет подача байт-кодов JRE; это достаточно легко сбросить несколько мусорных двоичных данных в файл .class, и попросить JRE запустить его:

$ echo 'crap crap crap' > crap.class 
$ java crap 
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1668440432 in class file crap 

ли это считать? Я имею в виду, что сам JRE не разбился; он правильно обнаружил фиктивный код, сообщил об этом и вышел.

Это оставляет нам самые очевидные виды решений, таких как продувка стека через рекурсию, выход из памяти кучи через выделение объектов или просто бросание RuntimeException. Но это просто приводит к тому, что JRE выходит с StackOverflowError или аналогичным исключением, которое, опять же, на самом деле не является крахом.

Итак, что осталось? Мне очень хотелось бы услышать, что автор действительно имел в виду как правильное решение.

Обновление: Chad Fowler responded here.

PS: это отличная книга. Я взял его за моральную поддержку, изучая Руби.

4

кратчайший возможный путь :)

public class Crash 
{ 
    public static void main(String[] args) 
    { 
     main(args); 
    } 
} 
14

Последний раз, когда я попытался это сделал бы это:

public class Recur { 
    public static void main(String[] argv) { 
     try { 
      recur(); 
     } 
     catch (Error e) { 
      System.out.println(e.toString()); 
     } 
     System.out.println("Ended normally"); 
    } 
    static void recur() { 
     Object[] o = null; 
     try { 
      while(true) { 
       Object[] newO = new Object[1]; 
       newO[0] = o; 
       o = newO; 
      } 
     } 
     finally { 
      recur(); 
     } 
    } 
} 

Первая часть сгенерированного файла журнала:

# 
# An unexpected error has been detected by Java Runtime Environment: 
# 
# EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x000000006dad5c3d, pid=6752, tid=1996 
# 
# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.2-b01 mixed mode windows-amd64) 
# Problematic frame: 
# V [jvm.dll+0x2e5c3d] 
# 
# If you would like to submit a bug report, please visit: 
# http://java.sun.com/webapps/bugreport/crash.jsp 
# 

--------------- T H R E A D --------------- 

Current thread (0x00000000014c6000): VMThread [stack: 0x0000000049810000,0x0000000049910000] [id=1996] 

siginfo: ExceptionCode=0xc00000fd, ExceptionInformation=0x0000000000000001 0x0000000049813fe8 

Registers: 
EAX=0x000000006dc83090, EBX=0x000000003680f400, ECX=0x0000000005d40ce8, EDX=0x000000003680f400 
ESP=0x0000000049813ff0, EBP=0x00000000013f2df0, ESI=0x00000000013f0e40, EDI=0x000000003680f400 
EIP=0x000000006dad5c3d, EFLAGS=0x0000000000010206 
0

Если в «Крушения '- это что-то, что прерывает jvm/program от обычного завершения, тогда исключение Un-Handled могло бы сделать это.

public static void main(String args[]){ 
    int i = 1/0; 
    System.out.print(i); // This part will not be executed due to above unhandled exception 
    } 

Итак, это зависит от того, какой тип CRASH?!

4

Не аварии, но ближе к аварии, чем принятый ответ использования System.exit

Вы можете остановить JVM по телефону

Runtime.getRuntime().halt(status)

Согласно документации: -

"this method does not cause shutdown hooks to be started and does not run uninvoked finalizers if finalization-on-exit has been enabled".

0

Кратчайшие? Используйте класс Robot для запуска CTRL + BREAK. Я заметил это, когда пытался закрыть свою программу без закрытия консоли (у нее не было функции «выхода»).

0

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

public class Crash { 
    public static void main(String[] args) { 

     Runnable[] arr = new Runnable[1]; 
     arr[0] =() -> { 

      while (true) { 
       new Thread(arr[0]).start(); 
      } 
     }; 

     arr[0].run(); 
    } 
} 

Это дало мне выход (через 5 минут, следите за своим барана)

An unrecoverable stack overflow has occurred. 
# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x0000000070e53ed7, pid=12840, tid=0x0000000000101078 
# 
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01) 
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode windows-amd64 compressed oops) 
# Problematic frame: 
#