2장. 자바와 절차적/ 구조적 프로그래밍

자바를 실행하기 위한 도구들을 살펴보고, 자바를 구동하는 JVM 의 메모리 구조에서 우리가 실제 사용하는 코드는 어떻게 저장하고 있으며 관리하는지 살펴본다.

자바 프로그램의 개발과 구동

자바 프로그램의 개발과 구동 과정을 나타낼 때, JVM 의 존재와 역할을 아는 것이 자바 개발 환경을 이해하는 데 필수적인 요소이다.

  • JDK(Java Development Kit): JVM 용 소프트웨어 개발 도구 -> Java 를 사용하기 위해 필요한 모든 기능을 갖춘 SDK이다.

  • JRE(Java Runtime Environment): JVM 용 OS -> Java 프로그램과 운영 체제간의 통신을 위한 기술로, Java 관련 파일이 있는 디렉터리이다.

  • JVM(Java Virtual Machine): 가상의 컴퓨터

JDK 가 JRE 를 포함하고, 다시 JRE 는 JVM 을 포함하는 형태로 배포된다.

자바가 이런 구조를 선택한 이유 기존 언어로 작성한 프로그램은 윈도우용, 리눅스용, 맥OS 용 등 각 플랫폼용으로 배포되는 설치 파일을 따로 준비해야 했던 불편함을 없애기 위해서이다.

객체지향 프로그램의 메모리 사용 방식

  • static: 전역 변수, 클래스

  • stack: 호출 되는 메서드

  • heap: 사용자 정의 객체

main() 메서드가 실행되기 전 JVM에서 수행하는 전처리 작업들

  1. JRE 는 먼저 프로그램 안에 main() 메서드가 있는지 확인한다.

  2. main() 메서드의 존재가 확인되면 JRE 는 프로그램 실행을 위한 JVM 에 전원을 넣어 부팅한다.

  3. JVM 은 가장 먼저 java.lang 패키지를 static 영역에 가져다 놓는다.

  4. JVM 은 개발자가 작성한 모든 클래스와 임포트 패키지 역시 static 영역에 가져다 놓는다.

블록 구문과 메모리: 블록 스택 프레임

여는 중괄호를 만나면 스택 프레임이 시작되는데, 여기서 만들어지는 스택 프레임은 메서드의 스택 프레임이 아니라 블록의 스택 프레임이 된다.

if 블록 중 참일 때의 블록을 종료하는 닫는 중괄호를 만나면 if 블록 스택 프레임은 스택 영역에서 사라진다. 이처럼 프레임을 별도로 관리하기 때문에 지역 변수를 활용할 수 있게 된다.

최종적으로 main() 메서드 스택 프레임을 소멸시키는 블록 마침 기호인 닫는 중괄호를 만나면 T 메모리 소멸, JVM 기동 중지, JRE 가 사용했던 자원을 운영체제에게 반납하며 시스템이 종료된다.

변수는 JVM 메모리 구조에 어디에 위치 해 있을까?

JVM 메모리 구조는 간단하게 세 개의 영역이 존재하며 스태틱 영역, 스택 영역, 힙 영역 중 변수는 어디에 저장되었을까? 모든 영역에 저장되며 서로 다른 목적을 갖고있다.

  • 지역 변수: 스택 영역에 위치해 있으며 지역 변수를 닫는 소괄호가 실행되기 전 까지 존재한다.

  • 클래스 멤버 변수: 스태틱 영역에 위치해 있으며 JVM 이 종료될 때 까지 고정된 상태로 존재한다.

  • 객체 멤버 변수: 힙 영역에 위치해 있으며 객체와 함께 가비지 컬렉터라고 하는 메모리 회수기에 의해 제거되기 전 까지 존재한다.

왜, 메서드의 지역 변수에 직접 접근할 수 없을까?

서로 다른 스택 프레임에 존재하기 때문에 지역 변수에 있는 값을 확인할 수 없다. 하지만 자바는 왜 그렇게 불편하게 구성 했을까?

  1. 메서드는 서로의 고유 공간이기 때문에 서로 침범하면 자바 전역에 문제를 발생시킬 수 있다. 이는 자바에서 객체의 값을 복사하는 원리인 Call By Value 를 어긋나게 된다.

  2. 자바는 포인터가 없기 때문에, 위치를 명확히 알 수 없다.

멀티 스레드 / 멀티 프로세스를 간략하게 살펴보기

멀티 스레드 는 JVM 메모리구조에서 스택 영역을 스레드 개수만큼 분할해서 쓰는 것이다.

  • 하나의 JVM 메모리만 사용하는데 스택 영역만 분할해서 사용하는 구조이다.

  • 스택 영역만 분할한 것이기 때문에 하나의 스레드에서 다른 스레드의 스택 영역에는 접근할 수 없지만 스태틱 영역과 힙 영역은 공유해서 사용하는 구조로, 멀티 프로세스 대비 메모리를 적게 사용할 수 있다.

멀티 프로세스 는 다수의 데이터 저장 영역, 즉 다수의 JVM 메모리 구조를 갖는 구조이다.

  • 각 프로세스마다 각자의 JVM 메모리가 있고 각자 고유의 공간이므로 서로 참조할 수 없다

  • 프로세스 간 메모리 영역을 침범할 수 없기 때문에 메모리 안전한 구조이지만 메모리 사용량은 그만큼 크다.

정리
  • JVM: 자바 가상 기계로 컴파일된 바이트 코드를 실행하며 다양한 운영 체제에서 동일한 바이트코드를 실행할 수 있게 해주기 때문에 자바의 철학인 "한 번 작성하면 어디서든 실행된다" 를 지킬 수 있게된다.

  • JRE: OS 플랫폼에 의존적인 런타임 플랫폼으로 운영체제 별로 JRE 를 설치하게 되면 Mac OS, Windows OS 등 여러 기기에서 자바 코드를 실행 시킬 수 있다.

  • JVM 메모리 구조

    • static: 전역 변수, 클래스

    • stack: 호출 되는 메서드

    • heap: 사용자 정의 객체

java.lang 패키지는 JVM 이 첫번째로 static 프레임에 저장하는 패키지이다.

  • 그 외 import 패키지들은 두번째로 static 프레임에 저장한다.

메서드 스택 프레임은 호출되는 메서드, 메서드 시그니처의 지역 변수를 관리하며 내부에 {} 문법이 포함되는 지역 범위는 개별 프레임으로 관리한다.

  • 스택 프레임에서 내부에 조건문이 존재한다면 프레임 안에 또 다른 프레임이 생성된다.

멀티 스레드 / 멀티 프로세스

  • 멀티 스레드는 JVM 메모리 구조에서 스택 영역만 서로 다르고, 그 외에 스태틱과 힙 영역은 서로 공유하기 때문에 전역 변수를 사용할 경우 임계구역에 벗어나 의도하지 않은 값이 나올 수 있다.

  • 멀티 프로세스는 프로세스 간 JVM 메모리 구조를 갖고 있으므로 서로 메모리를 공유할 수 없지만 이로인해 메모리를 그만큼 크게 사용한다.

Last updated