public class VendingMachine {
public String pushProductButton(int menuId) {
System.out.println(menuId +"를 전달받았습니다.");
return "콜라";
}
public static void printVersion() {
System.out.println("V1.0");
}
}
public class Main {
public static void main(String[] args) {
VendingMachine.printVersion();
VendingMachine vm = new VendingMachine();
VendingMachine vm2 = new VendingMachine();
String product = vm.pushProductButton(100);
System.out.println(product);
String product2 = vm2.pushProductButton(200);
System.out.println(product2);
}
}
다음과 같이 하나의 프로젝트에 두개의 java파일이 있습니다.
터미널을 이용해 실행하는 경우 다음과 같습니다.
1.실행
//터미널
javac VendingMachine.java //자바컴파일러가 컴파일 -> .class파일 생성
javac Main.java //자바컴파일러가 컴파일 -> .class파일 생성
java Main // 실행(main 메서드가 있는 파일의 main 메서드를 JVM(JavaVirtualMachine)이 실행)
JVM은 Main이라는 클래스를 어디서 찾아서 실행하는가?
자바는 클래스를 사용하려고 탐색을 할 때, JVM 혹은 자바 컴파일러가 사용하는 파라미터로
클래스나 패키지를 찾을 때 기준이 되는 CLASSPath를 이용해 class의 위치를 찾습니다.
소스 코드(.java)를 컴파일하면 바이트코드(.class)로 변환되고 JVM이 바이트코드로 된 파일을 실행하려면 그 경로를 찾아야 하는데 이 바이트코드(.class파일)까지의 경로를 클래스패스라고 한다.
이렇게 Main 클래스를 JVM은 읽어드리고 읽어드릴 클래스 정보를 PERM 메모리 영역에 저장합니다.
JVM PERM 메모리에 올라가 있는 Main 클래스에서 main 메서드를 찾습니다.
이후, 해당 main메서드를 Java Stack(First In First Out 방식)에 넣어줍니다.
정리하면 다음과 같습니다.
.java 파일 작성 → --javac compiler-- → 컴파일 → 자바 소스코드생성(.class파일) → JVM시작(CLASSPATH를 이용)→ Main 클래스 실행→ JVM이 main 메서드 검색 → main 메서드 실행
2. main 메서드 실행
1. main 메서드 실행: main 메서드에 선언된 지역 변수들과 매개변수인 String[] args는 Java Stack의 StackEntry에 저장됩니다. 이때, 매개변수 args는 Heap 메모리에 생성된 String[] 인스턴스를 참조합니다.
2. printVersion() 메서드가 호출: printVersion() 메서드가 호출되면, 새로운 StackEntry가 Java Stack에 추가됩니다. 이 StackEntry는 prinVersion()메서드의 지역 변수들을 포함하며, 메서드 실행이 종료되면, 해당 StackEntrty는 Java Stack에서 제거됩니다.
3. VendingMachine 객체 생성: VendingMachine vm = new VendingMachine(); 코드가 실행되면 VendingMachine 클래스의 인스턴스가 힙 메모리에 생성되고, vm (참조)변수는 이 인스턴스를 참조합니다. VendingMachine vm2 = new VendingMachine(); 또한 인스턴스가 Heap 메모리에 생성되고 vm2(참조)변수가 이를 참조합니다.
4. PushProductButton 메서드 호출 및 실행: pushProductButton() 메서드가 호출되면 새로운 Stack Entry가 생성됩니다. 이 메서드내에 선언된 지역변수 menuId는 이 Stack Entry에 저장됩니다. 메서드가 종료되면 이 StackEntry는 Java Stack에서 제거됩니다.
5. 값 반환 및 출력: pushProductButton() 메서드에서 반환한 값이 product 변수에 저장되고, 이값이 출력됩니다. 이 과정은 product2에서도 반복됩니다.
6. main 메서드의 종료: main 메서드의 실행이 종료되면, main 메서드의 StackEntry가 Java Stack에서 제거됩니다.
7. JVM과 프로그램의 종료: Java Stack에 더 이상 StackEntry가 없으면 JVM이 종료되고 프로그램이 종료됩니다.
- 메서드가 호출될 때마다 해당 메서드의 Stack Entry가 Java Stack에 추가됩니다. 메서드 내의 지역 변수들은 이 Stack Entry에 저장되며, 메서드 실행이 종료되면 이 Stack Entry는 제거되고 지역 변수들도 사라집니다.
- 만약 pushProductButton() 메서드가 여러 번 실행된다면, 각 호출마다 새로운 menuId 지역 변수가 Stack Entry에 저장됩니다. 각 메서드 호출이 서로 독립적이므로, 각 menuId 변수는 별도의 메모리 영역에 저장됩니다.
'Java > 기초' 카테고리의 다른 글
[Java] JavaIO - (4) Object IO Stream(+깊은복사, 얕은복사) (0) | 2023.10.27 |
---|---|
[Java] JavaIO - (3)Data, ByteArray, StringReaderWriter (0) | 2023.10.27 |
[Java]JavaIO - (2)FileIOStream (0) | 2023.10.25 |
[Java] JavaIO - (1) (0) | 2023.10.25 |
[Java] 상속 - 필드, 메서드 오버라이딩할 때 주의점 (0) | 2023.10.23 |