Skip to Content
Suffering builds character
아카이브10.Java설치 & 설정3. JDK에 포함된 JRE를 통해 프로그램 실행하기

3. JDK에 포함된 JRE를 통해 프로그램 실행하기

1. Java 프로그램 실행하기

자바 언어로 작성된 .java 확장자를 가진 파일을 실행하기 위한 단계는 다음과 같음

Step 1, 소스 코드

인간이 쉽게 이해하고 작성할 수 있는 자연어
컴파일러를 통해 컴파일 과정을 거쳐 바이트 코드로 변환됨

Hello.java
System.out.println();

Step 2, 바이트 코드

소프트웨어(JVM)가 이해할 수 있는 반 기계어(half)

Hello.class
0: getstatic..

Step 3, 기계어

하드웨어(CPU core)가 이해할 수 있는 완전한 형태의 기계어

text
0101011..

2. 세부 실행 단계

1번에서 설명된 Java 프로그램의 세부 실행 단계는 다음과 같음

2-1. 작성한 소스 코드를 컴파일하기

컴파일이란 자바 언어로 작성된 소스 코드를 바이트 코드로 변환하는 과정
→ 변환된 바이트 코드는 자바 가상 머신인 JVM이 이해하고 실행할 수 있는 코드로 활용됨

이러한 컴파일은 자바 컴파일러인 javac.exe를 통해 수행할 수 있음

💡
Tip

javac 명령어
.java 파일을 JVM이 실행할 수 있는 .class 파일로 변환을 수행하는 명령어
→ javac.exe 파일을 통해 동작함

Hello.java 파일 컴파일하기

terminal
javac Hello.java // 자바씨~ 컴파일 해줘

정리하면, 자바 언어로 작성된 하나의 프로그램을 실행하기 위해서는 먼저 컴파일 과정을 거쳐야 함

2-2. 컴파일된 바이트 코드 확인하기

컴파일된 바이트 코드는 바이너리 형태이기 때문에 일반 텍스트 에디터나 메모장을 통해 확인이 어려움

간단한 Linux/MacOS 명령어를 통해 확인

terminal
xxd Hello.class # xxd: .class 파일을 Hex(16진수) 형태로 출력 # 실행 결과 00000000: cafe babe 0000 003d 001d 0a00 0200 0307 .......=........ 00000010: 0004 0c00 0500 0601 0010 6a61 7661 2f6c ..........java/l 00000020: 616e 672f 4f62 6a65 6374 0100 063c 696e ang/Object...<in 00000030: 6974 3e01 0003 2829 5609 0008 0009 0700 it>...()V....... 00000040: 0a0c 000b 000c 0100 106a 6176 612f 6c61 .........java/la 00000050: 6e67 2f53 7973 7465 6d01 0003 6f75 7401 ng/System...out. 00000060: 0015 4c6a 6176 612f 696f 2f50 7269 6e74 ..Ljava/io/Print 00000070: 5374 7265 616d 3b08 000e 0100 0b48 656c Stream;......Hel 00000080: 6c6f 2057 6f72 6c64 0a00 1000 1107 0012 lo World........ 00000090: 0c00 1300 1401 0013 6a61 7661 2f69 6f2f ........java/io/ 000000a0: 5072 696e 7453 7472 6561 6d01 0007 7072 PrintStream...pr 000000b0: 696e 746c 6e01 0015 284c 6a61 7661 2f6c intln...(Ljava/l 000000c0: 616e 672f 5374 7269 6e67 3b29 5607 0016 ang/String;)V... 000000d0: 0100 0548 656c 6c6f 0100 0443 6f64 6501 ...Hello...Code. 000000e0: 000f 4c69 6e65 4e75 6d62 6572 5461 626c ..LineNumberTabl 000000f0: 6501 0004 6d61 696e 0100 1628 5b4c 6a61 e...main...([Lja 00000100: 7661 2f6c 616e 672f 5374 7269 6e67 3b29 va/lang/String;) 00000110: 5601 000a 536f 7572 6365 4669 6c65 0100 V...SourceFile.. 00000120: 0a48 656c 6c6f 2e6a 6176 6100 2100 1500 .Hello.java.!... 00000130: 0200 0000 0000 0200 0100 0500 0600 0100 ................ 00000140: 1700 0000 1d00 0100 0100 0000 052a b700 .............*.. 00000150: 01b1 0000 0001 0018 0000 0006 0001 0000 ................ 00000160: 0001 0009 0019 001a 0001 0017 0000 0025 ...............% 00000170: 0002 0001 0000 0009 b200 0712 0db6 000f ................ 00000180: b100 0000 0100 1800 0000 0a00 0200 0000 ................ 00000190: 0300 0800 0400 0100 1b00 0000 0200 1c ...............

2-3. 바이트 코드를 이해할 수 있는 형태로 변환하기

컴파일된 결과인 바이트 코드를 다시 인간이 이해할 수 있는 형태로 복원하기 위해서는 디컴파일(Decompile) 과정을 거쳐야 함

하지만 자바는 별도의 디컴파일까지 거치지 않고도, 바이트 코드로 작성된 .class 파일의 내부 구조를 간단하게 분석할 수 있도록 기능도 제공함

javap.exe를 통해 활용 가능

terminal
javap -c Hello # Hello.class 해독 # 실행 결과 Compiled from "Hello.java" public class Hello { public Hello(); # Hello() 생성자를 통해 Hello 객체 생성 Code: 0: aload_0 # 지역 변수 0(this 객체)를 스택에 로드 1: invokespecial #1 // Method java/lang/Object."<init>":()V, Object() 호출 4: return # 생성자 호출 종료 # -> 기본 생성자를 호출할 때, super()가 호출됨 public static void main(java.lang.String[]); Code: 0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; # System.out 객체인 PrintStream을 가져옴 3: ldc #13 // String Hello World # 문자열 "Hello World"를 문자열 상수 풀(String Constant Pool)에서 로드 5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V # Printstream.println() 메서드 호출 8: return # 메서드 종료 # -> main() 내부에서 System.out.println("Hello World")를 수행하는 과정 }
💡
Tip

javac가 컴파일을 수행하는 과정에서 참조하는 클래스 패스 확인하기

terminal
javac -verbose Hello.java

실행 결과

terminal
[search path for class files: C:\Users\82107\Desktop\install\jdk-17.0.8+7\lib\modules,.] [loading /modules/java.base/java/lang/Object.class] [loading /modules/java.base/java/lang/String.class] [loading /modules/java.base/java/lang/Deprecated.class] [loading /modules/java.base/java/lang/annotation/Retention.class] [loading /modules/java.base/java/lang/annotation/RetentionPolicy.class] [loading /modules/java.base/java/lang/annotation/Target.class] [loading /modules/java.base/java/lang/annotation/ElementType.class] [checking Hello] [loading /modules/java.base/java/io/Serializable.class] [loading /modules/java.base/java/lang/AutoCloseable.class] [loading /modules/java.base/java/lang/System.class] [loading /modules/java.base/java/io/PrintStream.class] [loading /modules/java.base/java/lang/Appendable.class] [loading /modules/java.base/java/io/Closeable.class] [loading /modules/java.base/java/io/FilterOutputStream.class] [loading /modules/java.base/java/io/OutputStream.class] [loading /modules/java.base/java/io/Flushable.class] [loading /modules/java.base/java/lang/Comparable.class] [loading /modules/java.base/java/lang/CharSequence.class] [loading /modules/java.base/java/lang/constant/Constable.class] [loading /modules/java.base/java/lang/constant/ConstantDesc.class] [wrote Hello.class]

2-4. 컴파일된 바이트 코드 실행하기(Run)

앞서 간단하게 확인해본 바이트 코드는 java.exe를 통해 실행할 수 있음

terminal
00000000: cafe babe 0000 003d 001d 0a00 0200 0307 .......=........ 00000010: 0004 0c00 0500 0601 0010 6a61 7661 2f6c ..........java/l 00000020: 616e 672f 4f62 6a65 6374 0100 063c 696e ang/Object...<in 00000030: 6974 3e01 0003 2829 5609 0008 0009 0700 it>...()V....... 00000040: 0a0c 000b 000c 0100 106a 6176 612f 6c61 .........java/la 00000050: 6e67 2f53 7973 7465 6d01 0003 6f75 7401 ng/System...out.

Hello.class 파일 실행하기

terminal
java Hello # java 명령어 실행 시 .class는 생략하고 실행 # 실행 결과 "Hello World"

Q. 왜 Hello.class가 아닌 Hello?

설명 보기

💡
Tip

왜 Hello.class가 아닌 Hello?

JVM은 클래스를 실행할 때, .class 파일이 아닌 클래스 이름을 기준으로 찾음
→ Hello.class가 아니라 Hello라고 입력해야 JVM이 자동으로 .class 를 찾아서 로딩함

또한 JVM은 기본적으로 .(현재 디렉토리)를 포함하여 .class를 찾음

만약 java Hello.class로 실행할 경우,
JVM은 ‘Hello.class’라는 이름의 패키지클래스를 찾으려다 실패(ClassNotFoundException)

java, javac와 같은 JDK Tool에 대한 공식 스펙

Last updated on