Java의 플랫폼 독립성

정호윤·2024년 2월 14일
0

Java Virtual Machine

목록 보기
1/3

자바는 write once, run anywhere 라는 철학을 가진 컴파일 언어입니다. 자바가 일반적인 컴파일 언어인 C, C++과 구분되는 가장 큰 특징은 바로 플랫폼 독립성입니다. 즉, 한 번 컴파일된 자바 코드는 다시 컴파일하지 않고도 자바 가상 머신이 설치된 모든 플랫폼에서 실행될 수 있습니다.

자바 가상 머신(Java Virtual Machine, 이하 JVM)은 자바 프로그램을 실행하기 위한 가상 머신입니다. JVM 덕분에, 우리가 작성한 자바 프로그램은 호스트 운영체제와의 직접적인 상호작용 없이 실행될 수 있습니다. 이는 자바 프로그램을 바이트코드(bytecode)로 컴파일하고, 해당 바이트코드를 JVM에서 실행함으로써 가능합니다. 여기서 바이트코드란 JVM의 명령어 집합을 의미합니다.

Note
바이트코드로 표현할 수 있는 모든 프로그래밍 언어는 JVM에서 실행될 수 있습니다.


자바 프로그램 실행하기

자바 프로그램을 javac 컴파일러를 사용해 바이트코드로 컴파일해 봅시다.

public class JavaComplieExample {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

자바 프로그램은 javac 명령어를 사용해 컴파일할 수 있습니다.

$ javac JavaComplieExample.java

해당 프로그램을 컴파일하면, 자바 파일과 같은 경로에 JavaComplieExample.class라는 클래스 파일이 생성된 것을 확인할 수 있습니다. 클래스 파일은 JVM에서 실행될 수 있는 바이트코드와 기타 보조 정보를 포함하는 이진 데이터 파일입니다.


java 명령어를 사용하면 컴파일된 자바 프로그램을 실행할 수 있습니다.

$ java JavaComplieExample
Hello, World!

클래스 파일의 구조

컴파일된 JavaComplieExample.class 파일을 javap 역어셈블러로 역어셈블해 직접 확인해 봅시다.

$ javap -s -v JavaComplieExample.class

javap 명령어를 사용하면 다음과 같은 결과물을 확인할 수 있습니다.

Classfile /Users/junghoyun/Desktop/JavaComplieExample.class
  Last modified 2024. 2. 14.; size 443 bytes
  SHA-256 checksum 9d5b2d9cbd2f87508cfa354ad668608b5d7fca8c9b8717d740abec3efc0ed744
  Compiled from "JavaComplieExample.java"
public class JavaComplieExample
  minor version: 0
  major version: 65
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #21                         // JavaComplieExample
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Fieldref           #8.#9          // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Class              #10            // java/lang/System
   #9 = NameAndType        #11:#12        // out:Ljava/io/PrintStream;
  #10 = Utf8               java/lang/System
  #11 = Utf8               out
  #12 = Utf8               Ljava/io/PrintStream;
  #13 = String             #14            // Hello, World!
  #14 = Utf8               Hello, World!
  #15 = Methodref          #16.#17        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #16 = Class              #18            // java/io/PrintStream
  #17 = NameAndType        #19:#20        // println:(Ljava/lang/String;)V
  #18 = Utf8               java/io/PrintStream
  #19 = Utf8               println
  #20 = Utf8               (Ljava/lang/String;)V
  #21 = Class              #22            // JavaComplieExample
  #22 = Utf8               JavaComplieExample
  #23 = Utf8               Code
  #24 = Utf8               LineNumberTable
  #25 = Utf8               main
  #26 = Utf8               ([Ljava/lang/String;)V
  #27 = Utf8               SourceFile
  #28 = Utf8               JavaComplieExample.java
{
  public JavaComplieExample();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #13                 // String Hello, World!
         5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 3: 0
        line 4: 8
}
SourceFile: "JavaComplieExample.java"

상수 풀

클래스 파일에서 가장 주목해야할 부분은 상수 풀(constant pool)입니다. 상수 풀은 클래스와 관련된 다양한 데이터를 저장하는 테이블 형태의 자료구조이며, 클래스 파일 내에서 중복을 피하고 값을 공유하여 메모리를 절약하는 데 사용됩니다. 상수 풀에는 리터럴이나 클래스 및 메서드에 대한 심볼릭 참조 등이 저장됩니다. JVM은 클래스 파일을 로드할 때 상수 풀에 저장된 값들을 참고하여 클래스 및 메서드의 정보를 효율적으로 읽어들일 수 있습니다.

Note
심볼릭 참조란 참조하는 대상의 실제 메모리 주소가 아닌 이름이나 식별자를 참조하는 것입니다.


출처

0개의 댓글