ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 왜 JVM이 필요할까?
    JVM 2020. 6. 6. 18:49
    반응형

    누군가 저에게 물었습니다.

     

    "어차피 JVM도 C로 만들어진 가상 머신인데, 처음부터 C처럼 바로 기계어로 컴파일해주면 되지 않나요? 왜 굳이 속도 저하를 가지면서 두 번의 과정을 거쳐야 하죠?" 

     

    답변을 하려고 생각을 해보니 꽤 타당한 이야기입니다. 뭔가 설득당할 것 같습니다. 혼자서 나름대로 오랜 시간 고민을 해보고, 정리한 내용들입니다.


    1. History of Java

    모든 것을 설명하기 전에 자바의 유래에 대해서 알아보려고 합니다. 모든 것의 뿌리는 중요합니다. 아무리 변형이 일어나도, 근본이 되는 진리는 변하지 않습니다.

     

    자바는 James Gosling이라는 캐나다의 개발자에 의해서 만들어졌습니다. 자바의 역사를 보면 지겹도록 나오는 말이 "Write once, Read anywhere"입니다. 한번 쓴 것은 어디서든지 읽혀야 한다는 말인데요. 근데 궁금합니다. 아니 자바코드 그냥 읽으면 되는 거 아니야? 여기서는 읽고, 저기서는 못 읽는 게 있나?라고 생각할 수 있습니다. 

     

    물론 개발자가 직접 밝힌 적은 없지만 여기서 말하는 ReadRecompilation(재컴파일)이 필요 없는, 바로 기계가 읽고 실행할 수 있게 함이 아닌가 생각합니다. 즉 한번 컴파일한 것은, 어느 하드웨어 구조에서든지 읽고 동작해야 한다는 것인데요. 이 Recompilation 없이 어느 기계에서든지 실행 가능하게 도와주는 것이, JVM입니다. JVM에 대한 자세한 내용은 JVM Architecture란? 에서 다루고 있습니다.

     

    처음의 목적은 Interactive Television을 위해서 만들어졌습니다. 뭔가 생소하죠?  영어 그대로 해석을 해보면, 뭔가 TV랑 쌍방향으로 대화를 하는 느낌이 듭니다. 이는 전통적인 TV 기술에서 방송 전파상에 데이터를 전송함으로써 TV에 대화형 서비스 기능을 구현한 것입니다. 즉 TV 프로그램을 보면서 동시에 시청자가 퀴즈를 맞추고, 이미 방영시간이 지난 프로그램을 다시 볼 수도 있습니다. 또한 프로그램 시청 건마다 시청료가 부과되는 pay-by-view 시스템을 갖추고도 있습니다.

     

    왜 개발자가 어디서든 재컴파일(Recompilation) 없이, 읽고 실행할 수 있게 자바를 디자인했는지 느낌이 오시나요? 초기에는 이 자바를 TV, 셋톱박스 등 다양한 디지털 기기에서 사용하려고 했습니다. 그런데 똑같은 TV인데 기기마다 다른 구조로 인해서, 응용프로그래머가 다르게 프로그램을 만들고, 컴파일해야 한다면 정말 비효율적이겠죠? 어차피 채널 돌리고, 뭔가 선택하고 하는 근본적인 기능은 똑같은데, 하드웨어 구조가 다르기 때문에, 다른 기계어로 바꿔주는 컴파일러를 일일이 만드는 것은 귀찮은 일입니다. 이러한 것을 해결하기 위해서 JVM이라는 것이 필요했습니다. 응용프로그래머가 컴파일한 코드와 하드웨어 사이에, JVM이라는 가상 머신을 가운데에 넣어뒀습니다. 즉 해당 기기에 맞는 JVM을 설치하면, 자바 프로그램을 쉽게 돌릴 수 있게 하는 것입니다.

     

    안타깝게도 이러한 쌍방향 TV는 너무 시대를 앞서간 나머지, 자바는 원래 의도인 임베디드가 아닌, 웹 프로그래밍에서 주로 사용하게 되었습니다. 물론 안타까운 일은 아닙니다. 웹 프로그래밍 역사에 남는 강력한 언어를 개발했으니까요. 

     

    2. 컴파일 과정의 차이

    (글의 성격상 자세한 과정은 생략하겠습니다)

     

    Java와 C의 컴파일 과정에는 차이점이 있습니다.

     

    Java는 Javac(Java Compiler)라는 컴파일러가 있는데요. 이는 프로그래머가 작성한 .java 파일을 .class파일인 Byte code로 컴파일해줍니다. 그리고 이 Byte code는 JVM에 의해서 기계어로 변환되게 됩니다. 

     

    C의 컴파일은 Pre-processing, Compilation, Assembly, Linking을 통해서 이루어지게 됩니다. 이때 중요한 것은 Binary code인 기계어로 바로 변환이 되어 하드웨어에 의해서 읽어지게 되는데요. 자바처럼 컴파일러와 JVM을 거치는 것이 아닌, 바로 기계어로 변환됩니다. 그래서 많은 사람들은 C가 Java에 비해 실행 속도가 빠르다는 이야기를 합니다. 

     

    Java Byte Code

    앞서 언급했던 것처럼 자바는 "Write once, Read anywhere" 철학으로 만들어졌습니다. 즉 A 환경에서 작성된 패키지를 다른 운영체제와 컴퓨터 구조의 B, C 환경에서도 쉽게 동작을 해야 합니다. 이러한 것을 가능하게 하기 위해서 A 환경에서 컴파일한 Byte code는 B, C 환경에 알맞게 기계어로 변환될 수 있어야 했습니다. 이러한 다른 환경을 위해서 Byte code를 변환해 주는 것이 JVM입니다. 즉 OS나 CPU 구조에 상관없이 JVM을 해당 OS에 맞게 한번 인스톨하는 과정만 거치면, 다른 환경의 Byte code를 언제든지 읽어올 수 있습니다. 

     

    Binary Code vs Byte Code

    Byte code는 0과 1로 만들어진 "이진 코드"이지만, Binary code는 아닙니다. 좀 헷갈리는 말입니다. 걱정 마세요.

     

    • Binary code "기계가 읽을 수 있는 이진 코드" 
    • Byte code "가상 머신이 읽을 수 있는 이진 코드"  

     

    javac가 컴파일한 Byte code는 JVM이라는 가상 머신을 위해서 만들어졌습니다. 즉 모든 환경의 JVM에 의해서 사용될 수 있습니다. 이는 다른 환경에서 만들어진 Byte code를 해당 OS의 JVM이 알맞게 기계어로 바꿔주기 때문입니다.

     

    하지만 위에서도 언급했듯이 바로 기계어로 변환하는 C언어 보다 한 번의 컴파일 과정을 더 거쳐야 하는 Java는 더 느릴 수 밖에 없습니다. 이때 JIT 컴파일러가 필요한 부분만을 기계어로 바꾸어서, C보다 느린 자바의 성능 향상을 가져오고 있습니다. 그럼에도 불구하고 C언의 실행 속도를 따라잡을 수 없지만요. JIT는 JVM Architecture란? 에서 설명을 하고 있습니다.

     

    C Machine Code

    하지만 C는 곧바로 Binary code인 기계어로 변환이 되는데요. 위에서 언급했던 것처럼, 이때의 Binary code는 "기계가 읽을 수 있는 이진 코드"입니다. 즉 특정 OS, CPU 구조를 사용하는 컴파일러에 의해서 컴파일됐으며, 다른 OS, CPU 구조를 사용하는 환경에서는 이 기계어를 읽을 수 없습니다. 똑같은 한국어지만 연인끼리 만든 애칭을 다른 사람 앞에서 사용해도, 다른 사람은 눈치채지 못하는 것과 같습니다. 즉 같은 형식의 Binary code 기계어지만, 자신이 사용하는 환경에 맞게 처음부터 만들었기 때문에 다른 환경에서는 사용하지 못합니다. 이러한 것을 두고, 이식성이 낮다고 표현을 합니다.

     

    앞의 이유로 Java는 OS에 종속되지 않는 언어, C는 종속된 언어라고 흔히 표현합니다. 자신이 처음에 만들었던 환경을 벗어나, 다른 OS 환경으로 가게 된다면 C는 읽어질 수 없기 때문입니다. 물론 프로그래머가 C언어로 작성한 코드 자체를 IDE에 복사 붙이기 한다면 동작합니다. 이는 기계어로 컴파일되기 전이니까요.

     

    다른 환경이란

    앞에서 C와 Java의 컴파일 과정을 비교하면서 "다른 환경"의 문제점으로 인해서 방식이 다르다고 언급했습니다. 근데 이때의 다른 환경은 무엇이고, 왜 다른걸까요?

     

    흔히 우리가 "다른 환경"이라고 표현하는 것에는 OS, CPU 구조가 다른 것을 표현합니다. 즉 우리가 실행시키는 프로그램이 뛰어놀 수 있는 환경을 말하는데요. 이러한 환경이 다르게 나타나는 것에는 여러 이유가 존재합니다.

     

    각각의 CPU는 각각의 ISA(instruction set architecture)가 존재합니다. 또한 같은 x86 CPU라고 하더라도 32비트 혹은 64비트 CPU가 존재합니다. 심지어 각 비트 별로 window, mac, linux 다른 OS가 존재합니다. 이러한 OS들은 다른 System call, libraries가 존재합니다. 그리고 기계어는 언어가 아닙니다. 단순히 CPU에서 사용되는 CPU 명령어 집합을 나타내는 것입니다. 이러한 명령어 집합은 CPU의 제조사에 따라서도 많이 달라지게 됩니다. 그렇기 때문에 CPU가 달라지면 해당 기계어는 읽어질 수 없게 되는 것입니다.


    수정사항

    2020년 6월 7일 

    오타 교정

     

    2020년 6월 8일

    다른 환경에 관한 내용 추가

     

    2020년 6월 9일

    History of Java 추가

     

    2020년 6월 10일

    오타 교정

     

    “자신이 처음에 만들었던 환경을 벗아나, 다른 OS 환경으로 가게 된다면 C는 읽어질 수 없기 때문입니다.”

    --> “자신이 처음에 만들었던 환경을 벗어나, 다른 OS 환경으로 가게 된다면 C는 읽어질 수 없기 때문입니다.”

     

    2020년 9월 23일

    문맥 교정 및 약간의 내용 추가

     

     

    2021년 6월 14일

    문맥 교정 및 오타 수정

     

    참고 문헌

    www.lgeri.com/uploadFiles/ko/pdf/pub/산업리뷰_인터랙티브_TV_vs_IPT_20040312092314.pdf 

    en.wikipedia.org/wiki/Java_(programming_language)

    반응형

    'JVM' 카테고리의 다른 글

    Java Memory Model(자바 메모리 모델)  (7) 2020.05.27
    [Java]JVM Architecture란?  (6) 2020.05.24

    댓글

Designed by Tistory.