Java/스프링 입문을 위한 자바 객체 지향의 원리와 이해
Ch 02. Java와 절차적/구조적 프로그래밍
계란💕
2023. 11. 26. 00:49
Java 로 작성된 프로그램을 실행하기 위한 과정에 대해 알아보려고한다.
JDK, JRE, JVM 의 역할
- Java 로 작성된 프로그램을 실행하기 위해서는 JVM(Java Virtual Machine, 자바 가상 머신)이 필요하다.
- JVM으로 Java 코드를 실행하는 것은 컴퓨터가 어떤 프로그램을 실행하는 것과 비슷하다.
- ex) 어떤 소프트웨어 개발자가 개발 도구를 이용해서 개발하고 OS를 통해서 물리적 컴퓨터인 하드웨어 상에서 구동한다.
- JDK(Java Development Kit, 자바 개발 도구): JVM용 소프트웨어 개발 도구이다. 컴파일러인 javac.exe를 포함한다.
- JRE(Java Runtime Enviornment): JVM용 운영체제로서Java.exe(자바 프로그램 실행기)를 포함한다.
- JVM(Java Virtual Machine): 가상 컴퓨터로서 하드웨어 역할
T 메모리 구조
- T 메모리란?
- 이 책(스프링 입문을 위한 자바 객체 지향의 원리와 이해)에서는 저자가 설명상 편의를 위해서 데이터가 저장되는 영역을 "T 메모리" 라고 지칭했다.
- T 메모리는 static / stack / heap 영역으로 구성된다. (실제 코드는 code 영역에 존재한다. )
- static (스태틱) 영역: 클래스, 전역 변수 존재, JVM이 종료될 때까지 데이터가 고정된 상태로 존재한다.
- stack (메서드) 영역: 메서드, 지역 변수 존재, 중괄호가 열릴 때마다 새로운 스택 프레임이 생성된다.
- heap (힙) 영역: 객체, 객체 멤버 변수 존재
전역 변수(공유 변수)
- static (스태틱) 영역에 존재하는 전역 변수는 스택 프레임과 종속적이다.
- 어느 코드에서나 전역 변수에 접근 가능하다.
- ※ 전역 변수를 쓰지 말아야되는 이유
- 큰 프로젝트의 경우, 여러 메서드에서 전역변수의 값을 변경하면 T 메모리로 추적하지 않는 이상 전역 변수에 저장된 값을 파악하기 쉽지 않기 때문이다.
- 쓰기 가능한 전역 변수를 사용하면 스레드 안전성이 깨진다. 이는 lock(락)으로 보완 가능하지만 lock(락)을 쓸 경우에는 멀티 스레드의 장점이 사라진다.
Java main() 메서드 구동 과정
- 먼저, 운영체제 역할을 하는 JRE는 main() 메서드의 존재를 확인한다.
- 프로그램 실행하기 위한 사전 준비가 시작
- 하드웨어 역할을 하는 JVM에 전원을 넣어 부팅한다.
- 부팅된 JVM은 목적 파일(확장자가 '.class' 인 바이트 코드 파일)을 받아서 실행한다.
- JVM은 전처리 시작
- java.lang 패키지를 static 영역에 갖다놓는다.
- import 된 패키지를 static 영역에 갖다놓는다.
- 프로그램의 모든 클래스를 static 영역에 갖다놓는다.
- stack 영역에 스택 프레임이 할당된다. (클래스를 정의할 때 쓰는 중괄호를 제외하고) 중괄호 '{' 를 열 때마다 스택 프레임이 생성된다. 닫으면 소멸.
- 위 사진과 같이 T메모리를 구성하고 나서야 main() 메서드 안의 명령문을 실행하게 된다.
- main() 의 닫는 중괄호와 함께 스택 프레임이 사라지며 프로그램이 종료된다.
- main() 메서드 실행이 끝난 다음에 JRE는 JVM의 전원을 끄고 JRE 자체도 OS 상의 메모리에서 사라진다.
T 메모리와 멀티 스레드 / 멀티 프로세스
- 멀티 스레드와 멀티 프로세스는 메모리를 사용하는 방식이 다르다.
멀티 스레드
- 하나의 T 메모리 안에 stack 영역을 스레드 개수만큼 분할해서 쓰는 구조이다.
- 메모리 사용량이 적다.
Ex) 멀티 스레드
<hide/>
public class Start6 extends Thread{
static int share;
public static void main(String[] args) {
Start6 t1 = new Start6();
Start6 t2 = new Start6();
t1.start();
t2.start();
}
@Override
public void run() {
for(int count = 0; count < 10; ++count){
System.out.println(share++);
try{
sleep(10000);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
- 동시에 실행중인 두 개의 스레드가 특정 static 변수에 동시에 접근하는 경우, 같은 값이 출력된다.
Note) 실행 결과
- 0 1 2 2 3 3 4 4 5 5 6 7 8 9 11 10 12 12 13 14
멀티 프로세스
- 여러 개의 T메모리를 갖는 구조이다.
- 메모리 사용량이 크다.
- 각 프로세스는 다른 프로세스의 데이터에 접근 불가능
Note
- CallByValue(값에 의한 전달): 어떤 메서드의 인자에 변수를 넣어서 전달할 때, 변수 자체가 이동하는 게 아니라 변수의 값이 복사된 형태로 전달된다. 이런 전달 방식을 'CallByValue ' 라고 한다.
찾아보기
- 쓰기 가능한 전역변수에 대해 lock을 쓰면 멀티스레드의 장점이 사라지는 이유
출처 - 「 스프링 입문을 위한 자바 객체 지향의 원리와 이해 - 김종민 」