it-swarm-ko.tech

JVM을 어떻게 중단합니까?

저자가 인터뷰 대상자에게 "JVM을 어떻게 충돌 시키는가?"라고 묻는 프로그래밍 기술에 관한 책을 읽고있었습니다. 결국 모든 메모리를 사용하는 무한 for-loop를 작성하여 그렇게 할 수 있다고 생각했습니다.

누구든지 어떤 아이디어가 있습니까?

141
Shivasubramanian A

하나의 "답변"에 가장 가까운 것은 System.exit()입니다. 이것은 올바른 정리없이 즉시 JVM을 종료합니다. 그러나 그 외에도 네이티브 코드와 리소스 소모가 가장 가능성이 높은 답변입니다. 또는 Sun의 버그 추적기에서 JVM 버전의 버그를 찾아 볼 수 있습니다.이 중 일부는 반복 가능한 충돌 시나리오를 허용합니다. 우리는 32 비트 버전에서 4Gb 메모리 제한에 접근 할 때 반 정기 충돌을 일으켰습니다 (일반적으로 64 비트를 사용합니다).

6
Leigh Caldwell

OutOfMemoryError 또는 StackOverflowError에 충돌을 발생시키는 호출을하지 않습니다. 이것들은 단지 일반적인 예외입니다. 실제로 VM을 충돌시키는 3 가지 방법이 있습니다 :

  1. 기본 코드에서 JNI를 사용하여 충돌하십시오.
  2. 보안 관리자가 설치되어 있지 않으면 리플렉션을 사용하여 VM을 중단 할 수 있습니다. 이것은 VM 특정 적이지만 일반적으로 VM은 개인 리소스에 네이티브 리소스에 대한 많은 포인터를 저장합니다 (예 : 네이티브 스레드 객체에 대한 포인터는 Java.lang.Thread)의 긴 필드입니다. 반사를 통해 변경하면 VM 조만간 충돌합니다.
  3. 모든 VM에는 버그가 있으므로 하나만 트리거하면됩니다.

마지막 방법으로 간단한 예를 들었습니다. Sun Hotspot VM quiet) :

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

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

이로 인해 GC에서 스택 오버플로가 발생하므로 StackOverflowError가 발생하지 않지만 hs_err * 파일을 포함하여 실제 충돌이 발생합니다.

172
ralfs

JNI . 실제로 JNI의 경우 충돌이 기본 작동 모드입니다. 충돌하지 않도록 더 열심히 노력해야합니다.

123
Dan Dyer

이것을 사용하십시오 :

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 :. 크래시

56
Dave Griffiths

Chad Fowler의 The Passionate Programmer 에서이 질문에 부딪 쳤기 때문에 여기에 왔습니다. 사본에 접근 할 수없는 사람들을 위해, 질문은 "정말로 좋은 Java 프로그래머")가 필요한 입장에 대해 인터뷰하는 후보자를위한 일종의 필터/테스트로 구성됩니다.

특히 그는 묻습니다.

순수 Java로 프로그램을 작성하여 Java 가상 머신이 중단되는 원인은 무엇입니까?)

저는 15 년 이상 Java에서 프로그래밍했으며이 질문은 당혹스럽고 불공평 한 것으로 나타났습니다. 다른 사람들이 지적했듯이 Java는 관리되는 언어로서 특별히 충돌하지 마라. 물론 JVM 버그는 항상 있지만

  1. 프로덕션 레벨 JRE가 15 년 이상 지난 후에는 드물다.
  2. 이러한 버그는 다음 릴리스에서 패치 될 가능성이 있으므로 프로그래머가 현재 JRE 쇼 스토퍼 세트의 세부 사항을 실행하고 기억할 가능성은 얼마나됩니까?

다른 사람들이 언급했듯이 JNI를 통한 일부 네이티브 코드는 JRE를 충돌시키는 확실한 방법입니다. 그러나 저자는 구체적으로 in pure 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 또는 이와 유사한 예외로 종료됩니다. 다시 실제로 크래시가 아닙니다.

남은 것은 무엇입니까? 저자가 실제로 올바른 솔루션으로 생각한 것을 듣고 싶습니다.

업데이트 : 채드 파울러 여기에 응답 .

추신 : 그것은 다른 위대한 책입니다. 루비를 배우면서 도덕적 지원을 받기 위해 그것을 선택했습니다.

32
George Armhold

이 코드는 불쾌한 방식으로 JVM을 중단시킵니다

import Sun.dc.pr.PathDasher; 

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

내가 마지막으로 시도했을 때 그것을 할 것입니다 :

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
17
Hot Licks

완벽한 JVM 구현은 결코 중단되지 않습니다.

JVM을 크래시하려면 JNI를 제외하고 VM 자체에서 버그를 찾아야합니다. 무한 루프는 CPU 만 소모합니다. 아마도 다른 스레드에 문제가 발생할 수 있지만 양호한 JVM은 여전히 ​​충돌하지 않아야합니다.

VM의 소스 코드에서 버그를 발견하고 예를 들어 VM 구현의 메모리 사용에 세분화 오류가 발생하면 실제로 충돌 할 수 있습니다.

15
Dave L.

JVM을 중단하려면 Sun JDK 1.6_23 이하에서 다음을 사용하십시오.

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

이것은 Sun JDK의 bug 때문입니다. OpenJDK에도 있습니다. 이것은 Oracle JDK 1.6_24부터 수정되었습니다.

14

충돌의 의미에 따라 다릅니다.

스택 공간이 부족해 지도록 무한 재귀를 수행 할 수 있지만 "정상적으로"충돌합니다. 예외가 발생하지만 JVM 자체가 모든 것을 처리합니다.

JNI를 사용하여 기본 코드를 호출 할 수도 있습니다. 제대로하지 않으면 충돌을 일으킬 수 있습니다. 이러한 충돌을 디버깅하는 것은 "재미"입니다 (믿습니다. 서명 된 DLL 애플릿)에서 호출하는 큰 C++ Java을 작성해야했습니다. :)

10
Herms

Jon Meyer의 Java Virtual Machine 책에는 JVM이 코어 덤프되도록하는 일련의 바이트 코드 명령에 대한 예제가 있습니다. 이 책의 사본을 찾을 수 없습니다. 누군가가 있다면 그것을 찾아서 답을 게시하십시오.

6
Soulfly

손상된 하드웨어는 모든 프로그램과 충돌 할 수 있습니다. 한 번만 특정 컴퓨터에서 앱 충돌이 발생하면서 동일한 설정으로 다른 컴퓨터에서 정상적으로 실행되었습니다. 머신에 RAM에 결함이 있음을 나타냅니다.

5

가장 짧은 방법 :)

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

winxpsp2에서 wmp10으로 jre6.0_7

Desktop.open (uriToAviOrMpgFile)

이로 인해 스폰 된 스레드가 catch되지 않은 Throwable을 발생시키고 핫스팟이 충돌합니다.

YMMV

5
kitsuneymg

처리되지 않은 상황 (예 : Java 예외 또는 오류) 때문에 프로세스 중단으로 충돌을 정의하면 Java (Sun.misc.Unsafe 클래스를 사용할 권한이없는 경우) 관리되는 코드의 핵심입니다.

네이티브 코드의 일반적인 충돌은 잘못된 메모리 영역 (널 주소 또는 정렬 오류)에 대한 포인터를 역 참조함으로써 발생합니다. 다른 소스는 잘못된 기계 명령어 (opcode) 또는 라이브러리 또는 커널 호출에서 처리되지 않은 신호일 수 있습니다. JVM 또는 시스템 라이브러리에 버그가있는 경우 둘 다 트리거 될 수 있습니다.

예를 들어, JITed (생성 된) 코드, 고유 메소드 또는 시스템 호출 (그래픽 드라이버)은 실제 충돌로 이어질 수 있습니다 (Zip 함수를 사용하고 메모리가 부족할 때 충돌이 발생하는 것이 일반적 임). 이러한 경우 JVM의 크래시 핸들러가 시작되어 상태를 덤프합니다. 또한 OS 코어 파일 (Windows의 Dr. Watson 및 * nix의 코어 덤프)을 생성 할 수 있습니다.

Linux/Unix에서는 실행중인 프로세스에 신호를 보내 JVM 충돌을 쉽게 일으킬 수 있습니다. 참고 : 핫스팟은이 신호를 잡아서 대부분의 장소에서 NullPointerException으로 다시 던지기 때문에 SIGSEGV를 사용하면 안됩니다. 따라서 예를 들어 SIGBUS를 보내는 것이 좋습니다.

4
eckes

다음은 JVM에서 코어 덤프를 유발하는 원인 (예 : 충돌)에 대한 자세한 설명입니다. http://kb.Adobe.com/selfservice/viewContent.do?externalId=tn_17534

4
COTOHA

당신은 당신이 할 수있는 메모리가 부족한 척하려는 경우

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

네이티브 메소드 (내장 메소드)를 호출하여 JVM이 오류 파일을 덤프하게하는 몇 가지 방법을 알고 있지만 아마도이 방법을 모르는 것이 가장 좋습니다. ;)

3
Peter Lawrey

JNI는 큰 충돌 원인입니다. JVMTI 인터페이스를 사용하여 C/C++로 작성해야하므로 충돌 할 수도 있습니다.

3
Jared

더 많은 스레드를 생성하는 스레드 프로세스를 만들면 (더 많은 스레드를 생성하는 등) 결국 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:
# 
2
Lightfire228

최단? 로봇 클래스를 사용하여 CTRL + BREAK를 트리거합니다. 콘솔을 닫지 않고 프로그램을 닫으려고 할 때 이것을 발견했습니다 ( '종료'기능이 없음).

1
user6022288

나는 지금하고 있지만, 어떻게 ... :-) JVM (및 내 응용 프로그램)이 때로는 완전히 사라지는지를 완전히 확신하지는 못합니다. 오류가 발생하지 않았으며 아무것도 기록되지 않았습니다. 경고없이 즉시 작동하지 않고 전혀 작동하지 않습니다.

0
Brian Knoblauch

"충돌"이라는 말이 갑자기 중단 된 JVM을 의미한다면 예를 들어, JVM이 hs_err_pid % p.log에 쓰도록하는, 이런 식으로 할 수 있습니다.

-Xmx arg를 작은 ​​값으로 설정하고 메모리 부족으로 인해 충돌이 발생하도록 JVM에 지시하십시오.

 -Xmx10m -XX:+CrashOnOutOfMemoryError

분명히 위의 두 번째 인수가 없으면 OutOfMemoryError와 함께 jvm terminating이 발생하지만 jvm이 "충돌"되거나 갑자기 중단되지는 않습니다.

이 기술은 JVM -XX : ErrorFile arg를 테스트 할 때 도움이되었으며, 이러한 hs_err_pid 로그를 작성해야하는 위치를 제어합니다. 그런 충돌을 일으키는 방법을 찾으려고 노력 하면서이 게시물을 찾았습니다. 나중에 위의 내용이 내 필요에 가장 쉬운 것으로 밝혀지면 여기에 목록에 추가하고 싶었습니다.

마지막으로, FWIW, 누군가가 이미 args에 -Xms 값을 설정했을 때 이것을 테스트 할 수 있다면 (위보다 더 큰 값으로), 제거하거나 변경하고 싶거나 충돌하지 않고 단순히 "초기 힙 크기가 최대 힙 크기보다 큰 값으로 설정 됨"을보고하는 jvm 시작 실패 (일부 앱 서버와 같은 서비스로 JVM을 실행하는 경우 분명하지 않습니다. 다시 한 번 말하지만 공유하고 싶었습니다.)

0
charlie arehart

이 계산입니까?

long pid = ProcessHandle.current().pid();
try { Runtime.getRuntime().exec("kill -9 "+pid); } catch (Exception e) {}

Linux 및 Java 9에서만 작동합니다.

어떤 이유로 나는 얻지 못합니다. ProcessHandle.current().destroyForcibly();은 JVM을 죽이지 않고 현재 프로세스의 파괴는 허용되지 않음 메시지와 함께 Java.lang.IllegalStateException를 던집니다.

0
mszmurlo