Graal
이라 불리는 Java JIT 컴파이러에 대해 깊이 살펴본다javac
커맨드 사용해서 Java 프로그램 컴파일 시, 이진 표현의 JVM bytecode
로 컴파일된 소스코드를 얻게 된다bytecode
는 소스코드보다 간단하고 더 간결(compact)하지만, 전통적인 프로세서는 이를 실행시킬 수 없다bytecode
를 해석해야 한다bytecode
를 프로세서가 실행할 수 있는 머신 코드로 컴파일하는 다른 컴파일러를 사용할 수 있으며, 이를 JIT(Just In Time) 컴파일러
라고 한다JIT(Just In Time) 컴파일러
는 javac
컴파일러보다 훨씬 복잡하고, 고성능의 머신 코드 생성 위해서는 복잡한 최적화를 수행한다JIT 컴파일러
에 대해 더 상세하기 보기HotSpot virtual machine
을 포함하며, 이는 두 개의 전통적인 JIT 컴파일러를 포함한다
C1
이라 불리는 클라이언트 컴파일러opto
또는 C2
라 불리는 서버 컴파일러C1
C2
javac
로 컴파일된 자바 프로그램은 bytecode
가 해석된 모드에서 실행된다C1
을 컴파일에 사용한다C2
를 사용하여 그 메서드들은 다시 한번 컴파일한다C2
는 매우, 최적화되었고 C++과 경쟁하거나 더 빠른 코드를 생산한다C2
) 자체가 C++의 특정 방언으로 작성되었다C2
는 관리하기 어려워졌고, 현재 설계로는 주요한 향상을 기대할 수 없다GraalVM
이라 명명된 새로운 JIT 컴파일러 프로젝트 생성GraalVM
GraalVM
은 오라클이 만든 리서치 프로젝트다GraalVM
을 여러 연결된 프로젝트로 볼 수 있는데
Graal
은 고성능의 JIT 컴파일러로, JVM 바이트코드를 받아서 머신 코드를 생산한다JVMCI
를 사용한-XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler
JVMCI(JVM Compiler Interface)
JVMCI
는 JDK 9부터 OpenJDK의 일부가 됐고, Graal 실행 위해 어떤 표준 OpenJDK나 오라클 JDK를 사용할 수 있다JVMCI
는 표준 계층화된 컴파일을 제외하고, 새로운 컴파일러 Graal을 JVM 변경 없이 플러그인할 수 있게 해준다Graal
이 메서드 컴파일할 때, 해당 메서드의 bytecode
를 JVMCI
에 입력(input)으로 넘긴다(byte arrays)interface JVMCICompiler {
byte[] compileMethod(byte[] bytecode);
}
compileMethod()
메서드 호출 시, CompilationRequest
오브젝트를 전달해야 한다그러면 컴파일하려는 Java 메서드를 반환하고, 그 메서드에서 우리가 원하는 정보를 찾을 수 있다
public class CountUppercase {
static final int ITERATIONS = Math.max(Integer.getInteger("iterations", 1), 1);
public static void main(String[] args) {
String sentence = String.join(" ", args);
for (int iter = 0; iter < ITERATIONS; iter++) {
if (ITERATIONS != 1) {
System.out.println("-- iteration " + (iter + 1) + " --");
}
long total = 0, start = System.currentTimeMillis(), last = start;
for (int i = 1; i < 10_000_000; i++) {
total += sentence
.chars()
.filter(Character::isUpperCase)
.count();
if (i % 1_000_000 == 0) {
long now = System.currentTimeMillis();
System.out.printf("%d (%d ms)%n", i / 1_000_000, now - last);
last = now;
}
}
System.out.printf("total: %d (%d ms)%n", total, System.currentTimeMillis() - start);
}
}
}
실행
javac CountUppercase.java
java -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler
hot
해질 때 우선 해석되어 JIT 컴파일러된다
hot
은 말 그대로 뜨거워지는, 자주 호출되는 것을 의미한다. -XX:CompileThreshold=<num>
로 설정 가능