저자가 인터뷰 대상자에게 “JVM을 어떻게 충돌 시키는가?”라는 프로그래밍 기술에 관한 책을 읽고있었습니다. 결국 모든 메모리를 사용하는 무한 for-loop를 작성하여 그렇게 할 수 있다고 생각했습니다.
누구든지 어떤 아이디어가 있습니까?
답변
단일 “응답”에 가장 가까운 것은 System.exit()
적절한 정리없이 즉시 JVM을 종료하는 것입니다. 그러나 그 외에도 네이티브 코드와 리소스 소모가 가장 가능성이 높은 답변입니다. 또는 JVM 버전에서 버그를 Sun의 버그 추적기에서 찾아 볼 수 있습니다.이 중 일부는 반복 가능한 충돌 시나리오를 허용합니다. 우리는 32 비트 버전에서 4Gb 메모리 제한에 접근 할 때 반 정기 충돌을 겪었습니다 (일반적으로 64 비트를 사용합니다).
답변
OutOfMemoryError 또는 StackOverflowError에 충돌을 발생시키는 호출을하지 않습니다. 이것들은 단지 일반적인 예외입니다. VM을 실제로 크래시하려면 다음 세 가지 방법이 있습니다.
- 기본 코드에서 JNI를 사용하여 충돌하십시오.
- 보안 관리자가 설치되어 있지 않으면 리플렉션을 사용하여 VM을 중단 할 수 있습니다. 이것은 VM마다 다르지만 일반적으로 VM은 기본 리소스에 대한 많은 포인터를 개인 필드에 저장합니다 (예 : 기본 스레드 객체에 대한 포인터는 java.lang.Thread 의 긴 필드에 저장 됨 ). 리플렉션을 통해 변경하면 VM이 조만간 충돌합니다.
- 모든 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 :. 크래시
답변
Chad Fowler의 The Passionate Programmer 에서도이 질문에 부딪 쳤기 때문에 여기에 왔습니다 . 사본에 접근 할 수없는 사람들을 위해, 질문은 “정말로 훌륭한 자바 프로그래머”가 필요한 입장을 인터뷰하는 응시자들을위한 일종의 필터 / 테스트로 구성됩니다.
특히 그는 묻습니다.
순수 Java로 Java Virtual Machine이 충돌하는 프로그램을 어떻게 작성 하시겠습니까?
저는 15 년 이상 Java로 프로그래밍했으며이 질문은 당혹스럽고 불공평 한 것으로 나타났습니다. 다른 사람들이 지적했듯이 관리되는 언어 인 Java는 특별히 충돌하지 않도록 설계되었습니다 . 물론 JVM 버그는 항상 있지만
- 프로덕션 레벨 JRE가 15 년 이상 지난 후에는 드물다.
- 이러한 버그는 다음 릴리스에서 패치 될 가능성이 있으므로 프로그래머가 현재 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 가 여기에 응답했습니다 .
추신 : 그것은 다른 위대한 책입니다. 루비를 배우면서 도덕적 지원을 받기 위해 그것을 선택했습니다.
답변
이 코드는 불쾌한 방식으로 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