
JNI는 Java Application이 C/C++로 작성된 네이티브 코드와 상호작용할 수 있도록 제공되는 인터페이스입니다. Java가 운영체제 고유의 기능에 접근하거나, Java에서 기본적으로 제공하지 않는 기능을 수행해야 할 경우 JNI를 통해 네이티브 코드를 호출합니다.
다음 그림과 같이 개발자는 Java Source Code인 .java 파일을 생성합니다.

다음 그림과 같이 생성한 .java 파일을 Java Bytecode 파일인 .class 파일로 변환합니다. 이렇게 생성된 파일은 운영체제나 하드웨어가 아닌 JVM이 이해할 수 있는 Middle Level 수준의 언어입니다.

다음 그림과 같이 JVM의 Class Loader가 컴파일 과정에서 생성된 .class 파일과 필요한 라이브러리를 메모리의 Method Area에 로드합니다. 이후 로드된 바이트 코드는 Bytecode Verifier를 통해 검증됩니다. 이 단계에서 운영체제의 파일 시스템과 상호작용이 필요할 경우, JNI를 통해 네이티브 코드를 호출하여 파일 I/O 작업을 수행합니다.

다음 그림과 같이 Execution Engine은 로드된 바이트 코드를 2가지 방식(인터프리터, JIT 컴파일러)으로 실행합니다. 더불어, 실행 과정에서 Garbage Collection을 활용하여 사용되지 않는 객체를 자동으로 정리함으로써 메모리를 효율적으로 관리합니다.

인터프리터
바이트 코드를 한 줄씩 읽고 해석하여 실행하며 속도가 상대적으로 느리지만 즉시 실행이 가능합니다.
JIT 컴파일러
자주 실행되는 바이트 코드를 기계어로 변환하고, 변한된 기계어는 캐시에 저장되어 실행 속도 최적화를 수행합니다.
이를 정리하면, Java 언어의 운영체제 독립성을 가능하게 하는 요소는 다음과 같습니다
더불어, Java Application의 수행 과정은 다음과 같습니다.

JNI는 OS의 고유 기능인 Native Code를 사용하기 위한 중간 매개체입니다. 파일 입출력, 네트워크 등 OS의 고유기능을 사용해야 한다면, JNI를 통해 OS와 상호작용을 수행한 후 Native Method Stack에 이를 보관하여 필요한 기능을 수행합니다.