들어가기에 앞서서 간단하게 제 이야기를 해 보고자 합니다.
대학교에서 Java를 처음 배워 지금까지 관성적으로 사용해왔습니다. JAVA API , Annotation , JDK 등의 코드를
자바 개발자가 어떤 생각을 가지며 기술들을 만들었는지 왜 이렇게 동작 하는지는 하나도 이해 못하고
사용하고 있었다고 말 할 수 있겠네요. 그렇지만 이번 백기선님 강의를 들으면서 이런 부족한 마인드
배경지식을 확실히 공고히 하고자 합니다. 왜 이렇게 작동하지? 라는 근본적인 질문을 이해하지 못했던,
관성적으로 코딩을 해오셨던 분들이라면 백기선님 강의를 들어보시는 걸 추천 드립니다. GoF, 언어의 근본 등
개발자를 꿈 꾸는 사람이라면 무조건 필요로 하는 내용이라고 제가 감히 말하겠습니다.
자바 Language , JVM , JDK에 차이를 아십니까?
혹자는 어차피 한 몸 아니냐 , 알 필요가 있냐 말 할 수 있을 것 입니다.
그러나 저는 이렇게 말 하겠습니다. 자기가 쓰는 도구가 어떤 식으로 만들어졌는지 모르는데 어떻게 활용을 하겠습니까?
백기선님 더 자바 로드맵
을 수강하며 정리한 내용 입니다.
예) 바이트 코드
Compiled from "HelloJava.java"
public class HelloJava {
public HelloJava();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello, Java
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
이러한 바이트 코드를 인터프리터와 JIT 컴파일러를 사용하여 네이티브 OS에 맞게 코드(기계어)로 변환후 실행
→ 특정 플랫폼에 종속적!
예) Hello.kt 파일 kotlinc로 컴파일 후 javap 명령어로 바이트 코드 확인
> javap -c HelloKt.class
Compiled from "Hello.kt"
public final class HelloKt {
public static final void main();
Code:
0: ldc #8 // String Hello, Kotlin
2: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream;
5: swap
6: invokevirtual #20 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
9: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #23 // Method main:()V
3: return
}
JVM 구조
는 크게 4 가지로 구성
native
라는 키워드가 붙고 구현은 C
나 C++
로 한 것.스택
, PC
, 네이티브 메소드 스택
은 특정 쓰레드에 국한된 것. 즉 , 쓰레드 끼리 공유하지 않음힙
, 메소드
영역은 모든 쓰레드에서 사용하는 공유 자원GC
(Garbage Collector): 더이상 참조되지 않는 객체를 모아서 정리class
파일을 읽음.class
파일을 읽은 다음 적절한 바이너리 데이터를 만들고 메소드
영역에 저장힙
영역에 저장public class App
{
public static void main( String[] args ) {
ClassLoader classLoader = App.class.getClassLoader();
System.out.println(classLoader); // (1)현재 App 클래스를 읽어온 클래스 로더 출력
System.out.println(classLoader.getParent()); // (2)클래스로더의 부모 출력
System.out.println(classLoader.getParent().getParent()); // (3)부모의 부모 출력
}
}
/**
(1) jdk.internal.loader.ClassLoaders$AppClassLoader@3b192d32
(2) jdk.internal.loader.ClassLoaders$PlatformClassLoader@6bdf28bb
(3) null
*/
(3) null이 나오는 이유
는 최상위 클래스 로더인 부트스트랩 클래스 로더
는 네이티브 코드
로 구현되어 있기 때문에 자바 코드에서 참조해서 출력할 수가 없기에 null이 출력되게 된다.
선택적이다.
이 단계에서 실제 Heap 영역에 있는 레퍼런스를 참조 할 수도 있지만 실제로 사용할때 참조하도록 교체할 수 도 있기에 선택적이다.Reference:더 자바, 코드를 조작하는 다양한 방법 : 백기선