종료 코드는 충돌 원인이 아니라 그냥 어깨를 으쓱하는 것뿐이다
그 숫자는 아무것도 알려주지 않는다. 바로 위의 줄이 모든 것을 알려주며, 그것은 이미 로그 폴더에 들어 있다. 종료 코드 137은 충돌이 아니라 대개 메모리 부족으로 OS가 프로세스를 끝낸 것이다.
죽어버린 Java 서버는 Exit Code 1을 출력하고 멈춘다. 그게 전부다. 종료 코드 1은 "프로세스가 비정상적으로 종료됨"을 의미한다 — 이는 원인이 아니라 분류이며, 월드 폴더가 없어서부터 클래스 로딩 중에 예외를 던지는 모드까지 모든 것을 포괄한다.
진짜 답이 있는 곳
종료 코드는 게임이 아니라 런처나 호스팅 패널이 출력한다. 원인은 logs/latest.log에 있고, 충돌의 경우 서버가 crash-reports/ 아래에 저장하는 리포트에 있다. 로그 끝에서부터 거꾸로 읽어 올라가면서 첫 번째 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 | watchdog이 멈춘 틱을 죽였거나, JVM이 시작을 거부했거나, 런처나 모드 로더가 충돌을 보고함 |
| 137 | OS에 의해 종료됨, 거의 항상 OOM killer |
| 143 | SIGTERM — 컨테이너 오케스트레이터가 중지시킴 |
코드 137은 사람들이 충돌로 잘못 읽는 것이다. JVM이 실패한 게 아니라, JVM 바깥의 무언가가 그 프로세스가 메모리를 너무 많이 썼다고 판단한 것이다.
Java와 Bedrock은 같은 문제가 아니다
Bedrock의 전용 서버는 자체 로깅을 가진 다른 프로그램이며, Java 로그를 위해 쓰인 조언은 여기에 그대로 적용되지 않는다.
모드를 적용한 스택은 다르게 실패한다
모드가 있으면, 첫 번째 예외는 종종 증상일 뿐이다. mixin 적용 실패는 진짜 원인이 서른 줄 뒤의 NoSuchMethodError이 아니라 첫 번째 Mixin apply failed 줄인 연쇄 반응을 만들어낸다. Exception을 검색하기 전에 로그에서 Mixin을 검색하라.
서버가 살아 있는지 확인하기
로그는 왜 죽었는지 알려준다. 지금 살아 있는지는 알려주지 않는다. 서버 포트에 대한 상태 쿼리는 요청 한 번으로 그 답을 준다. 여기 있는 도구는 Java 서버를 확인한다; Bedrock은 UDP로 통신하므로 자체 쿼리가 필요하다.
로그를 Server Diagnostics 도구에 붙여 넣으면 실패한 줄을 뽑아낼 수 있고, 호스트를 지정하면 서버가 실제로 응답하는지 확인할 수 있다.