2006년 12월 24일
Java Compiler 들여다 보기
이번엔 2006년 7월호의 서광열님이 쓴 마소 기사를 간략히 정리해본다.
자바 디컴파일러! (javap)
자바 디컴파일러는 여태까지 C++로 만들어진 jad만 사용했었는데 이 기사에서 javap를 소개하였다. JavaSE 5에 새로 추가된 것인지 알았더니 1.4.2에도 있네..
그런데 javap를 해보니 jad처럼 (jad -s java *.class) 깔끔하게 소스코드가 나오는게 아니라. 내부에서 수행되는 바이트 코드가 나온다. 예를 들면 내가 다음과 같이 javap package에 Foo라는 클래스를 만들었다.
------------------------------------
package javap;
public class Foo
{
public static void main(String[] args)
{
if( false)
{
System.out.println("Never");
}
}
}
------------------------------------------------------------------------
그리고 나서 아래와 같이 명령어를 입력하였더니 또 아래와 같이 결과가 나왔다.
------------------------------------------------------------------------
E:\javaSE\00_Essential>javap -classpath . -c javap.Foo
Compiled from "Foo.java"
public class javap.Foo extends java.lang.Object{
public javap.Foo();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: return
}
------------------------------------------------------------------------
즉 JVM에서 처리하는 byte code를 볼 수 있다.
이 아티클에서는 C++의 #ifdef - #endif와 같은 조건부 컴파일 기술에 대해서 이야기 한다. 즉 컴파일 자체도 원하는 부분만 할 수 있도록 하는 기술을 의미한다. 그런데 위의 코드에서 보듯이 'if( false )'라고 적어주면 java 컴파일러가 dead code로 인식하여 그 내용 자체를 컴파일 하지 않는 사실을 사용하면 C++의 #ifdef - #endif를 흉내 낼 수 있다.!
그래서 예전 Interface의 DEBUG를 static final로 선언해서 썼듯이 이기능을 Java SE 5의 static import기능을 활용하여 interface에 정의해 놓고 쓰면 아주 유용할 듯 하다. ( 오~^^ 좋은걸)
문자열 처리
자바에서 String은 Immutable Pattern의 클래스이다. 즉 String객체는 절대 변화하지 않으며, 만약에 변화를 주면 기존의 객체는 그대로 두고, 새로운 객체가 생성되서 나오게 된다. 이 내용을 어떻게 JVM내부에서 구동되는지 javap를 활용해서 알아 볼 수 있다. 다음과 같이 코드를 적어주면
------------------------------------------------------------------------
package javap;
public class StringTest
{
public static void main(String[] args)
{
String h = "hello";
h += " world";
}
}
------------------------------------------------------------------------
그리고 javap를 통해서 확인해 보면
------------------------------------------------------------------------
E:\javaSE\00_Essential>javap -classpath . -c javap.StringTest
Compiled from "StringTest.java"
public class javap.StringTest extends java.lang.Object{
public javap.StringTest();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16; //String hello
2: astore_1
3: new #18; //class java/lang/StringBuilder
6: dup
7: aload_1
8: invokestatic #20; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
11: invokespecial #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
14: ldc #29; //String world
16: invokevirtual #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: return
}
------------------------------------------------------------------------
이처럼 내부에서 StringBuilder를 통해서 한줄의 명령어 "String h = "hello";"가 StringBuilder혹은 StringBuffer를 New하고 append하는 것을 알 수 있다. 이처럼 직접 확인해 볼 수 있어서 아주 좋다! ^^
음~ 결과적으로 jad는 그대로 java source decompiler로 그냥 사용하고 javap라는 java byte code를 볼 수 있는 좋은 툴로 JVM내부에서 어떻게 동작하는지 확인해 볼 수도 있다.
실제도 Java SE 5에서 강화된 언어의 지원(enhanced For loop, type safe enum, autoboxing, unboxing, variable arguments, static import)기능이 javac에 의해서 수행되고 byte코드는 예전과 동일하다고 한다. ~ 좋구나! ^^
자바 디컴파일러! (javap)
자바 디컴파일러는 여태까지 C++로 만들어진 jad만 사용했었는데 이 기사에서 javap를 소개하였다. JavaSE 5에 새로 추가된 것인지 알았더니 1.4.2에도 있네..
그런데 javap를 해보니 jad처럼 (jad -s java *.class) 깔끔하게 소스코드가 나오는게 아니라. 내부에서 수행되는 바이트 코드가 나온다. 예를 들면 내가 다음과 같이 javap package에 Foo라는 클래스를 만들었다.
------------------------------------
package javap;
public class Foo
{
public static void main(String[] args)
{
if( false)
{
System.out.println("Never");
}
}
}
------------------------------------------------------------------------
그리고 나서 아래와 같이 명령어를 입력하였더니 또 아래와 같이 결과가 나왔다.
------------------------------------------------------------------------
E:\javaSE\00_Essential>javap -classpath . -c javap.Foo
Compiled from "Foo.java"
public class javap.Foo extends java.lang.Object{
public javap.Foo();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: return
}
------------------------------------------------------------------------
즉 JVM에서 처리하는 byte code를 볼 수 있다.
이 아티클에서는 C++의 #ifdef - #endif와 같은 조건부 컴파일 기술에 대해서 이야기 한다. 즉 컴파일 자체도 원하는 부분만 할 수 있도록 하는 기술을 의미한다. 그런데 위의 코드에서 보듯이 'if( false )'라고 적어주면 java 컴파일러가 dead code로 인식하여 그 내용 자체를 컴파일 하지 않는 사실을 사용하면 C++의 #ifdef - #endif를 흉내 낼 수 있다.!
그래서 예전 Interface의 DEBUG를 static final로 선언해서 썼듯이 이기능을 Java SE 5의 static import기능을 활용하여 interface에 정의해 놓고 쓰면 아주 유용할 듯 하다. ( 오~^^ 좋은걸)
문자열 처리
자바에서 String은 Immutable Pattern의 클래스이다. 즉 String객체는 절대 변화하지 않으며, 만약에 변화를 주면 기존의 객체는 그대로 두고, 새로운 객체가 생성되서 나오게 된다. 이 내용을 어떻게 JVM내부에서 구동되는지 javap를 활용해서 알아 볼 수 있다. 다음과 같이 코드를 적어주면
------------------------------------------------------------------------
package javap;
public class StringTest
{
public static void main(String[] args)
{
String h = "hello";
h += " world";
}
}
------------------------------------------------------------------------
그리고 javap를 통해서 확인해 보면
------------------------------------------------------------------------
E:\javaSE\00_Essential>javap -classpath . -c javap.StringTest
Compiled from "StringTest.java"
public class javap.StringTest extends java.lang.Object{
public javap.StringTest();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16; //String hello
2: astore_1
3: new #18; //class java/lang/StringBuilder
6: dup
7: aload_1
8: invokestatic #20; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
11: invokespecial #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
14: ldc #29; //String world
16: invokevirtual #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: return
}
------------------------------------------------------------------------
이처럼 내부에서 StringBuilder를 통해서 한줄의 명령어 "String h = "hello";"가 StringBuilder혹은 StringBuffer를 New하고 append하는 것을 알 수 있다. 이처럼 직접 확인해 볼 수 있어서 아주 좋다! ^^
음~ 결과적으로 jad는 그대로 java source decompiler로 그냥 사용하고 javap라는 java byte code를 볼 수 있는 좋은 툴로 JVM내부에서 어떻게 동작하는지 확인해 볼 수도 있다.
실제도 Java SE 5에서 강화된 언어의 지원(enhanced For loop, type safe enum, autoboxing, unboxing, variable arguments, static import)기능이 javac에 의해서 수행되고 byte코드는 예전과 동일하다고 한다. ~ 좋구나! ^^
# by | 2006/12/24 16:15 | Java/Essential | 트랙백 | 덧글(2)





☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]