본문으로 바로가기

C언어는 컴파일러에 의해 소스파일(*.c)이 목적파일(*.obj)로 변환될때 바이너리 파일, 즉 0과 1로 이루어진 코드로 변환된다.

즉, 컴파일 후에 이미 컴퓨터가 이해할 수 있는 이진코드로 변환되는 것이다.


목적파일은 기본적으로 컴퓨터가 이해할 수 있는 바이너리 코드(이진 코드)의 형태이지만 실행될 수는 없다.  그 이유는 완전한 기계어(CPU에서 사용하는 명령어 집합)이 아니기 때문이다.


변환된 목적파일은 링커에 의해 실행 가능한 실행파일(*.exe)로 변환될 때 함수나 헤더 파일 등의 실제 메모리 주소를 코드에 반영하는 과정에서 일부 주소값이 변경되는데, 이러한 과정을 거쳐야 비로소 컴퓨터가 바로 실행 할 수 있는 100% 기계어가 될 수 있다.


결론적으로 목적파일은 바이너리 코드이지만 컴퓨터가 바로 실행 할 수 있는 100% 기계어라고는 할 수 없다.

(결론적으로 완벽한 기계어는 실행파일 뿐이라고 할 수 있다.)

하지만Java에서는 컴파일러(javac)에 의해 소스파일(*.java)이 목적파일(*.class)로 변환될때 컴퓨터가 바로 인식할 수 있는 바이너리코드가 아닌 바이트 코드로 변환된다.


그렇다면 바이트 코드와 바이너리 코드는 무엇이 다른가? 구분을 위해선 우선 짚고 넘어가야 할 개념들이 있다.



바이너리 코드란?

바이너리 코드는 컴퓨터가 인식할 수 있는 0과 1로 구성된 이진코드를 의미한다.


기계어란?

1. 기계어는 0과 1로 이루어진 바이너리 코드이다.

2. 기계어가 이진코드로 이루어졌을 뿐이지 모든 이진코드가 기계어인 것은 아니다. ( 바이너리 코드 != 기계어)

3. 기계어는 특정한 언어가 아니다. 

   단지 CPU제조사에서 CPU를 만들 때 해당 CPU에서 사용하는 명령어 집합을 공개하는데, 이것을 '기계어'라고 부를 뿐이다.

   때문에 CPU가 변경되면 기계어가 달라진다. 같은 동작을 하는 명령어지만 완전히 다른 0과 1의 나열이 될 수 있다는 말이다. 

4. 아주 기본적인 연산자들은 서로 호화이 되는 편이다.

5. 같은 회사의 CPU라도 버전 별로 다른 명령을 포함할 수 있으며 다른 회사라도 같은 명령어 집합을 공유할 수도 있다.


바이트 코드란?

CPU가 이해할 수 있는 언어가 바이너리 코드라면 바이트 코드는 가상 머신이 이해할 수 언어이다.

CPU가 아닌 가상 머신에서 이해할 수 있는 코드를 위한 이진 표현법이다. 즉, 가상 머신이 이해할 수 있는0과 1로 구성된 이진코드를 의미.

어떤 플렛폼에도 종속되지 않고 실행될 수 있는 가상 머신용 기계어 코드이다.

고급언어로 작성된 소스코드를 가상 머신이 이해할 수 있는 중간 코드로 컴파일한 것을 말한다.

바이트 코드는 다시 실시간 번역기 또는 저스트 인 타임(just-in-time, JIT) 컴파일러에 의해 바이너리 코드로 변환된다.

CPU가 텍스트를 이해하지 못하듯이 가상 머신 또한 텍스트를 이해하지 못한다.

Java의 가상 머신을 JVM이라고 하며 JVM을 위한 바이트 코드를 자바 바이트 코드라고 한다.

어셈블리어와 비슷한 형태를 띈다. => ?? 어셈블리어랑 비슷한건지 바이너리(이진법)인건지 모르겠네


* 플렛폼 

개발환경 실행환경 등 어떠한 목적을 수행할 수 있는 환경을 말한다.

ex) 프로그램이 실행되는 환경인 운영체제의 종류(window, mac), 개발이 수행되는 환경의 종류(안드로이드 스튜디오, 비쥬얼 스튜디오)