JVM 이란?
JVM은 java파일을 컴파일/실행 시키기위한 Stack기반 가상머신이다
JAVA와 OS사이에 중개자 역할을 수행하여 JAVA가 OS에 구애받지않고 재사용기능을 가능하게 해준다.그리고 가장 중요한 메모리관리, GC( GarbageCollection)을 수행한다.
메모리 구조
1. Static 영역
이 영역에는 전역변수와 정적 멤버변수(static이 붙은 자료형)을 static 영역에 저장한다. 이 영역의 데이터는 프로그램의 시작부터 종료될때까지 메모리에 남아있게된다.
이 말은 프로그램이 종료될 때 까지 어디서든 사용이 가능하지만 이를 무분별하게 생성하여 사용 할 경우 메모리낭비가 발생 할 수 있다.
2. Stack 영역
이 영역에는 기본 자료형(primitive type)인 int, double, byte, long, boolean 등이 해당되는 지역(매개 변수 및 블럭문)의 데이터 값이 저장되는 공간이다.
해당 메소드가 호출될 때 메모리에 할당되고 종료되면 메모리가 해제된다.
예를 들어서
public class StackAreaEx{
public static void main(String args[]){
int a = 5;
a = 4;
a = 3;
a = 2;
a = 1;
System.out.println(a);
}
}
위 코드에서 a를 처음에 5로 초기화하고 그 뒤로 4,3,2,1로 초기화하면 이 a는 지역변수 이므로 Stack 영역에 저장되며 5,4,3,2 라는 데이터는 지워지고 1이라는 값으로 초기화된다.
이 처럼 Stack 영역은 LIFO ( Last In First Out ) 구조를 가지고 변수에 새로운 값이 들어오면 이 전 데이터는 지워진다.
3. Heap 영역
이 영역에는 참조타입 ( Reference Type )이 저장되는데 이는 Stack 영역에 선언된 변수이름의 참조값이 저장된다.
String a = "Hello";
위 코드에서 String 타입인 변수 a는 Stack 영역에 a가 들어가게되고 Heap 영역에는 그 a를 참조하는 [String]: Hello 형태로 저장된다.
더 나아가서
List<String> list_A = new ArrayList<>();
위 코드에서 list_A라는 변수이름은 Stack 영역에 저장되지만 Heap 영역에는 이 list_A가 List라는것을 참조해주는 List가 Heap 영역에 존재하게된다.
list_A.add("number1");
이 코드는 사실 list_A.add(new String("number1"));와 같다. 여기서 new 키워드는 문자열을 할당하기전에 먼저 heap 영역에 충분한 공간이 있는지 확인 후 할당되게 된다.
학습문제
public class Main {
public static void main(String[] args) {
String s = "hello";
changeString(s);
System.out.println(s);
}
public static void changeString(String param) {
param += " world";
}
}
위 코드에서 출력되는 결과는 결국 hello 이다.
그 이유는 s라는 이름으로 String 타입이 선언되어 Stack에는 s가 Heap에는 String : hello가 존재하게된다
그 다음으로 changeString(String param) 메소드가 호출되는데 매개변수로 s를 받아 호출된다.
이 때 메소드안에서 param이라는 String 타입인 새로운 데이터가 Stack에는 param이 Heap에는 앞에서 선언했던 s의 값을 참조했을뿐인 String : hello가 생성된다.
그러므로 param에 +="world"를 해줘봤자 s는 바뀌지않는것이고 changeString메소드 안에서의 param만 바뀌는 것이다.
그 후 메소드가 종료되면 param은 소멸된다.
저 changeString 메소드에서 param값을 return시켜 s에 넣어주지않는이상 s는 변하지 않는다.