Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java 9에서 JShell 디버깅 모드 사용하는 방법

JShell은 코드 조각(snippet)을 클래스에 넣지 않고도 바로 실행할 수 있는 REPL(Read-Eval-Print Loop) 도구입니다. 이 도구를 사용하면 Java에서 선언문, 실행문, 표현식을 손쉽게 평가할 수 있으며, 코드의 일부를 테스트하기 위해 별도로 main() 메서드를 만들 필요가 없습니다.

JShell에는 내부 동작을 확인할 수 있는 디버깅 기능이 내장되어 있습니다. "/debug" 명령어를 입력하면 JShell 구현에 대한 디버깅 정보가 출력됩니다. 명령어를 입력하는 순간 디버깅 모드가 켜지며, 이후 간단한 덧셈이나 문자열 입력 같은 코드를 실행하면 컴파일 과정의 상세 정보가 화면에 출력됩니다.

예제 1: 숫자 연산 디버깅

jshell> /debug
| Debugging on

jshell> 5+3
Compiling: 5+3
Kind: EXPRESSION_STATEMENT -- 5 + 3;
compileAndLoad [Unit($1)]
++setCompilationInfo() Snippet:VariableKey($1)#11-5+3
package REPL;
import java.io.*;import java.math.*;import java.net.*;import java.nio.file.*;import java.util.*;
import java.util.concurrent.*;import java.util.function.*;import java.util.prefs.*;
import java.util.regex.*;import java.util.stream.*;class $JShell
$11 {
public static
int $1;
public static Object do_it$() throws Throwable {
return $1 = 5+3;
}
}

-- diags: []
setStatus() Snippet:VariableKey($1)#11-5+3 - status: VALID
compileAndLoad ins = [Unit($1)] -- legit = [Unit($1)]
Compiler generating class REPL.$JShell$11
compileAndLoad [Unit($1)] -- deps: [] success: true
recordCompilation: Snippet:VariableKey($1)#11-5+3 -- status VALID, unresolved []

$1 ==> 8

위 출력 결과를 보면, 단순한 5+3 연산 하나에도 내부적으로 임시 클래스($JShell$11)가 생성되고, 스니펫이 VARIABLE 키로 관리되며 최종 상태가 VALID로 기록되는 전체 과정을 확인할 수 있습니다. 마지막 줄의 $1 ==> 8은 연산 결과가 변수에 저장되었음을 의미합니다.

예제 2: 문자열 변수 선언 디버깅

jshell> /debug
| Debugging on

jshell> String s = "Adithya"
Compiling: String s = "Adithya";
Kind: VARIABLE -- String s = "Adithya"
compileAndLoad [Unit(s)]
++setCompilationInfo() Snippet:VariableKey(s)#12-String s = "Adithya";
package REPL;
import java.io.*;import java.math.*;import java.net.*;import java.nio.file.*;import java.util.*;
import java.util.concurrent.*;import java.util.function.*;import java.util.prefs.*;
import java.util.regex.*;import java.util.stream.*;import static REPL.$JShell$11.$1;
class $JShell$12 {
public static String s;
public static Object do_it$() throws Throwable {
String s_ =
"Adithya";
return s = s_;
}
}

-- diags: []
setStatus() Snippet:VariableKey(s)#12-String s = "Adithya"; - status: VALID
compileAndLoad ins = [Unit(s)] -- legit = [Unit(s)]
Compiler generating class REPL.$JShell$12
compileAndLoad [Unit(s)] -- deps: [] success: true
recordCompilation: Snippet:VariableKey(s)#12-String s = "Adithya"; -- status VALID, unresolved []
s ==> "Adithya"

문자열 변수 선언 역시 동일한 방식으로 처리됩니다. 새로운 임시 클래스($JShell$12)가 생성되고, 이전 세션의 변수($JShell$11.$1)가 정적 임포트되어 상태가 유지되는 것을 확인할 수 있습니다. 이처럼 JShell은 입력된 모든 스니펫을 내부 클래스로 감싸 컴파일하고 실행합니다.

디버깅 모드 끄기

디버깅 모드를 종료하려면 같은 세션에서 다시 한 번 "/debug" 명령어를 입력하면 됩니다.

jshell> /debug
| Debugging off

정리하면, /debug 명령어는 JShell이 내부적으로 어떻게 코드를 컴파일하고 로드하는지 학습하거나 문제를 진단할 때 유용한 도구입니다. 일상적인 개발 환경에서는 출력량이 많아 불편할 수 있으므로, 필요할 때만 켜고 사용 후에는 반드시 끄는 것이 좋습니다.