Development/CS

[스프링 입문을 위한 자바 객체지향의 원리와 이해] 2장. 자바와 절차적/ 구조적 프로그래밍

lovetan 2025. 2. 12. 01:21

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

현실 세계 가상 세계(자바 월드)  
소프트웨어 개발 도구 JDK - 자바 개발 도구 JVM용 소프트웨어 개발 도구
운영체제 JRE - 자바 실행 환경 JVM용 OS
하드웨어 - 물리적 컴퓨터 JVM - 자바 가상 기계 가상의 컴퓨터 

 

 

JVM(Java Virtual Machine)이란?

  • 말그래도 '가상기계'다.
  • 현실 세계에서 컴퓨터를 구동하기 위해 하드웨어와 운영체제, 소프트웨어, 스프트웨어를 개발할 수 있는 개발 도구가 필요하다.
  • 자바의 가상 세계는 현실 세계를 그대로 모방한다. 
JDK(소프트웨어 개발 도구)를 이용해 개발된 프로그램은
JRE(자바용 OS)에 의해
JVM(자바 가상의 컴퓨터) 상에서 구동된다.

 

  • 배포용은 편의를 위해 JDK가 JRE를 포함함. 다시 JRE가 JVM을 포함함.

 

 

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

코드 실행 영역 Stactic 영역 - 클래스들의 놀이터
스택 영역 - 메서드들의 놀이터  힙 영역 - 객체들의 놀이터

 

 

다시 보는 main() 메서드: 메서드 스택 프레임

public class Start1 {
 public static void main(String[] args) {
    System.out.println("Hello World");
 }
}
  • JRE는 먼저 프로그램 안에 main() 메서가 있는지 확인한다.
  • main() 메서드의 존재가 확인되면 JVM(가상기계)에 전원을 넣어 부팅한다.
  • 부팅된 JVM은 목적 파일을 받아 그 목적 파일을 실행한다. 
  • -> JVM이 맨 먼저 하는 일: '전처리 과정'

java.lang 

  • java.lang = 모든 자바 프로그램이 반드시 포함하게 되는 패키지
  • JVM은 java.lang 패키지를 T 메모리의 stactic 영역에 가져다 놓는다. 
  • java.lang 패키지가 있어 System.out.println() 같은 메서드 실행이 가능하다.
    • 클래스와 임포트 패키지를 T 메모리 Stactic 영역에 배치한 모습

 

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

  • java.lang 패키지를 T메모리의 stactic 영역에 배치한다.
  • import된 패키지를 T 메모리의 stactic 영역에 배치한다.
  • 프로그램 상의 모든 클래스를 T 메모리의 stactic 영역에 배치한다.

 

main() 메서드가 실행되기 위해 스택 프레임(stack frame)이 스택 영역에 할당된다.

  • 클래스 정의를 시작하는 여는 중괄호를 제외하고,
  • 여는 중괄호를 만날 때마다 스택 프레임이 하나씩 생긴다.

 

스택 프레임 - 변수 공간 할당

  • 메서드의 인자 args를 저장할 변수공간을 스택 프레임의 맨 밑에 확보해야 한다.
  • 이는 메서드 인자(들)의 변수 공간을 할당하는 것이다.
  • 위의 그림처럼 T메모리를 구성하고 나서야 main() 메서드 안의 첫 명령문을 실행하게 된다.

 

[JRE-JVM의 과정]

  • JRE는 눈에 보이지 않게 뒤에서 JVM이라고 하는 자바 가상 기계를 부팅한다.
  • JVM은 메모리 구조를 만들고 - java.lang 패키지 로딩, 각종 클래스 로딩, main() 메서드 스택 프레임 배치, 변수공간 배치 등등의 일을 처리한다.
  • 닫는 중괄호를 만나면 스택 프레임이 소멸된다. 
  • main() 메서드가 프로그램의 시작이면서 끝이다. 
  • main() 메서드가 끝나면 JRE는 JVM을 종료하고, JRE 자체도 운영체제 상의 메모리에서 사라진다. 
  • 그럼 이제 T메모리도 그 운명을 다하고 사라지게 된다. 

핵심 키워드

# T메모리 구조, javalang패키지, import 패키지와 클래스들, 메서드 스택프레임, JVM, JRE

 

 

변수와 메모리: 변수! 너 어디 있니?

1 public class Start2 {
2 	public static void main(String[] args) {
3 		 int i;
4 		 i = 10;
5 
6 		 double d = 20.0;//6번째 줄
7 		}
8  }

 

6번째 줄을 실행한 후의 T 메모리의 상태

7번째 줄의 실행

  • 7번째 줄의 닫는 중괄호로 main() 메서드 스택 프레임이 스택 영역에서 사라진다.
  • 즉, 프로그램이 종료된다. 

 

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

if-else 구문

1 public class Start3 {
2 public static void main(String[] args) {
3 int i = 10;
4 int k = 20;
5
6 if(i = 10) {
7 int m = k + 5;
8 k = m; // 8번째 줄 실행
9 } else { // 9번째 줄 실행
10 int p = k + 10;
11 k = p;
12 }
13
14 //k = m + p;
15 }
16 }

 

8번째 줄 실행

6 if(i = 10) {
7 int m = k + 5;
8 k = m;

 

9번째 줄 실행

9 } else {

 

-> if문의 스택프레임이 날아가면서 지역변수가 사라졌다.

 

지역 변수와 메모리: 스택 프레임에 갇혔어요!

변수의 위치스태틱/스택/힙 영역 중 어디에 있을까?

  • 정답: '세 군데 모두'에 존재한다.
  • 그런데, 세 군데 각각에 있는 변수는 각기 다른 목적을 가진다. 
  • 각각의 이름도 지역 변수, 클래스 멤버 변수, 객체 멤버 변수로 다르다.

지역 변수

  • 스택 영역에서 일생을 보낸다. 
  • 그것도, 스택 프레임 안에서.
  • 따라서 스택 프레임이 사라지면 함께 사라진다.
    • 외부 스택 프레임에서 내부 스택 프레임의 변수에 접근하는 것은 불가능하나, 그 역은 가능하다.
    • 내부 스택 프레임 -> 외부 스택 프레임 🅾️

클래스 멤버 변수

  • 스태틱 영역에서 일생을 보낸다.
  • 스태틱 영역에 한번 자리 잡으면 JVM이 종료될 때까지 고정된(static) 상태로 그 자리를 지킨다.

객체 멤버 변수

  • 에서 일생에서 보낸다.
  • 객체 멤버 변수들은 객체와 함께 가비지 컬렉터라고 하는 힙메모리 회수기에 의해 일생을 마치게 된다.

 

메서드 호출과 메모리: 메서드 스택 프레임 2

메서드 호출 시, 전달되는 것

  • 메서드를 호출하면서 인자로 전달되는 것은 변수 자체가 아니라 변수가 저장한 값만을 복제해서 전달한다.
  • 이런 전달 방식을 Call By Vahie(값에 의한 전달)이라고 한다. 

 

전역 변수와 메모리: 전역 변수 쓰지 말라니까요!

1 public class Starts {
2 	static int share;
3
4 	public static void main(String[] args) {
5 	share = 55;
6
7 	int k = fun(5,7);// 7번째 줄
8
9	System.out.printIn(share);
10 }
11
12 private static int fun(int m, int p) {
13 	share = m + p; // 12번째 줄
14
15 	return m - p;
16 	}
17 }

 

13번째 줄

-> m+p 공격에도 꿈쩍도 않는 share = 12 .. 

  • 스택 프레임에 종속적인 지역 변수

 

7번째 줄

-> stactic 아니면 k는 이렇게 할당이 잘 된다. (가변)

  • 스택 프레임에 독립적인 전역 변수



 

전역 변수 언제 쓰지 말고, 언제 써야 할까?

  • 전역 변수의 무시무시함이 드러난다. 전역 변수를 피할 수 있다면 피해야 할 존재다.
  • 다만, 읽기 전용으로 값을 공유해서 전역 상수로 쓰는 것은 적극 추천한다.

 

멀티 스레드 / 멀티 프로세스의 이해

멀티 스레드(Multi Thread)란?

  • 멀티 스레드의 T 메모리 모델은 스택 영역을 스레드 개수만큼 분할해서 쓴다. 
스태틱 영역 - 클래스들의 놀이터
스택 영역 - 메서드들의 놀이터  힙 영역 - 객체들의 놀이터
스레드 스레드
  • 하나의 T 메모리만 사용하는데, 스택 영역만 분할해서 사용하는 구조다.

 

멀티 프로세스(Multi Process)란?

  • 다수의 데이터 저장 영역, 즉 다수의 T 메모리를 갖는 구조다.

 

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

 

자바 웹 프로그래밍의 특징: 서블릿은 요청당 스레드O(프로세스X)를 생성한다.

  • 왜? 요청당 스레드(Servlet)가 요청당 프로세스(CGI, Common Gateway Interface)보다 더 효율적이기 때문이다.
    • CGI는 요청당 새로운 프로세스를 생성 → 프로세스 생성/종료 비용이 크고 메모리 낭비 심함.
    • 서블릿은 요청당 새로운 스레드를 생성스레드는 프로세스보다 가볍고 빠름, 자원을 효율적으로 사용.
    • 서블릿 컨테이너(Tomcat)는 Thread Pool을 활용 → 불필요한 스레드 생성을 방지하고 재사용하여 성능 최적화.
    • 결론적으로, 서블릿 방식이 고성능 웹 애플리케이션 개발에 더 적합함.

멀티 스레드에서의 전역 변수 사용 문제점

  • 예시
    • 스레드1 - 공유 영역(스태틱과 힙)에 있는 전역 변수 A에 10을 할당 (static int num = 10;)
    • CPU 사용권이 스레드2로 넘어감.
    • 스레드2 - 전역 변수 A에 20을 할당 (num = 20;)
    • CPU 사용권이 스레드1로 넘어감. A의 값을 출력
    • 스레드1 입장: 갑자기 ' 20 '이 출력되네?!
  • 이래서 전역 변수를 쓰지 말라는 것이다!
  • 쓰기 가능한 전역 변수를 사용하게 되면 스레드 안정성이 깨진다.
    • 물론, 보완하는 방법으로 락(lock)을 거는 방법이 있다.
    • 그러나, 락을 거는 순간 멀티 스레드의 장점은 버린 것과 같다.