JVM을 실행할 수 있는 환경이라면, 어디든지 Jar파일을 동작 시킬수 있습니다.
JVM은 바이트코드를 해석하거나 실행할 수 있는 실행파일 이기 때문 입니다.
프로세스로 실행되는 건 jar 파일인가 java 실행 파일인가?
myapp.jar = 특수한 형태의 ZIP 압축 파일
├── META-INF/
│ └── MANIFEST.MF (메타정보)
├── com/example/
│ ├── Main.class (컴파일된 바이트코드)
│ └── Service.class
└── application.properties
Plain Text
복사
# 이렇게 실행하면
java -jar myapp.jar
# 실제로는 이런 일이 벌어집니다
/usr/bin/java ← 이게 실행 파일이고 프로세스가 됨
Plain Text
복사
/bin/java 실행 후 우리가 작성한 Main.class까지 접근하는 방법
// 1. 진입점: java 명령어 실행
JNIEXPORT int main(int argc, char **argv) {
return JLI_Launch(argc, argv, ...);
}
// 2. JLI_Launch 내부에서 플랫폼별 처리 후
int CallJavaMainInNewThread(jlong stack_size, void* args) {
// 새로운 스레드 생성 (필요 시)
if (pthread_create(&tid, &attr, ThreadJavaMain, args) == 0) {
// 성공: 새 스레드에서 JavaMain 실행
pthread_join(tid, &res);
} else {
// 실패: 현재 스레드에서 JavaMain 실행
rslt = JavaMain(args);
}
}
// 3. 실제 Java 실행 로직
int JavaMain(void* _args) {
// ① JVM 초기화
if (!InitializeJVM(&vm, &env, &ifn)) {
// 실패 처리
}
// InitializeJVM 내부:
result = JNI_CreateJavaVM(&vm, (void**)&env, &args);
↓
// hotspot/share/prims/jni.cpp
jint JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) {
result = Threads::create_vm(
(JavaVMInitArgs*) args,
&can_try_again
);
}
↓
// Threads::create_vm 내부에서
JavaThread* main_thread = JavaThread::create_system_thread_object(...);
// ② Main 클래스 로딩
mainClass = LoadMainClass(env, mode, what);
// 예: "com.example.Application" 클래스 찾기
// ③ main 메서드 ID 가져오기
mainID = (*env)->GetStaticMethodID(env, mainClass,
"main",
"([Ljava/lang/String;)V");
// ④ main 메서드 호출
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
// 또는
// ret = invokeStaticMainWithoutArgs(env, mainClass);
return 0;
}
C++
복사
Kernel Thread : OS Thread : JVM Thread : java.lang.Thread 관계 부연설명
1:1:1:1 관계 부연설명
VM이 바이트코드를 실행하는 두 가지 흐름
public class Main {
public static void main (String[] args) {
superAmazingPopularMethod();
}
public static void superAmazingPopularMethod) {
int a = 10;
int b = a + 7;
//
....
}
Java
복사
public static void main(java.lang. String[]);
Code:
0: invokestatic
3: return
#7
public static void superAmazingPopularMethod);
Code:
0: bipush
2: istore_0
3: iload_0
4: bipush
6: iadd
7: istore_1
8: return
Java
복사
1. Interpreter (인터프리터)
바이트코드를 한 줄씩 해석해서 실행
•
바이트코드를 한 줄씩 읽으면서 각 명령어에 정의된 동작을 내부 코드로 실행하는 방식
•
java 명령으로 프로그램을 실행하면 기본적으로 인터프리터가 바이트코드를 해석하며 실행
2. JIT Compiler (Just-In-Time 컴파일러)
자주 사용되는 코드를 기계어로 컴파일해서 성능 최적화
•
바이트코드 중 자주 호출되는 메서드나 반복문(loop) 블록을 감지
•
해당 코드를 최적화된 네이티브 기계어로 컴파일하여 Code Cache에 저장
•
이후 같은 코드 실행 시 컴파일된 기계어를 직접 호출하여 빠르게 실행

