자바와 절차적/구조적 프로그래밍
자바 프로그램의 개발과 구동
현실 세계 vs. 가상 세계 | 현실 세계 | 가상 세계(자바 월드) | | |–|–|–| | 소프트웨어 개발 도구 | JDK - 자바 개발 도구 | JVM용 소프트웨어 개발 도구 | | 운영체제 | JRE - 자바 실행 환경 | JVM용 OS | | 하드웨어 - 물리적 컴퓨터 | JVM - 자바 가상 기계 | 가상의 컴퓨터 |
- JDK는 자바 소스 컴파일러인 javac.exe를 포함
- JRE는 자바 프로그램 실행기인 java.exe를 포함
- Write Once Run Anywhere
객체 지향 프로그램의 메모리 사용 방식
자바에 존재하는 절차적/구조적 프로그래밍의 유산
- 절차적 프로그래밍:
goto
를 쓰지 말 것. 자바는goto
를 사용하지 못하도록 예약어로 등록함 - 구조적 프로그래밍: 함수 사용 권장
- 중복 코드를 한 곳에 모아 관리
- 논리를 함수 단위로 분해하여 이해하기 쉬운 코드 작성
- 공유 사용 시 문제가 발생하기 쉬운 전역 변수보다는 지역 변수 사용 권장
- 함수(Function)와 메서드(Method)의 차이
- 절차적/구조적 프로그래밍에서는 함수, 객체 지향에서는 메서드
- 메서드는 반드시 클래스 정의 안에 존재해야 함
import
문은 단순한 편의 기능
- 자바의 예약어 중 절반 이상(continue, for, switch, default, goto, boolean 등)이 절차적/구조적 프로그래밍의 유산
다시 보는 main() 메서드: 메서드 스택 프레임
public class Start {
public static void main(String[] args) {
System.out.println("Hello OOP!!!");
}
}
- JRE는 프로그램 안에
main()
메서드가 있는지 확인 main()
메서드가 확인되면 JRE는 JVM을 부팅, JVM은 전처리 시작- java.lang 패키지를 T 메모리의 스태틱 영역에 배치
- 개발자가 작성한 모든 클래스와 임포트 패키지를 스태틱 영역에 배치
- 여는 중괄호를 만날 때마다 스택 프레임이 스택 영역에 할당됨
- 메서드의 인자
args
를 저장할 변수 공간을 스택 프레임의 맨 밑에 배치 - 구문 실행은 T 메모리 바깥에서 일어나므로 구문 실행 시 T 메모리에는 변화가 없음
- 닫는 중괄호를 만날 때마다 스택 프레임이 소멸됨
main()
메서드가 종료되면 JRE는 JVM을 종료, JRE도 운영체제 메모리에서 제거됨
변수와 메모리: 변수! 너 어디 있니?
public class Start2 {
public static void main(String[] args) {
int i;
i = 10;
double d = 20.0;
}
}
- 변수
i
와d
는main()
메서드 스택 프레임 내에 저장됨 - 선언만 하고 초기화되지 않은 변수를 사용할 경우 자바 컴파일러(javac)는 경고 메시지를 보냄
블록과 메모리: 블록 스택 프레임
public class Start3 {
public static void main(String[] args) {
int i = 10;
int k = 20;
if(i == 10) {
int m = k + 5;
k = m;
} else {
int p = k + 10;
k = p;
}
//k = m + p;
}
}
if
를 만날 경우main()
스택 프레임 내에 새로운 스택 프레임이 중첩되어 생성됨- 변수
m
은 새로운 스택 프레임 내부에 존재하고if
문의 닫는 중괄호를 만날 때 소멸됨 - 주석을 해제할 경우 변수
m
과p
는 T 메모리 내에 존재하지 않으므로 컴파일 오류가 발생함
지역 변수와 메모리: 스택 프레임에 갇혔어요!
- 지역 변수: 스택 영역에 존재, 스택 프레임이 사라지면 함께 사라짐
- 클래스 멤버 변수: 스태틱 영역에 존재, JVM이 종료될 때까지 존재
- 객체 멤버 변수: 힙에 존재, 가비지 컬렉터에 의해 회수될 때까지 존재
- 외부 스택 프레임에서 내부 스택 프레임의 변수에 접근하는 것은 불가능하나 그 역은 가능
메서드 호출과 메모리: 메서드 스택 프레임 2
public class Start4 {
public static void main(String[] args) {
int k = 5;
int m;
m = square(k);
}
private static int square(int k) {
int result;
k = 25;
result = k;
return result;
}
}
- 메서드 호출이 일어나면 무조건 호출되는 메서드의 스택 프레임이 T 메모리 스택 영역에 새로 생성됨
main()
메서드 내에서는square()
메서드 내에 존재하는 지역변수에 접근할 수 없음- 자바에서는 포인터를 사용할 수 없으므로 메서드 스택 프레임 사이에 변수를 참조할 수 없음
- 메서드를 호출하면서 인자로 전달되는 것은 변수 자체가 아니라 변수가 저장한 값 (Call by Value)
전역 변수와 메모리: 전역 변수 쓰지 말라니까요!
public class Start5 {
static int share;
public static void main(String[] args) {
share = 55;
int k = fun(5, 7);
System.out.println(share);
}
private static int fun(int m, int p) {
share = m + p;
return m - p;
}
}
share
변수는static
키워드가 붙어 있으므로 T 메모리의 스태틱 영역에 저장되는 전역 변수- 전역 변수는 여러 메서드에서 변경할 수 있으므로 저장되어 있는 값을 파악하기 어려움
- 전역 변수는 읽기 전용으로 값을 공유하는 상수로 사용하는 것이 좋음
멀티 스레드 / 멀티 프로세스의 이해
- 멀티 스레드: T 메모리의 스택 영역을 스레드 개수만큼 분할해서 사용
- 하나의 스레드에서 다른 스레드의 스택 영역에는 접근할 수 없지만 스태틱 영역과 힙 영역은 공유
- 멀티 프로세스: 다수의 T 메모리를 가짐
- 각 프로세스의 T 메모리는 고유의 공간이므로 프로세스끼리 참조할 수 없음
- 멀티 프로세스는 멀티 스레드에 비해 메모리 사용량이 커짐
- 요청당 스레드(Servlet)가 요청당 프로세스(CGI)보다 효율적
- 스태틱 영역에 있는 쓰기 가능한 전역 변수를 스레드가 사용할 경우 스레드 안정성이 깨짐