ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 메모리 구조
    프로그래밍/Java 2017. 5. 30. 15:29


    첫 포스팅 입니다.


    언제나 처음은 두근두근 거리네요.

    저 스스로의 발전과 자그마한 지식의 공유를 위해 시작했는데요,

    처음 시작하시는 분들께 조금이라도 도움이 되셨으면 좋겠습니다.

    저 또한 프로그래밍 공부를 시작한 지 얼마 되지 않아,

    틀린 점이 있을 수 있습니다.

    만약, 그런 부분들이 보이신다면 언제든지 태클 걸어주세요.

    언제든지 환영입니다.!



    그럼 시작하겠습니다.




    이번에 다룰 내용은 자바의 메모리 구조에 대해서 입니다.


    자바를 맨 처음 시작하게 되면 배우는 내용 중에 하나 인데요,

    "개발자가 코딩만 잘하면 되지, 왜 메모리까지 알아야 되지?" 라고 하시는 분이 계실지도 모르겠습니다.

    물론 코딩 실력이 중요한 건 부인할 수 없지만, 메모리 구조를 아는 것 또한 굉장히 중요하다고 생각합니다.


    그렇다면, 왜 메모리가 중요할까요?


    예를 들어, 동일한 기능을 하는 두 개의 프로그램이 있다고 가정합니다. 하나의 프로그램은 메모리 설계가 잘 되어있는 반면에, 다른 하나의 프로그램은 메모리의 고려가 되어있지 않은 프로그램 입니다.

    두 개의 프로그램을 실행해보면 메모리 설계가 잘되어 있는 프로그램에 비해 메모리 고려가 되지 않은 프로그램은 속도 저하 현상이나 튕김 등의 현상이 일어날 확률이 큽니다.

    결과적으로, 같은 기능의 프로그램이라 하여도 메모리의 관리에 따라 성능이 차이가 나게 됩니다. 


    그러므로, 우리는 한정된 메모리를 효율적으로 사용하여 최고의 성능을 낼 수 있도록 프로그램을 설계해야 할 것입니다.



    자바 프로그램의 실행 구조

    일반 프로그램은 실행 되기 위해서는 운영체제(OS)의 제어 아래에서 메모리를 제어하여 실행되는 반면에, 자바 프로그램은 JVM(Java Virtual Machine)이 운영체제로부터 메모리를 할당 받아 프로그램을 실행하게 하는 구조입니다.


    일반 프로그램과 자바 프로그램의 실행 구조



    앞서 말씀드린 바와 같이, 일반 프로그램은 운영체제에 의해 영향을 받으므로 운영체제에 대해 종속적이라고 할 수 있습니다. 마찬가지로, 자바 프로그램은 운영체제로부터 메모리를 할당받은 JVM의 호출에 의해 실행되기 때문에 운영체제로부터 독립적이고, JVM에 대해 종속적이라고 할 수 있습니다.


    그러므로 한번 작성 된 자바 프로그램은 어떠한 운영체제에서도 동일한 결과를 가질 수 있습니다. 다만, 아무래도 JVM을 한번 더 거쳐가는 구조 때문에 일반 프로그램에 비해 속도가 낮다는 단점도 존재합니다.



    JVM의 내부 구조

    프로그램이 실행되면, JVM은 운영체제로부터 메모리를 할당 받으며, 할당받은 메모리를 용도에 따라 여러 영역으로 나누어 관리하게 됩니다.


    JVM의 내부 메모리 구조



    위의 그림에서 보다시피, 

    JVM은 크게 Class Loader, Excution Engine, Gabage Collector, Runtime Data Area(Memory Area)로 나누어져 구성되어 있습니다.


    JVM의 기본적인 수행과정을 살펴보면, 프로그램을 실행하게 되면 개발자에 의해 작성된 소스코드(.java)는 컴파일러(javac.exe)를 통해 JVM이 읽을 수 있도록 Byte Code(.Class)파일로 변환됩니다. 이렇게 변환 된 Byte Code파일을 JVM 내부의 Class Loader가 읽어들여 Runtime Data Area(Memory Area)에 저장하게 됩니다. 저장된 코드들을 Excution Engine이 하나의 명령어 단위로 읽어들여 프로그램을 실행하게됩니다. 그리고 사용이 끝나 더 이상 사용하지 않는 코드들을 Gabage Collector가 모아서 메모리에서 해제합니다.

    JVM의 각각의 영역에 대한 역할을 정리하면 다음과 같습니다.


    • Class Loader

    - 프로그램 실행 시에, 컴파일러에 의해 변환 된 Byte Code(.Class)를 읽어 메모리에 저장하는 역할을 합니다.


    • Excution Engine

    - Class Loader에 의해 JVM 메모리 공간에 저장 된 Byte Code를 하나의 명령어 단위로 읽어 들여 실행하도록 합니다.


    • Gabage Collector

    - 사용하지 않는 객체들을 메모리에서 해제하는 역할을 합니다.


    • Runtime Data Area

    - JVM이 프로그램을 수행하기 위 해 운영체제로부터 할당받은 메모리 공간입니다.


    그럼 좀 더 자세히 Runtime Data Area. JVM의 메모리 영역이 어떻게 이루어져 있는지 살펴보도록 하겠습니다.



    JVM의 메모리 영역

    JVM의 메모리 영역은 크게 Method Area, Heap, Stack, PC Register Native Method Stack 영역으로 구분 됩니다.


    JVM 메모리 영역의 내부 구조



    각각의 영역이 어떤 역할을 하는지 보겠습니다.


    • Method 영역

    - Method 영역은 인스턴스 생성을 위한 필요 정보(필드, 메소드, 생성자... 등)를 저장하는 공간입니다. 각 데이터는 Runtime Constant Pool이라는 것을 가지게 되는데요, 이는 각 데이터의 Reference를 가지고 있어서 실제 물리적 메모리 위치를 참조할 때 사용하게 됩니다.


    ※  Constant Pool

    상수 풀은 말 그대로 상수를 저장하는 공간입니다. 이외에도 필드나 메소드 등의 Reference 값들을 저장하고 있습니다. 이후, 실행 중에 중복되는 정보가 필요할 때에 기존의 정보를 사용하도록 도와줍니다.


    • Heap 영

    - Heap 영역은 동적으로 생성 된 객체 또는 배열, Array 등을 저장하는 영역입니다. 메소드 영역에서 참조한 값을 바탕으로 새로운 객체를 생성 할 시에 이곳에 저장됩니다. 여기서 사용이 끝난 객체들을 Gabage Collector가 모아서 처리하게 됩니다.


    • Stack 영역

    - 프로그램 실행 중에 메서드들이 호출되게 되면, Stack 영역에 각각의 메서드를 위한 메모리가 할당 됩니다. 즉, 각 메서드는  하나씩의 Stack을 가지게 됩니다. 

    Stack 영역은 이 메서드들 안에서 사용되어지는 값을 저장하며, 호출된 메서드의 지역변수, 매개변수, 리턴 값 및 연산 값들을 임시로 저장하는 공간입니다. 임시 저장 공간이기 때문에 사용이 끝나면 Stack 영역에서 해제됩니다.


    Stack은 LIFI(Last In First Out) 자료구조 형식이기 때문에 Stack의 맨 위(가장 나중에 쌓은 Stack)에서 부터 순차적으로 실행하게 됩니다.

    만약, 반환 값이 있는 리턴 타입의 메서드 일 경우, 종료 전에 반환 값을 그 아래(그 다음에 실행 될 Stack)에 넘겨 주게 되고 영역으로부터 해제됩니다. 이 후, 반환 값을 넘겨 받은 메서드가 이어서 실행하게 됩니다.


    Stack영역 구조


    • PC Register

    - PC Register는 현재 실행되고 있는 부분의 주소(Adress)를 가지고 있습니다. 현재 실행되고 있는 명령이 종료되면 카운트 값을 증가시켜 다음 명령을 실행하게 합니다.


    • Native Method Area

    - 자바 외 언어(C, C++ 등)을 수행하기 위한 Stack 영역입니다. 프로그램 실행 도중 호출 된 메서드가 Native 방식을 사용하는 메소드 일 경우, 이 영역에 저장되어 처리됩니다.





    '프로그래밍 > Java' 카테고리의 다른 글

    [Java] Call by value와 Call by reference  (10) 2017.05.31
Designed by Tistory.