종료 코드는 충돌 원인이 아니라 그냥 어깨를 으쓱하는 신호일 뿐
그 숫자는 아무것도 알려주지 않습니다. 바로 위의 줄이 모든 것을 알려주며, 그것은 이미 로그 폴더에 있습니다.
죽어버린 Java 서버는 Exit Code 1를 출력하고 멈춥니다. 그게 전부입니다. 종료 코드 1은 "프로세스가 비정상적으로 종료됨"을 의미합니다. 이는 원인이 아니라 분류일 뿐이며, 월드 폴더 누락부터 클래스 로딩 중 예외를 던지는 모드까지 모든 것을 포괄합니다.
진짜 답이 있는 곳
종료 코드는 logs/latest.log의 마지막 줄입니다. 원인은 그 앞의 줄들에 있습니다. 끝에서부터 거꾸로 읽어 올라가면서 첫 번째 Exception, Caused by:, Failed to를 찾으세요. 그 줄이 클래스, 모드, 또는 파일의 이름을 알려줍니다.
[Server thread/ERROR]: Encountered an unexpected exception
java.lang.NoSuchMethodError: net.minecraft.world.level.Level.getBiome
at com.example.mod.ExampleMixin.inject(ExampleMixin.java:41)
Caused by: java.lang.NoClassDefFoundError: com/example/lib/Helper
여기서 NoClassDefFoundError는 월드 손상이 아니라 누락된 의존성입니다. 종료 코드는 그중 아무것도 알려주지 않았습니다.
실제로 보게 되는 종료 코드
| 코드 | 일반적인 의미 |
|---|---|
| 0 | 정상 종료 — /stop 또는 예약된 재시작 |
| 1 | 처리되지 않은 예외, 또는 JVM이 시작을 거부함 |
| 137 | OS에 의해 종료됨, 거의 항상 OOM killer |
| 143 | SIGTERM — 컨테이너 오케스트레이터가 중지시킴 |
사람들이 충돌로 잘못 읽는 것이 바로 코드 137입니다. JVM이 실패한 게 아니라, 외부의 무언가가 프로세스가 메모리를 너무 많이 썼다고 판단한 것입니다.
Java와 Bedrock은 같은 문제가 아닙니다
Bedrock의 서버는 bedrock_server.log를 기록하며 Java 스타일의 종료 코드를 전혀 내보내지 않습니다. 대신 스택 트레이스와 Crash report 줄이 포함된 크래시 핸들러 보고서를 덤프합니다. Java 로그를 기준으로 쓰인 조언은 여기에 그대로 적용되지 않습니다.
모드를 적용한 스택은 다르게 실패합니다
모드가 있으면 첫 번째 예외는 종종 증상일 뿐입니다. mixin 적용 실패는 연쇄 반응을 일으키는데, 진짜 원인은 30줄 뒤의 NoSuchMethodError가 아니라 첫 번째 Mixin apply failed 줄입니다. Exception를 검색하기 전에 로그에서 Mixin를 먼저 검색하세요.
서버가 살아 있는지 확인하기
로그는 왜 죽었는지 알려줍니다. 지금 살아 있는지는 알려주지 않습니다. 서버 포트에 대한 TCP 검사는 요청 한 번으로 그 답을 주며, Java와 Bedrock 모두 소켓으로 통신하기 때문에 동일하게 작동합니다.
로그를 Server Diagnostics 도구에 붙여 넣으면 실패한 줄을 추출할 수 있고, 호스트를 지정하면 서버가 실제로 응답하는지 확인할 수 있습니다.