Java는 Write Once Run Anywhere 이라고 한다.
- Java로 작성된 프로그램이 한 번 작성되면 다양한 플랫폼에서 수정 없이 실행될 수 있다는 것이다.
JDK, JRE, JVM에 대해서도 알아두면 좋다.
T자 메모리 구조
Java를 더 잘 활용하기 위해서는 우선, Java가 어떤 방식으로 메모리를 사용하는지 알아야 한다.
코드 실행 영역 | 데이터 저장 영역 |
하나의 프로그램이 실행될 때는 위와 같이 코드 실행 영역과 데이터 저장 영역으로 나뉜다. (모든 프로그래밍 언어의 공통된 메모리 사용 방식이다.)
그리고 객체 지향 프로그램에서는 데이터 저장 영역을 다시 세 개의 영역으로 분할해서 사용한다.
Static 영역 - 클래스들의 놀이터 | |
Stack 영역 - 메서드들의 놀이터 | Heap 영역 - 객체들의 놀이터 |
이 책에서는 위와 같은 메모리 형태를 T자 메모리 구조라고 지칭하였다.
main() 메서드와 T자 메모리
프로그램의 실행 시작 지점인 main() 메서드 먼저 살펴보자.
- main() 메서드가 실행될 때 T 메모리에서는 어떤 일이 일어날까?
- JRE는 먼저 프로그램 안에 main() 메서드가 있는지 확인한다. 만약, main() 메서드의 존재가 확인되면, JRE는 프로그램 실행을 위한 사전 준비(JVM 부팅)를 시작한다.
- JVM이 부팅되면 목적 파일(.class)을 받고 그 파일을 실행한다. JVM이 제일 먼저하는 일은 전처리 과정이다. 전처리 과정은 다음과 같다.
- 모든 자바 프로그램이 반드시 포함하게 되는 패키지인 java.lang 패키지를 T 메모리의 static 영역에 놓기
- JVM은 개발자가 작성한 모든 클래스와 import package 역시 static 영역에 가져다 놓기
- 전처리 과정이 끝나면, main() 메서드는 stack frame 영역에 할당된다. (중괄호를 만날 때마다 stack frame이 생긴다. - 클래스 중괄호는 제외)
- 메서드 인자인 args를 저장할 변수 공간을 stack frame의 제일 밑에 할당한다. (메서드 인자들의 공간 할당)
Stack Frame 같은 경우는 중괄호가 닫히면 소멸된다. 그리고 main() 메서드가 끝나면, JRE는 JVM을 종료하고 JRE 자체도 운영체제 상의 메모리에서 사라진다.
+) JVM 부팅과정은 클래스 로딩 - 바이트코드 검증 - 인터프리터 및 JIT 컴파일 준비로 이루어진다. (대충 이곳에서 알 수 있다.)
변수는?
그럼 만약, main 메서드 안에 변수를 선언하면 어떻게 될까?
우선, 생각해볼 수 있는 것은 main() 메서드 내부이니.. main 메서드의 Stack Frame 내에 생길 것이다.
여기서 한 발짝 더 나아가 보면 재밌는 사실을 알 수 있다.
위에서 중괄호를 만날 때마다 Stack Frame이 생긴다고 했다. (클래스 제외)
그럼 main() 메서드 내부에 또 중괄호를 생성하면? 당연히, Stack Frame이 생긴다.
그리고, 여기서 main() 메서드의 중괄호가 닫히기 전에 중괄호가 닫힌다면? 생성되었던 Stack Frame이 사라진다.
(오.. 머릿속에 그려지는 것이 이해가 정말 잘 되었다. 이 책을 읽으면서 책의 장점이라고 생각했다.)
그럼, main() 메서드 내에서도 중괄호를 기준으로 선언된 변수를 사용할 수 있는 범위도 달라진다는 것을 알 수 있다.
pulic class Main {
public static void main(String[] args) {
int i = 10;
int k = 1;
if (i == 10) {
int m = i + 5;
}
// k = m + i;
}
}
위의 예시를 보자. m을 사용하지 못하는 이유는 m은 if 문의 Stack Frame에 있기 때문이다.
따라서, k = m+i 까지 가기 전에 if 문의 Stack Frame이 소멸되게 된다.
외부 Stack Frame에서 내부 Stack Frame의 변수에 접근은 불가, 내부에서 외부는 가능
조금 더 생각해보자.
그럼, 변수는 Stack 영역에만 있을 수 있을까? 아니다.
변수는 Static, Stack, Heap 모두에 있을 수 있다. 그리고 이에 따라 불리는 명칭도 다르다.
- 지역 변수는 Stack 영역의 변수로 Stack Frame 안에서 생성, 소멸 된다.
- 클래스 멤버 변수는 Static 영역의 변수로, Static 영역에 한 번 생기면 JVM이 종료될 때까지 고정된 상태로 있는다.
- 객체 멤버 변수는 Heap 영역의 변수로, GC에 의해 소멸된다.
메서드는?
이번에는 메서드 호출 과정에서의 메모리 사용을 살펴보자.
사실 Java는 Call by Value로만 동작한다고 한다. (더 자세한 것은 참고..)
여기서는 가볍게 살펴보자.
pulic class Main {
public static void main(String[] args) {
int i = 5;
int m;
m = square(i);
}
private static int square(int i) {
int result;
i = 25;
result = i;
return result;
}
}
여기서 주목할 부분은 i 변수이다. 이름은 같지만, 사실 별도의 공간에 있는 다른 변수이다. (Call By Value이기 때문)
따라서, squre() 메서드에서 i에 어떤 짓을 해도 main()의 i에는 변화가 없다.
음.. 또 조금만 더 생각해보자.
위의 예시에서 main() 메서드의 지역 변수와 squre() 메서드의 지역 변수를 봤을 때, 서로의 지역 변수에는 접근을 하지 못할까? (main에서 square, square에서 main)
답은 못한다이다.
이는 메서드는 입력 값들과 반환 값에 의해서만 값이 전달될 뿐, 서로의 지역 변수는 못보게 되어있다. (블랙박스화)
전역 변수와 멀티 스레드
그럼 전역 변수(static)은 어떻게 동작할까?
전역 변수는 static 영역에 배치될 때, 그 안에서 클래스의 멤버로 공간을 만들어서 저장된다.
따라서, 지역 변수와 전역 변수에 대해서 다음과 같이 정리해볼 수 있다.
- 지역 변수 : Stack Frame에 종속적인 지역 변수
- 전역 변수 : Stack Frame에 독립적인 전역 변수
멀티 스레드와 멀티 프로세스에 대해서도 잠깐 알아보자.
멀티 스레드는 Stack 영역을 스레드 개수만큼 분할해서 사용하는 것이다. (static, heap은 공유)
반면, 멀티 프로세스는 다수의 T 메모리를 갖는다. (stack, static, heap 모두 별개)
자바에서 Servlet은 요청당 스레드를 생성한다. 즉, 동일한 프로세스 내에서 여러 요청을 처리하는 스레드들이 실행되며, Static, Heap 영역을 공유한다.
그럼, 멀티 스레드에서의 전역 변수 사용 문제를 알아보자.
- 2개의 스레드로 구성된 프로그램이 있다고 할 때,
- 프로그램 1이 전역 변수 A에 10을 할당하고 2에게 제어권이 넘어갔다.
- 프로그램 2가 20을 할당한다. 다시 1에게 제어권이 넘어간다.
- 1의 입장에서는 갑자기 A에 20이 할당된 상황이다.
한 스레드가 수정한 값이 다른 스레드에도 영향을 미치는 문제이며, Race Condition이라고 한다.
사실, 위와 같은 상황은 lock을 걸어서 방지할 수 있다. 하지만, lock을 거는 순간 멀티 스레드의 장점이 사라진다. (동기화로 인해 스레드들이 순차적으로 실행되어 멀티 스레드의 장점인 동시성이 사라진다.)
+) 필드, 속성, 함수, 메서드
객체 지향에서의 필드, 속성, 함수, 메서드의 의미를 알아보자.
- 필드 : 클래스나 객체의 data를 담는 변수이다. 필드는 클래스 내에 선언, 객체가 생성될 때 메모리에 할당된다. (private으로 선언하고, getter, setter로 접근)
- 속성 : 필드에 대한 접근자 메서드 (getter, setter), 필드에 대한 접근 및 수정 기능을 제공하는 인터페이스
- 함수 : 특정 작업을 수행하는 독립적인 코드 블록, 클래스에 속하지 않으며 호출 가능한 단위이다.
- 메서드 : 클래스에 속하는 함수, 특정 객체와 연관된 함수, 객체의 상태(필드 / 속성)를 다루는 기능 담당
책을 읽으니 머리에 있는 지식들이 차곡차곡 정리되는 느낌이다..📖📖
'📖 책책책 책을 읽읍시다. 📖 > 자바 객체 지향의 원리와 이해' 카테고리의 다른 글
Chapter 6. 스프링이 사랑한 디자인 패턴 (1) | 2024.12.03 |
---|---|
Chapter 5. 객체 지향 설계 5원칙 - SOLID (0) | 2024.11.26 |
Chapter 4. 자바가 확장한 객체 지향 (0) | 2024.11.26 |
Chapter 3. 자바와 객체 지향 (1) | 2024.11.25 |