이전까지의 스택 프레임은 Main 스택 프레임에서 벌어지는 일에 대해서 설명했으나, 오늘 설명할 스택 프레임은 Main 스택 프레임 밖에서 생성되는 스택 프레임을 설명할 것이다.
일단 다음 코드부터 읽어보자
public class Main {
public static void main(String[] args) {
int number = 5;
number = square(number);
System.out.println(number);
}
public static int square(int n) {
int result = n * n;
return result;
}
}
n의 제곱값을 반환하는 함수 square를 선언했다. 메서드를 호출하면 T메모리에는 Main 스택 프레임 바깥에 호출한 메서드의 스택 프레임이 할당된다.
square 스택 프레임은 인자로 n을 받아서 내부적으로 값을 따로 저장한다. square 스택 프레임의 n의 변화는 main 스택 프레임의 number에 아무런 영향을 주지 않는다. 이러한 메서드 호출을 Call by Value(값에 의한 호출)이라고 한다.
Call by Reference(참조에 의한 호출)
자바는 메서드 간의 참조 호출을 엄격하게 금지하고 있다. 자바는 포인터의 사용을 철저하게 숨겨놓았기 때문에, Reference 호출이 불가능하다. 그렇다면 Swap 함수는 어떻게 구현할 수 있을까?
일단, Swap이 이루어지려면 포인터나 Reference를 이용해야 한다. 그런데 그것은 미리 말했다시피 불가능하다.
하지만, 그건 Stack 프레임에서나 말이고 Heap 영역에 저장된 것들은 스왑이 가능하다. 즉 객체의 스왑은 가능하다.
public class Main {
int num;
public static void main(String[] args) {
Main a = new Main(3);
Main b = new Main(5);
swap(a, b);
System.out.println(a.num + " " + b.num);
}
public Main(int a){
this.num = a;
}
public static void swap(Main a, Main b) {
int temp = a.num;
a.num = b.num;
b.num = temp;
}
}
위의 코드를 천천히 읽어보고 이해하기를 바란다.
+) 다른 방법도 존재한다. 편법을 이용하는 방법이다.
public class Main {
public static void main(String[] args) {
int a = 3;
int b = 5;
b = swap(a, a = b);
System.out.println(a + " " + b);
}
public static int swap(int a, int b) {
return a;
}
}
이 코드도 이해해보길 바란다.
전역 변수 쓰지마세요!
로직을 열심히 잘 짜면 전역변수를 써도 되는거 아닌가? 라고 생각할 수 있지만 아니다.
내 생각은 전역변수는 무조건 문제를 발생시킨다. 멀티 쓰레딩 환경에서 말이다.
멀티 쓰레딩은 운영체제라는 과목에서 자세히 다루겠지만, 이 문제에 대해서 간단히 말하면 하나의 공유 자원을 여러 사람이 같이 사용하는 상황을 뜻한다.
쓰레딩의 컨텍스트 스위칭의 경우 아무때나 벌어진다라고 생각하면 된다. 즉, 값이 반영이 되지도(혹은 로직이 끝나지도) 않았는데 문맥 교환이 일어나고 이는 예기치 않은 오류를 발생시킨다.
Lock을 사용해 문제를 해결할 수도 있지만, 그러면 멀티 쓰레딩의 이점이 파괴된다. 웹 백엔드 개발이 꿈이라면 꼭 생각해보아야할 문제이다.
'Study > OOP with Java' 카테고리의 다른 글
[OOP with JAVA] 1. 객체 지향 프로그래밍을 시작하며 (0) | 2023.07.20 |
---|