JAVA 파헤치기 (Part 1)

Javac 와 Class 파일, 그리고 WORA

Posted by Sol on March 05, 2020 · 3 mins read

들어가며

컴퓨터의 세계에 입문하고 접한 첫 프로그래밍 언어가 Java이다.

회사의 주력(?)언어가 Java였던데다, 입사 과정에서 진행한 부트캠프라는 무시무시한 과정은 매일매일 Java 코딩 미션이 있었고, 마지막 최종 코딩 시험을 통과하지 못하면 탈락이었다.

어쨌든 그런 이유로 Java를 처음 접하고 배웠으며, 지금 현재도 Java말고 다룰 줄 아는 언어는 없다. 아직까지는..

Java 언어로 ‘코딩을 한다’는 것과 ‘Java의 특성과 본질을 안다’는 것은 질적으로 매우 다르다고 생각한다.

Java에 대한 깊이 있는 이해가 뒷받침되어야만 왜 특정 기업이 Java를 쓰는지, Java의 장단점은 무엇인지, 내가 run을 눌렀을 때 어떤 과정을 거쳐서 console창에 결과가 뜨는지, Java를 설치할 때 window 환경에서 설정하는 환경변수는 대체 무엇인지 등…수많은 궁금증을 해결할 수 있다고 생각했기 때문이다.

Java를 파헤치는 것은 하루 이틀로 될 일이 아니니, 포스팅을 여러개로 쪼개서 최대한 자세히 하나씩 알아보고자 포스팅을 시작한다.


Java 소스코드는 어떻게 컴파일 되는가?

Java의 특성은 ‘플랫폼 독립적’이라는 것이다.

내가 한번 Java 언어로 작성해놓은 코드는 어떤 운영체제던 상관없이(윈도우든, 유닉스 기반이든) 잘 돌아간다.

Java가 나오기 전, C/C++같은 코드들은 적용되는 각 하드웨어에 맞게 다르게 코딩작업을 해야했다고 한다.

< 기계어의 CPU 종속성 >
16bit 컴퓨터 만들기 실습을 공부하며 배운 내용을 생각해보자.
1. 기계어는 '언어'라기보다는 '해석'이다.
2. ROM에서 binary 명령어가 CPU로 입력되면, CPU는 명령어를 나름의 규칙을 갖고 '해석'한다.
3. 16bit Hack 명령어를 예로 들면, 
	if instruction[15] == 0 then it is 'A-instruction' 
     else it is 'C-instruction'
     과 같이, 16bit binary의 각 자리수를 해석하는 나름의 규칙이 있다.
4. Register, PC, ALU 등 각 부품으로 이루어져있는 CPU는 이러한 규칙을 가지고 각 부품들을 컨트롤한다.
5. 그런데 만약 이 CPU의 아키텍쳐 자체가 변한다면? binary 코드의 해석 규칙이 바뀔 수도 있다.
6. 따라서 다른 CPU가 달린 하드웨어에는 다른 규칙이 적용되어있으므로, 기계어 코딩도 달라질 수 밖에 없다.

< High-level Code의 운영체제(OS)종속성 >
1. 그렇다면, 동일한 CPU를 가진 하드웨어에서 OS가 다르면, 왜 호환되지 않을까?
2. OS또한 그 아키텍쳐가 다르기 때문에, CPU의 명령을 os에 따라 다르게 해석하기 때문이다.
	=> 이 내용은 추후 OS에 관해 학습하면 조금 더 자세히 배울 수 있을 것이다.

Java의 등장 이후 OS로부터의 종속성이 제거되었다.

그럼 어떻게 Java는 OS에 상관없이 동작하는가?

그것은 바로 JVM, 즉 ‘자바 가상머신‘이라는 플랫폼 덕분이라 할 수 있다.

내가 Java 언어로 작성한 코드는 complier(JAVAC)에 의해 binary코드(바이트 코드)로 변환된다.

이것은 만약 당신이 Eclipse를 사용하고 있다면, Eclipse에서 작성한 코드가 저장되는 workspace에서 확인할 수 있는데, eclipseworkspace/src 안에 있는 파일(.java)은 Java 소스코드이며, 이에 대응되는 binary 코드가 eclipseworkspace/bin안에 있음을 알 수 있다(.class).

바로 이 .class 파일, 바이트 코드가 JVM으로 들어가서 각 OS에 맞게 가공된 후, 최종적으로 실행되게 되는 것이다.

마치 어떤 음식이 고객의 입맛에 맞게 저절로 가공되어 나오는 것처럼…

바이트코드는 OS가 읽을 수 있는 기계어는 아직 아니다.

이 Class 파일을 OS가 읽을 수 있는 기계어로 바꾸는 것이 바로 JVM의 역할이다.

Class 파일이 생성되었을 때, OS가 리눅스라면 리눅스에 맞는 기계어로 바꾸고, OS가 윈도우라면 윈도우에 맞는 기계어로 변환해 주는 것이다.

JVM은 하드웨어 및 OS에 따라 다르게 구성되어있다.

즉, Class 파일은 플랫폼 독립적이나, JVM은 플랫폼 종속적이다.

따라서 본인이 윈도우 OS에서 작업하여 javac로 변환한 Class 파일을 리눅스로 옮겨서, 리눅스용 JVM 위에서 돌리면 그대로 잘 실행될 것이며, 이는 complie되기 전 High-level 자바 소스 또한 동일하게 잘 실행된다는 의미다.

이것이 바로, Java 언어가 표방하는 WORA(Write Once, Run Anywhere)이다.

그렇다면 JVM은 어떻게 구성되어 있기에, 이 Class 파일을 운영체제에 맞게 기계어로 변환하여 주는 것일까?

이 내용은 이후 이어지는 Part 들에서 알아보기로 하자.