문제

저자가 인터뷰 대상자에게 "JVM을 어떻게 충돌 시키십니까?" 나는 당신이 결국 모든 메모리를 사용하는 무한한 루프를 작성하여 그렇게 할 수 있다고 생각했습니다.

누구든지 어떤 생각을 가지고 있습니까?

도움이 되었습니까?

해결책

하나의 "답변"에 가장 가까운 것은 System.exit() 적절한 정리 없이 즉시 JVM을 종료합니다.하지만 그 외에도 네이티브 코드와 리소스 고갈이 가장 가능성이 높은 답입니다.또는 Sun의 버그 추적기를 통해 JVM 버전의 버그를 찾을 수 있습니다. 그 중 일부는 반복 가능한 충돌 시나리오를 허용합니다.32비트 버전에서 4Gb 메모리 제한에 접근하면 준정기적으로 충돌이 발생하곤 했습니다(현재는 일반적으로 64비트를 사용합니다).

다른 팁

OutOfMemoryError 또는 StackOverflowError를 충돌이라고 부르지는 않을 것입니다.이는 일반적인 예외일 뿐입니다.VM을 실제로 충돌시키려면 다음 세 가지 방법이 있습니다.

  1. JNI를 사용하고 네이티브 코드에서 충돌이 발생합니다.
  2. 보안 관리자가 설치되어 있지 않으면 리플렉션을 사용하여 VM을 충돌시킬 수 있습니다.이는 VM에 따라 다르지만 일반적으로 VM은 개인 필드에 기본 리소스에 대한 여러 포인터를 저장합니다(예:네이티브 스레드 개체에 대한 포인터는 다음의 긴 필드에 저장됩니다. java.lang.스레드).리플렉션을 통해 변경하면 조만간 VM이 충돌합니다.
  3. 모든 VM에는 버그가 있으므로 하나만 트리거하면 됩니다.

마지막 방법으로 Sun Hotspot VM을 조용하게 충돌시키는 간단한 예가 있습니다.

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

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

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

JNI.실제로 JNI에서는 충돌이 기본 작업 모드입니다.충돌하지 않도록 더욱 열심히 노력해야 합니다.

이것을 사용하십시오:

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:.충돌

저도 이 질문에 부딪혀 여기까지 왔습니다. 열정적인 프로그래머, 채드 파울러 지음.사본에 접근할 수 없는 사람들을 위해 질문은 "정말 훌륭한 Java 프로그래머"가 필요한 직위에 대해 인터뷰하는 후보자를 위한 일종의 필터/테스트로 구성됩니다.

구체적으로 그는 이렇게 묻습니다.

JVM(Java Virtual Machine) 충돌을 일으키는 프로그램을 순수 Java로 어떻게 작성하시겠습니까?

나는 15년 넘게 Java로 프로그래밍을 해왔지만 이 질문이 당혹스럽고 불공평하다는 것을 알았습니다.다른 사람들이 지적했듯이 관리 언어인 Java는 특별히 설계되었습니다. 충돌하지 않도록.물론 항상 JVM 버그가 있지만 다음과 같습니다.

  1. 15년 이상 프로덕션 수준 JRE를 사용한 후에는 이러한 경우가 거의 없습니다.
  2. 이러한 버그는 다음 릴리스에서 패치될 가능성이 높습니다. 그렇다면 프로그래머로서 현재 JRE 쇼 스토퍼 세트의 세부 사항을 접하고 기억할 가능성은 얼마나 됩니까?

다른 사람들이 언급했듯이 JNI를 통한 일부 기본 코드는 JRE를 충돌시키는 확실한 방법입니다.하지만 저자는 구체적으로 언급했다. 순수 자바에서, 그럼 종료되었습니다.

또 다른 옵션은 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 또는 이와 유사한 예외가 있습니다. 실제로 충돌이 아니다.

그럼 무엇이 남았나요?저자가 적절한 해결책으로 실제로 염두에 두고 있는 것이 무엇인지 듣고 싶습니다.

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

추신:그렇지 않으면 훌륭한 책입니다.Ruby를 배우면서 도덕적 지원을 위해 선택했습니다.

이 코드는 불쾌한 방식으로 JVM을 충돌시킵니다.

import sun.dc.pr.PathDasher; 

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

지난번에 내가 시도한 것은 다음과 같습니다.

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

완벽한 JVM 구현은 결코 충돌하지 않습니다.

JVM을 충돌시키려면 JNI 외에 VM 자체에서 버그를 찾아야 합니다.무한 루프는 CPU만 소모합니다.메모리를 무한히 할당하면 잘 구축된 JVM에서 OutOfMemoryError가 발생합니다.이로 인해 다른 스레드에 문제가 발생할 수 있지만 좋은 JVM은 여전히 ​​충돌하지 않아야 합니다.

VM의 소스 코드에서 버그를 발견하고 예를 들어 VM 구현의 메모리 사용량에 분할 오류를 일으키는 경우 실제로 충돌이 발생할 수 있습니다.

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

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

이는 다음으로 인해 발생합니다. 벌레 Sun JDK에서 - OpenJDK에서도 발견됩니다.이는 Oracle JDK 1.6_24부터 수정되었습니다.

충돌이 무엇을 의미하는지에 따라 다릅니다.

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

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

그 책 자바 가상 머신 Jon Meyer의 글에는 JVM이 코어 덤프를 발생시키는 일련의 바이트코드 명령의 예가 있습니다.이 책의 사본을 찾을 수 없습니다.누군가가 있다면 그것을 찾아 답변을 게시하십시오.

winxpsp2(wmp10 jre6.0_7 포함)

Desktop.open(uriToAviOrMpgFile)

이로 인해 생성된 스레드가 잡히지 않은 Throwable을 던지고 핫스팟이 충돌합니다.

YMMV

손상된 하드웨어는 모든 프로그램을 중단시킬 수 있습니다.정확히 동일한 설정으로 다른 컴퓨터에서는 잘 실행되는 동안 특정 컴퓨터에서는 재현 가능한 앱 충돌이 발생한 적이 있습니다.그 기계에 RAM 결함이 있는 것으로 밝혀졌습니다.

가장 짧은 방법 :)

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

충돌은 아니지만 사용에 대한 허용되는 답변보다 충돌에 더 가깝습니다. System.exit

다음을 호출하여 JVM을 중지할 수 있습니다.

Runtime.getRuntime().halt( status )

문서에 따르면 :-

"이 방법을 사용하면 종료 후크가 시작되지 않으며 종료 시 종료가 활성화된 경우 호출되지 않은 종료자를 실행하지 않습니다."

JVM이 코어 덤프를 발생시키는 원인에 대한 자세한 설명은 다음과 같습니다(예:충돌):http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_17534

처리되지 않은 상황(예:Java 예외 또는 오류 없음), Java 내에서 이 작업을 수행할 수 없습니다(sun.misc.Unsafe 클래스를 사용할 권한이 없는 경우).이것이 관리 코드의 핵심입니다.

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

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

Linux/Unix에서는 실행 중인 프로세스에 신호를 보내 JVM 충돌을 쉽게 만들 수 있습니다.메모:당신은 사용해서는 안됩니다 SIGSEGV 이를 위해 Hotspot은 이 신호를 포착하고 대부분의 장소에서 NullPointerException으로 다시 발생시키기 때문입니다.그래서 보내는 것이 더 좋습니다. SIGBUS 예를 들어.

메모리가 부족한 척하고 싶다면 다음을 수행할 수 있습니다.

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

나는 기본 메소드(내장된 메소드)를 호출하여 JVM이 오류 파일을 덤프하게 하는 몇 가지 방법을 알고 있지만 아마도 이를 수행하는 방법을 모르는 것이 가장 좋을 것입니다.;)

JNI는 충돌의 큰 원인입니다.C/C++로도 작성해야 하기 때문에 JVMTI 인터페이스를 사용하면 충돌이 발생할 수도 있습니다.

더 많은 스레드를 무한히 생성하는(더 많은 스레드를 생성하는) 스레드 프로세스를 생성하면 결국 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:
# 

가장 짧은가?Robot 클래스를 사용하여 Ctrl+Break를 실행합니다.콘솔을 닫지 않고 프로그램을 닫으려고 할 때 이것을 발견했습니다('종료' 기능이 없었습니다).

지금 하고 있는데 어떻게 될지 모르겠네요...:-) JVM(및 내 앱)이 때때로 완전히 사라지는 경우가 있습니다.오류가 발생하지 않고 기록된 것도 없습니다.경고 없이 즉시 작업에서 전혀 실행되지 않는 상태로 전환됩니다.

이것이 중요합니까?

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 메시지와 함께 현재 프로세스 삭제는 허용되지 않습니다..

무한 for 루프를 동일한 함수에 대한 재귀 호출로 변경하면 스택 오버플로 예외가 발생합니다.

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

public void causeStackOverflow() {
    causeStackOverflow();
}

'충돌'이 jvm/프로그램의 정상적인 종료를 방해하는 경우 처리되지 않은 예외가 이를 수행할 수 있습니다.

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에 따라 달라지나요?!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top