본문 바로가기



프로그래밍/JAVA

[JAVA] Byte code를 통한 메모리 분석

자바강좌를 2회차로 다른분 것을 듣고 있는데, heap과 stack에 관한 내용을 설명해 주시는데 개념적으로 이해가 어려워서 바이트코드로 갈음한 부분을 분석해 보기로 했다.

package java_memory_study;

public class object_create_and_vars {

	public static void main(String[] args) {
		object_create_and_vars var1 = new object_create_and_vars ();
		object_create_and_vars var2 = new object_create_and_vars ();
		
		System.out.println("Heap Memory Address");
		System.out.println(var1);
		System.out.println(var2);
	
	}

}

object_create_and_vars 의 var1 / var2의  객체가 stack 으로 위에 나오는 @뒤의 주소를 참조한다는 것을 알 수 있다. 1회차 강의를 들을때는 무슨이야기인지 어렴풋이만 알았는데 위의 출력물을 equal 로 비교하면서 같은 값이 아니라고 판단하는것이 강의 주제였는데. 이제보니 메모리 구조도 함께 이야기하는 강의였던것 같다. 

그럼 과연 실제로 어떻게 처리 되길래 저런 메시지가 나오는 것일까 ? 

Compiled from "object_create_and_vars.java"
public class java_memory_study.object_create_and_vars {
  public java_memory_study.object_create_and_vars();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class java_memory_study/object_create_and_vars
       3: dup
       4: invokespecial #16                 // Method "<init>":()V
       7: astore_1
       8: new           #1                  // class java_memory_study/object_create_and_vars
      11: dup
      12: invokespecial #16                 // Method "<init>":()V
      15: astore_2
      16: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
      19: ldc           #23                 // String Heap Memory Address
      21: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      24: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
      27: aload_1
      28: invokevirtual #31                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      31: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
      34: aload_2
      35: invokevirtual #31                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      38: return
}

 javap 를 통해서 바이트코드로 된 위의 소스를 살펴보면

1. aload : array 값을 stack에 올림
2. invokespecial :  인스턴스 메서드를 호출해서 결과를 stack에넣음
3. return 

0. new 인덱스에서 클래스로 참조 식별되는 유형의 새 개체를 만듦 (생성)
3. dup  stack값을 복제함(복제)
4. invockespecial  인스턴스 메서드를 호출해서 결과값을 stack에 넣음(스택)
7 astore_1 지역변수 참조에 저장 
8 ~ 15 는 0~ 7을 반복함.

-------System.out.println------ 
16 getstatic 클래스 정적 필드 값을 가져옴. 필드는 상수 풀 인덱스 필드 참조로 식별됨 
19 ldc 상수풀(var type)에서 스택의 상수를 push 함 - heap 메모리 주소를 문자화함 
21 invokevirtual  객체에서 가상 메소드를 호출하고 결과를 스택에 넣음. 메서드는 상수플의 메서드 참조 인덱스로 식별됨.