Java Vertual Machine

ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰ν•˜κΈ° μœ„ν•΄ 물리적 λ¨Έμ‹  (컴퓨터) κ³Ό μœ μ‚¬ν•˜κ²Œ λ§Œλ“  머신을 μ†Œν”„νŠΈμ›¨μ–΄λ‘œ κ΅¬ν˜„ν•œ κ²ƒμœΌλ‘œ
μ‹€μ œλ‘œ Java Byte Code λ₯Ό μ‹€ν–‰ν•  수 μžˆλŠ” ν”„λ‘œμ„ΈμŠ€ 가상 λ¨Έμ‹  이닀.

OS λ³„λ‘œ μ’…λ₯˜κ°€ λ‹€λ₯Έλ° MS Window & Linux λ“±μ˜ ν™˜κ²½μ—μ„œλŠ” HotSpot VM, IBM AIX 의 κ²½μš°μ—λŠ” IBM J9 이 μ‚¬μš©λœλ‹€.

"JVM μ•„ν‚€ν…μ²˜"

νŠΉμ§•

  • μžλ°”μ˜ κ°€μƒλ¨Έμ‹ μœΌλ‘œ OS 에 쒅속적이지 μ•Šμ•„ λ…λ¦½μ μœΌλ‘œ μš΄μ˜λœλ‹€.
  • GC (Garbage Collection) 은 μ‚¬μš©μžμ— μ˜ν•΄ λͺ…μ‹œλ˜μ§€ μ•ŠμœΌλ©° μžλ™μœΌλ‘œ λ©”λͺ¨λ¦¬ 관리가 λœλ‹€.

ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰λ˜λ©΄ JVM 은 OS λ‘œλΆ€ν„° ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”λ‘œν•˜λŠ” λ©”λͺ¨λ¦¬λ₯Ό ν• λ‹Ή λ°›κ³ , JVM 은 이 λ©”λͺ¨λ¦¬λ₯Ό μš©λ„μ— 따라 μ—¬λŸ¬ μ˜μ—­μœΌλ‘œ λ‚˜λˆ„μ–΄ 관리 ν•œλ‹€.

JVM μ™ΈλΆ€

"JVM ꡬ쑰"

Java 둜 μž‘μ„±ν•œ μ½”λ“œλŠ” Class Loader κ°€ 컴파일된 Java Byte Code λ₯Ό Runtime Data Areas 에 λ‘œλ“œν•˜κ³  Excution Engine 이 Java Byte Code λ₯Ό μ‹€ν–‰

Compile Running

  1. μ†ŒμŠ€μ½”λ“œλ₯Ό μž‘μ„±
  2. Compiler λŠ” JAVA μ†ŒμŠ€μ½”λ“œλ₯Ό μ΄μš©ν•˜μ—¬ 클래슀 νŒŒμΌμ„ 생성
  3. 컴파일된 νŒŒμΌμ€ JVM (Java Virtual Machine) 이 인식 κ°€λŠ₯ν•œ λ°”μ΄λ„ˆλ¦¬ 파일둜 λ³€ν™˜
  4. JVM 은 클래슀 파일의 λ°”μ΄λ„ˆλ¦¬ μ½”λ“œλ₯Ό ν•΄μ„ν•˜μ—¬ ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰
  5. μˆ˜ν–‰ κ²°κ³Όκ°€ 컴퓨터에 반영

Class Loader

μžλ°”λŠ” Runtime μ‹œμ— Class λ₯Ό λ‘œλ“œν•˜κ³  λ§ν¬ν•˜λŠ” Dynamic Loading νŠΉμ§• 이 μžˆλ‹€.

이 Dynamic Loading νŠΉμ§•μ„ λ‹΄λ‹Ήν•˜λŠ” 뢀뢄이 Class Loader 이닀.

Class Loader λŠ” λ‘œλ“œλœ 클래슀λ₯Ό λ³΄κ΄€ν•˜λŠ” Namespace λ₯Ό κ°–λŠ”λ°,
이미 λ‘œλ“œλœ 클래슀 인지 ν™•μΈν•˜κΈ° μœ„ν•˜μ—¬ Namespace 에 λ³΄κ΄€λœ FQCN 을 κΈ°μ€€μœΌλ‘œ 클래슀λ₯Ό μ°ΎλŠ”λ‹€.

FQCN (Fully Qualified Class Name) ?

ν΄λž˜μŠ€κ°€ μ†ν•œ νŒ¨ν‚€μ§€λͺ…을 λͺ¨λ‘ ν¬ν•¨ν•œ 이름을 λ§ν•œλ‹€.
보톡 java.lang.String s = new java.lang.String(); κ³Ό 같이 Alias Name (μΆ•μ•½) ν˜•μ΄ μ•„λ‹Œ νŒ¨ν‚€μ§€λ₯Ό λͺ¨λ‘ ν¬ν•¨ν•œ 경둜
Class Loader μ—μ„œλŠ” 비둝 FQCN 이 같더라도 Namespace κ°€ λ‹€λ₯΄λ©΄ λ‹€λ₯Έ 클래슀둜 κ°„μ£Ό

Class Loader 의 λŒ€ν‘œμ μΈ μ—­ν™œμ€ μ‚¬μš©μžκ°€ μž‘μ„±ν•œ Java Byte Code λ₯Ό JVM λ©”λͺ¨λ¦¬μƒμ— μ˜¬λ €μ£ΌλŠ” μ—­ν™œμ„ ν•œλ‹€.

νŠΉμ§•

클래슀 λ‘œλ”λŠ” λ‹€μŒκ³Ό 같은 νŠΉμ§•μ΄ μžˆλ‹€.

"Class Loader ꡬ쑰"

  • Hierarchical (계측 ꡬ쑰)
    • 클래슀 λ‘œλ”λΌλ¦¬ λΆ€λͺ¨ <-> μžμ‹ 관계λ₯Ό 이루어 계측 ꡬ쑰둜 κ΅¬μ„±λœλ‹€.
    • 졜 μƒμ˜ 클래슀 λ‘œλ”λŠ” λΆ€νŠΈμŠ€νŠΈλž© (Bootstrap Class Loader) 클래슀 λ‘œλ”μ΄λ‹€.
  • Delegate Load Request (μœ„μž„ λͺ¨λΈ)
    • 계측 ꡬ쑰λ₯Ό 기반으둜 클래슀 λ‘œλ”λΌλ¦¬ λ‘œλ“œλ₯Ό μœ„μž„ν•˜λŠ” ꡬ쑰둜 λ™μž‘ ν•œλ‹€.
    • 클래슀λ₯Ό λ‘œλ“œν•  λ•Œ λ¨Όμ € μƒμœ„ ν΄λž˜μŠ€λ‘œλ”λ₯Ό ν™•μΈν•˜μ—¬ μ‘΄μž¬ν•˜λ©΄ ν•΄λ‹Ή 클래슀λ₯Ό μ‚¬μš©ν•˜κ³  μ—†μœΌλ©΄ μš”μ²­ 받은 클래슀 λ‘œλ”κ°€ 클래슀λ₯Ό λ‘œλ“œν•œλ‹€.
  • Have Visibility Constraint (κ°€μ‹œμ„±)
    • ν•˜μœ„ (μžμ‹) 클래슀 λ‘œλ”λŠ” μƒμœ„ (λΆ€λͺ¨) 클래슀 λ‘œλ”λ₯Ό μ°Ύμ„μˆ˜ μžˆμ§€λ§Œ κ·Έ λ°˜λŒ€μ˜ 경우 (λΆ€λͺ¨ -> μžμ‹) 은 μžˆμ„ 수 μ—†λ‹€.
  • Cannot unload Classes (μ–Έλ‘œλ“œ λΆˆκ°€)
    • 클래슀 λ‘œλ”λŠ” Unload κΈ°λŠ₯을 ν•˜μ§€ μ•ŠλŠ”λ‹€. (Unload λŠ” GC μžλ™μœΌλ‘œ 함)

μš”μ²­ 처리

Class Loader κ°€ Class Load λ₯Ό μš”μ²­ λ°›μœΌλ©΄, μ•„λž˜ μˆœμ„œλŒ€λ‘œ 검색을 ν•œλ‹€.

"Class Loader μš”μ²­ 처리"

Bootstrap Class Loader κΉŒμ§€ 확인해도 μ—†μœΌλ©΄ μš”μ²­ 받은 클래슀 λ‘œλ”κ°€ 파일 μ‹œμŠ€ν…œμ—μ„œ ν•΄λ‹Ή 클래슀λ₯Ό 찾음

Runtime Data Areas

Class Loader μ—μ„œ λ‘œλ“œν•΄μ€€ 데이터λ₯Ό λ³΄κ΄€ν•˜μ—¬ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μˆ˜ν–‰ν•œλ‹€.
이 μˆ˜ν–‰ μž‘μ—…μ‹œμ— μ‚¬μš©λ˜λŠ” μ €μž₯ 및 참쑰둜 ν•˜λŠ” λ©”λͺ¨λ¦¬ μ˜μ—­μ΄λ‹€.

Method Area

  • λͺ¨λ“  Thread κ°€ κ³΅μœ ν•˜λŠ” λ©”λͺ¨λ¦¬ μ˜μ—­
    • class interface method field static valuable byte code 등을 보관
  • μž„ν¬νŠΈλœ ν΄λž˜μŠ€κ°€ λ‘œλ“œλ˜λŠ” μ˜μ—­

Heap Area

  • ν”„λ‘œκ·Έλž¨ μƒμ—μ„œ 데이터λ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•΄ λ™μ μœΌλ‘œ ν• λ‹Ήν•˜μ—¬ μ‚¬μš© ν•˜λŠ” λ©”λͺ¨λ¦¬ μ˜μ—­
    • μ‹€μ œλ‘œ Runtime μ‹œ λ™μ μœΌλ‘œ ν• λ‹Ήν•˜μ—¬ μ‚¬μš©ν•˜λŠ” μ˜μ—­
  • μžλ°” ν”„λ‘œκ·Έλž¨μ€ new μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό λ™μ μœΌλ‘œ 생성
    • Method Area 에 λ‘œλ“œλœ 클래슀만 생성 κ°€λŠ₯
    • class λ₯Ό μ΄μš©ν•˜μ—¬ instance λ₯Ό μƒμ„±ν•˜λ©΄ ν•΄λ‹Ή μ˜μ—­μ— μ €μž₯ν•˜μ—¬ μ‚¬μš©
  • μ—¬λŸ¬ Thread κ°€ 이 μ˜μ—­μ„ 곡유 ν•œλ‹€.
  • 이 μ˜μ—­μ€ GC (Garbage Collector) λ₯Ό ν†΅ν•΄μ„œλ§Œ λ©”λͺ¨λ¦¬ ν•΄μ œκ°€ κ°€λŠ₯ ν•˜λ‹€. (GC 의 μ‹€μ œμ μΈ λŒ€μƒ)
  • Method μ˜μ—­μ΄ 클래슀 정보λ₯Ό μ°Έκ³ ν•˜μ—¬ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λŠ” κ³³ 이닀.

Stack Area

  • Method κ°€ 호좜될 λ•Œλ§ˆλ‹€ Stack Frame μ΄λΌλŠ” 데이터 μ˜μ—­μ΄ μƒμ„±ν•˜μ—¬ ꡬ성
    • Method 에 μ‚¬μš©λ˜λŠ” Thread 의 μˆ˜ν–‰ 정보λ₯Ό Stack Frame 을 ν†΅ν•΄μ„œ μ €μž₯
    • Thread κ°€ μ‹œμž‘λ λ•Œ μƒμ„±ν•˜λ©°, Thread λ³„λ‘œ μƒμ„±λ˜κΈ° λ•Œλ¬Έμ— λ‹€λ₯Έ Thread λŠ” μ ‘κ·Ό ν•  수 μ—†λ‹€.
  • Method 의 정보, Local Valuable, Argument λ“±μ˜ μ—°μ‚° 쀑 λ°œμƒλ˜λŠ” μž„μ‹œ 데이터 등이 μ €μž₯ λœλ‹€.
  • Method μˆ˜ν–‰ λ˜λŠ” λ™μ•ˆλ§Œ μ‚¬μš©λ˜λ©° λ©”μ†Œλ“œμ˜ μˆ˜ν–‰μ΄ λλ‚˜λ©΄ ν•„μš” μ—†κ²Œ λœλ‹€.
  • Method κ°€ 호좜될 λ•ŒλŠ” ν•„μš”λ‘œν•˜λŠ” λ³€μˆ˜λ₯Ό Stack 에 μ €μž₯ ν•˜κ³ , Method 싀행이 λλ‚˜λ©΄ Stack 을 λ°˜ν™˜ ν•œλ‹€.
  • 싀행쀑인 Thread 에 따라 각각 ꡬ성 ν•˜κ²Œ λœλ‹€.

PC Register

  • 싀행쀑인 각 Thread λŠ” λ³„λ„μ˜ PC Register λ₯Ό 가지며, λͺ…령이 μ‹€ν–‰λ˜λ©΄ ν˜„μž¬ 싀행쀑인 λͺ…λ Ήμ˜ μ£Όμ†Œλ₯Ό μœ μ§€ν•œλ‹€.

Native Method Stack

  • JAVA μ™Έμ˜ μ–Έμ–΄λ‘œ μž‘μ„±λœ λ„€μ΄ν‹°λΈŒ μ½”λ“œλ“€μ„ μœ„ν•œ Stack
    • JNI (Java Native Interface) λ₯Ό ν†΅ν•˜μ—¬ ν˜ΈμΆœλ˜λŠ” C/C++ λ“±μ˜ μ½”λ“œλ₯Ό μˆ˜ν–‰ν•˜κΈ° μœ„ν•œ Stack
  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ Native Method λ₯Ό ν˜ΈμΆœν•˜κ²Œ 되면 내뢀에 Stack Frame 을 μƒμ„±ν•˜μ—¬ Push ν•œλ‹€.
    • JNI λ₯Ό μ΄μš©ν•˜μ—¬ JVM 내뢀에 영ν–₯을 주지 μ•ŠκΈ° μœ„ν•¨
    • Native Method Stack 을 μ‹€ν–‰ν• λ•ŒλŠ” JVM 을 κ±°μΉ˜μ§€ μ•Šκ³  λ°”λ‘œ μˆ˜ν–‰ν•œλ‹€.

Thread λ§ˆλ‹€ ν•˜λ‚˜μ”© 생성

  • PC Register
  • JVM Stack
  • Native Method Stack

Thread 끼리 곡유

  • Heap Area
  • Method Area
  • Runtime Constant Pool

Excution Engine

Class Loader λ₯Ό ν†΅ν•˜μ—¬ JVM λ©”λͺ¨λ¦¬μƒμ— λ°°μΉ˜λ˜μ–΄ μžˆλŠ” λ°”μ΄νŠΈ μ½”λ“œλ₯Ό Excution Engine 에 μ˜ν•΄ μ‹€ν–‰λœλ‹€.

Excution Engine λŠ” Java Byte Code λ₯Ό λͺ…λ Ήμ–΄ λ‹¨μœ„λ‘œ μ½μ–΄μ„œ μ‹€ν–‰ν•œλ‹€. (CPU κ°€ 기계어 & λͺ…λ Ήμ–΄ λ₯Ό ν•˜λ‚˜μ”© μ½μ–΄μ„œ μ‹€ν–‰ν•˜λŠ” 것 κ³Ό λΉ„μŠ·ν•˜λ‹€ )

Java Byte Code 의 각 λͺ…λ Ήμ–΄λŠ” 1 Byte 의 OpCode 와 μΆ”κ°€ ν”Ό μ—°μ‚°μžλ‘œ 이루어져 있으며, μ‹€ν–‰ 엔진은 ν•˜λ‚˜μ˜ OpCode λ₯Ό κ°€μ Έμ™€μ„œ ν”Ό μ—°μ‚°μžμ™€ ν•¨κ»˜ μž‘μ—…μ„ μˆ˜ν–‰ν•œ λ‹€μŒ, OpCode λ₯Ό μˆ˜ν–‰ν•˜λŠ” μ‹μœΌλ‘œ λ™μž‘

Java Byte Code λŠ” 기계어에 가깝기 λ³΄λ‹€λŠ” 비ꡐ적 인간이 보기 νŽΈν•œ ν–‰νƒœλ‘œ κΈ°μˆ ν•œλ‹€.

Excution Engine λŠ” 이와 같이 λ°”μ΄νŠΈ μ½”λ“œκ°€ μ‹€μ œλ‘œ JVM λ‚΄λΆ€μ—μ„œ 기계가 μ‹€ν–‰ν•  수 μžˆλŠ” ν˜•νƒœλ‘œ λ³€κ²½

졜초의 JVM 은 Interpreter λ°©μ‹μœΌλ‘œ μˆ˜ν–‰λ˜μ—ˆλ‹€.

Interpreter (인터프리터)

Byte Code λͺ…λ Ήμ–΄λ₯Ό ν•˜λ‚˜μ”© μ½μ–΄μ„œ ν•΄μ„ν•œλ‹€.
이둜 인해 싀행이 λŠλ¦¬λ‹€λŠ” 단점을 가지고 μžˆλ‹€.

이λ₯Ό κ°œμ„ ν•˜κΈ° μœ„ν•΄ JIT Compiler λ₯Ό λ„μž…ν•˜μ—¬ κ°œμ„ μ„ ν•œλ‹€.

JIT (Just In Time) Compiler

Interpreter λ°©μ‹μœΌλ‘œ μ‹€ν–‰ν•˜λ‹€ μ μ ˆν•œ(?) μ‹œμ μ— Byte Code 전체λ₯Ό Compile ν•˜μ—¬ Native Code 둜 λ³€κ²½ν•˜λ©° μ΄ν›„μ—λŠ” ν•΄λ‹Ή λ©”μ„œλ“œλ₯Ό 더 이상 Interpreting ν•˜μ§€ μ•Šκ³  Native Code 둜 직접 μ‹€ν–‰ν•˜λŠ” 방식

Native Code λ₯Ό μ‹€ν–‰ν•˜λŠ” 것이 λͺ…λ Ήμ–΄ λ‹¨μœ„λ‘œ Interpreting ν•˜λŠ”κ²ƒλ³΄λ‹€ λΉ λ₯΄λ©°, Native Code λŠ” λ‚΄λΆ€ μΊμ‹œμ— λ³΄κ΄€ν•˜κΈ° λ•Œλ¬Έμ— ν•œλ²ˆ Compile ν•œ μ½”λ“œλŠ” 계속 λΉ λ₯΄κ²Œ μˆ˜ν–‰

JIT Compile

JIT Compile 과정은 Byte Code λ₯Ό Interpreting ν•˜λŠ”κ²ƒλ³΄λ‹€ λ§Žμ€ λΉ„μš©μ΄ λ°œμƒν•˜μ—¬, λ§Œμ•½ ν•œλ²ˆλ§Œ μ‹€ν–‰λ˜λŠ” μ½”λ“œλΌλ©΄ Compile ν•˜μ§€ μ•Šκ³  Interpreting ν•˜λŠ”κ²ƒμ΄ 훨씬 μœ λ¦¬ν•˜λ‹€.

λ‚΄λΆ€μ μœΌλ‘œ ν•΄λ‹Ή Method κ°€ μ–Όλ§ˆλ‚˜ 자주 μˆ˜ν–‰λ˜κ³  μ²΄ν¬ν•˜μ—¬ 일정 μ •λ„μ˜ μˆ˜μ€€μ΄ λ„˜μ„λ•Œλ§Œ Compile μˆ˜ν–‰

finalize Method

객체가 μ†Œλ©Έλ λ•Œ ν˜ΈμΆœλ˜λŠ” λ©”μ†Œλ“œ
일반적으둜 GC μ—μ„œ 객체 λ©”λͺ¨λ¦¬λ₯Ό ν•΄μ§€ν• λ•Œ ν˜ΈμΆœλ˜λ―€λ‘œ μ‚¬μš©μ΄ ꢌμž₯ λ˜μ§€ μ•ŠλŠ”λ‹€.