이전 글에서 Spring WebFlux + BlockHound 주제로 포스팅하면서 간단히 블록하운드의 동작 방식에 대해서 설명한 적이 있다.
간단히 정리하자면 블록하운드는 런타임에 실행하는 바이트코드를 후킹해서 호출하는 메소드가 블로킹 메소드인지 내부적으로 판단 후 검출하는 자바 에이전트이다.
블록하운드는 내부적으로 런타임에 네이티브 메소드를 이리저리 변경해가며 동작하는데, 이 네이티브 메소드 재정의 기능은 JDK 자체에서 지원하는 기능이다.
하지만 JDK 13 버전 부터 기본적으로 네이티브 메소드 재정의 기능을 제공하지 않는다. 그래서 직접 JVM 의 native method 재정의 기능 옵션을 설정해줘야 기능이 동작한다.
그 옵션이 바로 -XX:+AllowRedefinitionToAddDeleteMethods 인것이다.
참고로 이 옵션은 JDK 13 부터 기본적으로 꺼져있는 상태이고, Deprecated 되었다.
언제 없어질지 모르는 옵션이라서 JDK 버전을 올렸다면 해당 버전의 JDK 스펙을 체크해서 옵션이 살아 있는지 확인하는 것이 좋다.
if (!thread.blockingCallDetected) {
String message = "The instrumentation have failed.";
try {
Class.forName("sun.nio.ch.NioSocketImpl");
message = message + "\n";
message = message + "It looks like you're running on JDK 13+.\n";
message = message + "You need to add '-XX:+AllowRedefinitionToAddDeleteMethods' JVM flag.\n";
message = message + "See https://github.com/reactor/BlockHound/issues/33 for more info.";
} catch (ClassNotFoundException var4) {
}
throw new IllegalStateException(message);
}
위 코드는 실제 블록하운드에서 에러를 발생시키는 코드 중 일부를 발췌한 내용이다.
애플리케이션을 실행하는 정확한 JDK 버전을 취득할 수 없어서 인지, 현재 환경이 JDK 13+ 인지 확인하기 위해 sun.nio.ch.NioSocketImpl 클래스를 로드하는 방식으로 검증하고 있다.
NioSocketImpl 클래스는 기존의 PlainSocketImpl 을 대체하는 ServerSocket 구현체로 JDK 13 부터 추가되었기 때문에 이 방식으로 검증해도 큰 문제는 없다.
아무튼 어떤 방식이든 JVM 실행 옵션에 -XX:+AllowRedefinitionToAddDeleteMethods 를 추가하고 실행하면 더 이상 에러가 발생하지 않는다.