2017년 6월 28일 수요일

Runtime Data Area simulation


JvmInternal.java

class JvmInternal {
   static int cv = 0;
   final static int fcv = 100;

   public static void main(String[] args){
       int a, b, c;
       a = Integer.parseInt(args[0]);
       b = Integer.parseInt(args[1]);
       c = addTwoArgs(a,b);
   }

   static int addTwoArgs(int x, int y){
      cv = fcv;
      return (x + y);
   }

}
====================================================

javap -c JvmInternal.class

class JvmInternal {

  static int cv;

  static final int fcv;


  JvmInternal();

    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);

    Code:
       0: aload_0
       1: iconst_0
       2: aaload
       3: invokestatic  #2                  // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
       6: istore_1
       7: aload_0
       8: iconst_1
       9: aaload
      10: invokestatic  #2                  // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
      13: istore_2
      14: iload_1
      15: iload_2
      16: invokestatic  #3                  // Method addTwoArgs:(II)I
      19: istore_3
      20: return

  static int addTwoArgs(int, int);

    Code:
       0: bipush        100
       2: putstatic     #5                  // Field cv:I
       5: iload_0
       6: iload_1
       7: iadd
       8: ireturn

  static {};

    Code:
       0: iconst_0
       1: putstatic     #5                  // Field cv:I
       4: return
}

JvmInternal 의 수행을 위해서 ClassLoader에 의해 JVM에 적재되는 과정을 거치고, Class가 Loading이 되면 우선 Method Area에 Class의 정보가 올라가게 되고, 이 작업이 완료되면 Heap에는 JvmInternal의 Instance가 하나 생성된다.


JvmInternal();
 => 생성자, Hidden this Method
    Code:
     0: aload_0
       => local variable영역의 0번 인덱스에서 args의 reference를 로딩
     1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       => instance의 초기화 메소드를 호출
       => Heap에 JVMInternal 인스턴스를 생성
     4: return
       => return ""

/.......

  static {};  // static 초기화 블럭?
    Code:
       0: iconst_0
       1: putstatic     #5                  // Field cv:I
       4: return
}

iconst_0 와 putstaatic은 클래스변수인 cv에 값0을 집어 넣었음을 의미함.
fcv 값은 상수이기 때문에 Constant Pool에 들어가 있다.

main() 메소드를 수행하게되면, 이 메소드에 해당하는 Stack에 새로운 Stack Frame이 하나 생성되어 Push된다. 그리고 이 Method를 호출하면서 args[]의 Reference데이터를 그대로 넘겨 주었다.
stack Frame은 메소드의 정보를 바탕으로 알맞은 크기로 생성됨. 

public static void main(java.lang.String[]);
  Code:
   0: aload_0
 => Local Variable 영역의 0번 인덱스를 load
   0번 인덱스의 값은 args임
   1: iconst_0
 => Reference를 통해 가져온 args의 인덱스 값으로 0이라는 상수를 취함
    Array args에서 어떤 값을 가졍ㄹ지에 대해 array index를 지정
   2: aaload
 => args[0]의 값을 heap에서 reference를 통해 가져옴
   3: invokestatic  #2       // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
 => parseInt라는 Method를 호출하여 실행
   6: istore_1
 => local variable의 1번 인덱스에 위의 결과를 저장

만약 static 메소드가 아닌 instance 메소드라면 local variable의 0번 인덱스에는 this에 해당하는 Reference가 들어가게 된다.
args[0]의 값을 알기위해 Local Variable에 저장된 args[]의 Reference를 Operand Stack에 Push한다.
 그 후 값을 가져올 args[]의 인덱스를 지정한다. Heap에 저장된 args[]의 Array Data에서 0번지의 값을 Pop하여 그 Reference로 10을 찾아 Operend Stack으로 집어 넣는다. 

     7: aload_0
     8: iconst_1
     9: aaload
    10: invokestatic  #2                  // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
    13: istore_2
    14: iload_1
 => Local Varible 1 번 인덱스에서 값을 load함 a의 값을 load
    15: iload_2
 => Local Varible 2 번 인덱스에서 값을 load함 b의 값을 load
    16: invokestatic  #3                  // Method addTwoArgs:(II)I
 => Static Method addTwoArgs를 호출


    19: istore_3
 => local variable의 3번 인덱스에 결과를 저장
    20: return
 => void형 Method에서 return

차례로 Stack Frame을 삭제하고 프로그램을 종료...

//====================

static int addTwoArgs(int, int);
  Code:
     0: bipush        100
 => stack에 byte값 100을 집어넣음
    값이 byte의 범위에 있으므로 bipush임
    128이 넘으면 short으로 인식하여 sipush로 처리함
     2: putstatic     #5                  // Field cv:I
 => static 변수 cv에 100을 집어넣음
     5: iload_0
 => local varible 0번 인덱스에서 값을 load함
     6: iload_1
 => local varible 1번 인덱스에서 값을 load함
     7: iadd
 => 두 int를 더함
     8: ireturn
 => Method에서 int값을 반환

Frame Data에 저장되는 Constant Pool Resolution에는 이 Method에서 사용되는 java.lang.Integer 객체나 java.lang.String객체의 심볼릭레퍼런스에 대한 실제 포인터가 저장되어있음
또한 main() 메소드를 호출한 Hidden this() 메소드의 주소값도 가지고 있다. 이는 main() Method가 정상 종료 후 복귀하기 위한 용도로 사용된다.

JavaScript_함수의 역할

◎ 자바스크립트 함수의 역할 ■ 자바스크립트 함수와 메서드는 전혀 다른 개념이다. - 자바스크립트 함수는 메서드 역할을 할 수 있지만, 객체지향 프로그래밍의 메서드는 자바스크립트의 함수 역할을 할 수 없다. - 메서드와는 다르게 ...