본문 바로가기

Dev.BackEnd/JAVA

[Java] 자바의 기본적인 이슈들 5가지


#JAVA의 기본적인 이슈들 5가지

1. 다시 자바의 기본으로
JDK(Java Development Kit) : 자바 개발 도구 - JVM용 소프트웨어 개발 도구
JRE(Java Runtime Environment) : 자바 실행 환경 - JVM용 OS
JVM(Java Virtual Machine) : 자바 가상 머신 - 가상의 컴퓨터
JDK를 이용해 개발된 프로그램은 JRE에 의해 가상의 컴퓨터인 JVM 상에서 구동된다.
JDK가 JRE를 포함하고 JRE는 JVM을 포함하는 형태로 배포된다.
JDK는 자바 소스 컴파일러인 javac.exe를 포함하고 있고,
JRE는 자바 프로그램 실행기인 java.exe를 포함하고 있다.



2. 메모리는 어떻게 사용되는가
일반적인 프로그램은 이 프로그램에게 할당된 메모리 영역을 크게 두 가지 영역으로 나누어 사용한다. 하나는 코드 실행 영역이고, 다른 하나는 데이터 저장 영역이다. 객체 지향 프로그램에서는 데이터 저장 영역을 다시 세 개의 영역으로 분할해서 사용한다.
스태틱(static)영역, 스택(stack)영역, 힙(heap)영역

자바 프로그램은 main 메소드에서부터 시작한다.
main()메서드가 실핼될 때 메모리에서는 어떤 일이 일어날까?

일단 JRE는 프로그램 안에 main()메서드가 있는지 확인한다. main()메서드의 존재가 확인되면 JVM에 전원을 넣어 부팅하고 프로그램 실행을 위한 사전 준비에 들어간다. 부팅된 JVM은 목적 파일을 받아 그 목적 파일을 실행한다. JVM은 가장 먼저 java.lang 패키지를 스태틱 영역에 가져다 놓는다.

다음으로 개발자가 작성한 모든 클래스(^)와 import package 역시 스태틱 영역에 가져다 놓는다.(loading) 사실 클래스와 클래스에서 import한 package들은 main() 메소드에서 클래스를 사용할 때( new 키워드를 통한 인스턴스 생성, static 메소드 호출 등) 스태틱 영역에 로드된다. 여기까지가 JVM이 수행하는 전처리 과정이다.

그리고 main 메서드를 만났다.
이 main() 메서드가 실행되기 위해 스택 영역에 스택 프레임을 할당한다. 이 스택 프레임은 메서드를 구현하기 위해 작성한 여는 중괄호를 만날 때마다 하나씩 생기는 것이다. 그리고 넘겨져 들어온 인자를 저장하기 위해 스택 프레임 맨 밑에 확보한다. 그리고 메소드 구현 부에 해당하는 작업을 모두 마치고 닫는 중괄호를 만나면 스택 프레임을 소멸시킨다.

main()메서드는 프로그램의 시작점이자 끝이다. main() 메서드가 끝이 나면 JVM을 종료하고 JRE자체도 운영체제 상의 메모리에서 사라진다,



3. 자바의 각종 변수들, 메소드들은 메모리 상 어디에 위치하는가?
자바의 변수에는 지역 변수, 클래스 멤버 변수, 객체 멤버 변수 세 가지의 변수가 존재한다.
지역 변수는 스택 영역에서 일생을 보낸다. 스택 영역 안에서도 스택 프레임 안에 존재한다. 따라서 스택 프레임이 사라지면 함께 사라진다.
클래스 멤버 변수는 스태틱 영역에 위치한다. JVM에 의해 클래스가 로딩될 때 함께 로딩되며 한 번 자리를 잡으면 JVM이 종료될 때까지 고정된 상태로 위치한다. 멤버 변수 앞에 static keyword가 붙게 되면 클래스 멤버 속성이 된다.
객체 멤버 변수(인스턴스 멤버 변수)는 힙에 위치한다. 객체 멤버 변수들은 GC에 의해 메모리 회수가 이루어지기 전까지 객체와 함께 존재한다. 

자바의 객체 멤버 메서드는 어디에 위치하는가?
객체 멤버 변수와는 달리 메서드는 한 번 로딩되면 인스턴스 모두가 공유하는 코드가 된다. 즉, 인스턴스에 따라 상태가 변화하지 않는다. 그렇기 때문에 static 영역에 로딩된다.


4. 메모리 구조 측면에서의 멀티 스레드와 멀티 프로세스 이해
멀티 스레드의 메모리 모델은 스택 영역을 스레드 개수만큼 분할해서 쓰는 것이다. 멀티 프로세스는 다수의 데이터 저장영역, 즉 프로세스 개수 만큼의 다수의 T메모리를 갖는 구조이다.
멀티 프로세스의 경우, 각 프로세스마다 각각 고유의 공간이므로 서로 참조할 수가 없다. 멀티 스레드는 스택 영역만 분할한 것이기 때문에 하나의 스레드에서 다른 스레드의 스택영역에는 접근할 수 없지만 스태틱 영역과 힙 영역은 공유해서 사용하는 구조이다. 때문에 멀티 프로세스 대비 메모리를 적게 사용할 수 있는 구조이다.



5. 자바는 Call by Value인가 Call by Reference 인가
결론부터 말하자면 자바는 전부 Call by Value이다.
자바에서 Primitive Type은 Call by Value이고, 객체는 Call by Reference이다 라는 글들이 인터넷에서 돌아다니고 있는데, 이는 Call by Reference의 엄밀한 정의를 인지하지 못했기 때문이라고 생각한다. Call by Reference의 정확한 의미는 해당 객체의 주소값을 넘기는 것이다. 주소값을 넘기면 메소드 안에서 넘겨받은 객체의 상태를 변화시킬 수 있다. (여기서 상태란 객체가 가지고 있는 객체 멤버 변수를 말한다.)

이러한 점에서 볼 때, 자바에서 메소드에 객체를 전달하는 것이 마치 Call by Reference로 작동하는 것처럼 보인다. 객체를 전달해주고 메소드 안에서 객체의 상태를 변화시켜주니 메소드 밖에서도 상태가 변화했기 때문이다! 하지만 이것은 말 그대로 CBR로 작동하는 것처럼 보이는 것일 뿐이다. 자바에서는 객체를 전달하더라도 동일한 객체를 가리키는 또다른 레퍼런스를 복사하여 전달한다. 즉, 객체가 실제 저장되어 있는 메모리상의 주소값이 아닌 이 객체를 가리키는 또다른 하나의 레퍼런스 값을 생성하여 그 값을 전달해주는 것이다. 메소드 안에서는 객체를 가리키고 있는 주소’값'을 받은 것이므로 Call by Value가 된다.



end