작심 365
2장-자바와 절차적/구조적 프로그래밍 본문
해당 글은 스프링 입문을 위한 자바 객체 지향의 원리와 이해 라는 책을 읽고 정리한 내용 입니다.
이번 장에서 가장 핵심적이고 중요한 내용은 자바 프로그램이 실행될 때 메모리가 어떤식으로 사용되는지 인것 같습니다.
자바 프로그램의 개발과 구동
자바 개발 도구인 JDK를 이용해 개발된 프로그램은 JRE에 의해 가상의 컴퓨터인 JVM 상에서 구동됩니다.
자바의 세계를 현실세계와 비교를 해보면 다음처럼 표현할수 있습니다.
| 현실 세계 | 가상 세계 (자바 월드) | |
| 소프트웨어 개발 도구 | JDK - 자바 개발 도구 | JVM용 소프트웨어 개발 도구 |
| 운영체제 | JRE - 자바 실행 환경 | JWM용 OS |
| 하드웨어 - 물리적 컴퓨터 | JVM - 자바 가상 기계 | 가상의 컴퓨터 |
자바 개발자는 본인이 사용 중인 플랫폼에 설치된 JVM용으로 프로그램을 작성하고 배포하면 각 플랫폼에 맞는 JVM이 중재자로서 각 플랫폼에서 프로그램을 구동하게 만들어 줍니다. ->Write Once Run Anywhere
자바 뿐만 아니라 다른 프로그래밍 언어를 잘 이해하고 활용하기 위해서는 프로그램이 메모리를 어떤식으로 사용하는지 아는것이 중요합니다.
메모리는 크게 코드 실행 영역과 데이터 저장 영역으로 나눌수 있습니다.
데이터 저장 영역은 다시 스태 틱(static) 영역, 스택(stack) 영역, 힙(heap) 영역으로 분할해서 사용합니다. 이 데이터 저장 영역을 3부분으로 나눠진 생김새에 따라 편의상 T 메모리라고 부르겠습니다.

다시 보는 main() 메서드 : 메서드 스택 프레임
main() 메서드는 프로그램이 실행되는 시작점입니다.

Start.java가 한줄씩 실행될때 마다 T 메모리가 어떻게 변화하는지 알아봅시다.
JRE는 먼저 프로그램 안에 main() 메서드가 있는지 확인합니다. main() 메서드를 발견하면, JVM에 전원을 넣어 부팅합니다.
부팅된 JVM은 목적 파일을 받아 그 목적 파일을 실행합니다.
JVM이 맨 먼저 하는 일은 전처리라는 과정입니다. 모든 자바 프로그램에 반드시 포함되는 패키지가 있는데 java.lang 이라는 패키지 입니다.
JVM은 가장 먼저 모든 자바 프로그램에 필수로 포함되는 java.lang 패키지를 T 메모리 스태틱 영역에 가져다 둡니다.
(java.lang 패키지가 있어서 System.out.println() 같은 기능을 따로 import 하지 않고 사용할수 있습니다.)
다음으로 JVM은 개발자가 작성한 모든 클래스와 import 패키지들을 스태틱 영역에 가져다 놓습니다.
정리하자면
main() 메서드가 실행되기 전 JVM에서 수행하는 전처리 작업들
- java.lang 패키지를 T 메모리의 스태틱 영역에 배치한다.
- import된 패키지를 T 메모리의 스태틱 영역에 배치한다.
- 프로그램 상의 모든 클래스를 T 메모리의 스태틱 영역에 배치한다.
그러면 이제 main() 메서드가 올라갈 공간이 필요합니다. main() 메서드를 위해 스택 프레임(stack frame)이
스택 영역에 할당 됩니다. 스택 프레임은 중괄호를 만날때 마다 하나씩 생긴다고 생각하면 됩니다.
main() { } <- 스택 프레임 1개 생성
이렇게 main() 메서드까지 메모리에 올라와야 main() 메서드 안에 구문들이 실행이 됩니다. 이때 main() 메서드의 인자인 args 도
main() 메서드 스택 프레임 공간에 할당이 됩니다. 그리고 나서 System.out.println() 문이 실행되게 됩니다.

그 후 main() 메서드의 닫는 괄호 } 를 만나게 되면 main() 메서드에 대한 스택 프레임은 소멸됩니다.
main() 메서드가 프로그램의 시작점이자 끝이기 때문에 main()메서드가 끝나면 JRE는 JVM 을 종료하고 JRE 도 운영체제 상의 메모리에서 사라지게 됩니다. 그렇게 T 메모리도 끝나게 되는 것입니다.
변수와 메모리 : 변수! 너 어디 있니?

Start2.java를 실행한 경우는 메모리가 어떻게 변하는지 확인해봅시다. 5번째 줄까지는 위에 예제와 다르지 않지만 9번째 줄까지 실행하게 되면 어떻게 될까요? 이번에는 변수를 위한 공간이 할당되어야 합니다.
변수 i와 d 둘다 main() 메서드 내에 있으므로 main()메서드 스택 프레임 안에 밑에서 부터 차곡차곡 변수 공간을 마련하게 됩니다.
밑에 그림은 9 번째 줄 까지 실행했을때 T 메모리의 모습입니다.

마찬가지로 10번째 닫는 중괄호로 main() 메서드 스택 프레임이 스택 영역에서 사라지게 됩니다. 즉, 프로그램이 종료됩니다.
블록 구문과 메모리 : 블록 스택 프레임

7번째 줄까지 실행을 하면, 이전 예시 처럼 스택 영역에 main() 메서드 스택 프레임이 생성되고 그 안에 변수 args, i , k 변수를 위한 공간들이 할당 될 것입니다.
그 다음으로 실행할 부분이 if 문인데, if ~ else 문의 조건 결과에 따라 둘중 어느 부분을 실행할지가 결정됩니다. 지금 예시에서는 i = 10 으로 할당이 되었기 때문에 i==10 이 성립해서 if 문 바로 뒤에 있는 중괄호에 내용들이 실행됩니다.
아까도 중괄호를 만나면 스택 프레임이 시작된다고 했는데 여기서 만들어지는 스택 프레임은 메서드의 스택 프레임이 아니라 if문, 그것도 참인 블록의 스택 프레임 입니다.
따라서 main() 메서드의 스택 프레임 안에 if 문의 블록 스택 프레임이 중첩되어 생성됩니다.
int m = k + 5; 구문은 if 스택 프레임 안의 변수 m에 값을 할당합니다. 이때 k 는 if 스택 프레임 밖에 존재하지만, main() 메서드 스택 프레임 안에 선언된 변수입니다.

그 다음 줄인 11번째 줄을 실행하면 main() 스택 프레임에 있는 k의 값이 20 에서 25로 변경됩니다. 그리고 if 블록 중 참일 때의 블록을 종료하는 닫는 중괄호를 만나게 되면 if 블록 스택 프레임은 스택 영역에서 사라집니다.
지역 변수와 메모리 : 스택 프레임에 갇혔어요!
그러면 변수는 어디에 존재해야 되는 걸까요? 변수는 static ,stack , heap 이 세군데에 모두 존재할수 있습니다.
이 세군데중 어디에 속할지는 변수가 어디에 선언됬는지에 따라 달라집니다.
지역 변수는 스택 (stack) 영역에 스택 프레임 안에 존재합니다. 따라서 해당 스택 프레임이 사라지면 같이 사라지게 됩니다.
클래스 맴버 변수는 스태틱(static) 영역에 존재합니다. static 영역에 저장된 값들은 JVM이 종료될때 까지 그대로 존재합니다.
객체 멤버 변수는 힙(heap) 영역에 존재합니다. 객체 멤버 변수들은 객체와 함께 가비지 컬렉터라고 하는 힙 메모리 회수기에 의해 사라지게 됩니다.
Start3.java 파일을 보면 if 스택 프레임 안에서 if 스택 프레임 밖에 존재하는 k 변수에 접근이 가능한 사실을 알 수 있습니다.
하지만 if 스택 프레임은 main() 스택 프레임이 종료되기 이전에 종료되므로 main() 스택 프레임 에서 if 스택 프레임에 있는 변수에는 접근이 불가능 합니다.
외부 스택 프레임에서 내부 스택 프레임의 변수에 접근하는 것은 불가능하나 그 역은 가능하다.
'책 > 스프링 입문을 위한 자바 객체 지향의 원리와 이해' 카테고리의 다른 글
| 5장-객체 지향 설계 5원칙 - SOLID (0) | 2023.10.03 |
|---|