모각소 3(java의 메모리 구조)

LEEHYUNJE·2024년 1월 16일
0
post-thumbnail

모각소 2주차 1번째
오늘은 "객체지향 프로그래밍 및 실습"시간에 자세하게 배우지 않았던 java의 메모리 구조에 대해서 공부해 보았다.
CS관련 지식의 중요성은 개발에 대해서 배울 때마다 항상 느끼고 있으므로, 잊지 않게 꾸준히 복습해놓도록 하자.

자바 메모리 구조


자바의 메모리 구조는 크게 메서드 영역, 스택 영역, 힙 영역 3개로 나눌 수 있다.

  • 메서드 영역: 클래스 정보를 보관(붕어빵 틀)
  • 스택 영역: 실제 프로그램이 실행되는 영역, 메서드를 실행할 때마다 하나씩 쌓인다
  • 힙 영역: 메모리의 동적할당을 담당한는 곳으로, java에서는 인스턴스가 생성되는 영역이다.(붕어빵 틀로 찍어낸 붕어빵)

좀 더 자세하게 들어가보면

  • 메서드 영역: 메서드 영역은 프로그램을 실행하는데 필요한 공통 데이터를 관리한다. 이 영역은 프로그램의 모든 영역에서 공유된다.
    • 클래스 정보: 클래스의 실행 코드(바이트 코드), 필드, 메서드와 생성자 코드등 모든 실행 코드가 존재한다.
  • static 영역: 'static' 변수들을 보관한다. 뒤에서 자세히 설명한다.
  • 런타임 상수 풀: 프로그램을 실행하는데 필요한 공통 리터럴 상수를 보관한다. 예를 들어서 프로그램에 "hello" 라는 리터럴 문자가 있으면 이런 문자를 공통으로 묶어서 관리한다. 이 외에도 프로그램을 효율적으로 관리하기 위한 상수들을 관리한다.

##참고
스택 영역은 더 정확히는 각 쓰레드별로 하나의 실행 스택이 생성된다. 따라서 쓰레드 수 만큼 스택 영역이 생성되는 것이다.
-> 시스템 프로그래밍 및 실습에서 배웠던 멀티스레딩을 잘 생각하자. stack 영역은 각 프로세스마다 할당이 되었지만, text, data, heap 영역은 공유해서 사용했다.

즉 메서드를 호출하면, 메서드 영역으로 점프하여 지정한 메서드가 실행되는 모습이다.

스태틱 변수

위에 나왔던 자바 메모리 구조에서 static 영역은 메서드 영역에 존재하는 것을 보았을 것이다.
하지만 내가 들었던 의문은

결국 지역 변수로 선언이 되니, 인스턴스로 선언되면 heap영역, 메서드로 호출되어 사용되면 stack 영역으로 들어가야하는 것이아닌가?

라는 생각을 했다.

이에 대한 답변으로 먼저 간단한 코드를 확인하겠다.

public class Data3 {
public String name;
 public static int count; //static
 public Data3(String name) {
 this.name = name;
        count++;
    }
 }

Data3 클래스 코드

  • static int count는 Data3 클래스의 생성자가 선언 될 때마다 1씩 증가한다.
  • 이때 static이 붙은 변수나, 메서드를 정적 변수,정적 메서드 또는 클래스 변수, 클래스 메서드라고 한다.
public class DataCountMain3 {
 public static void main(String[] args) {
 Data3 data1 = new Data3("A");
 System.out.println("A count=" + Data3.count);
 Data3 data2 = new Data3("B");
 System.out.println("B count=" + Data3.count);
 Data3 data3 = new Data3("C");
 System.out.println("C count=" + Data3.count);
 }
}

위 코드는 3번의 생성자를 호출하여 3개의 인스턴스를 만들어준 모습이다.

실행 결과

위 결과로 알 수 있는 점은 static을 사용하면 인스턴스가 다른 객체에서도 공유된 변수를 구현할 수 있다는 것이다.


1. 개발자가 인스턴스를 생성할 때마다, 각 인스턴스에 저장되어 있는 count++를 실행
2. count 는 static으로 선언 된 클래스 변수이므로, 메서드 영역에 접근하여 count의 수를 증가

즉, 모든 인스턴스에서 같은 주소공간을 가르키는 변수를 사용해야하기 때문에 메서드영역에 저장한다. 라고 답변하면 되겠다.

스태틱 메서드

같은 느낌으로 정적 메서드 또한 메서드 영역 중 static 영역에 저장되어 있으므로 클래스.(메서드이름)으로 바로 사용할 수 있다.
하지만, 정적 메서드는 언제나 사용할 수 있는 것이 아니다.

정적 메서드 사용법

  • static 메서드는 static만 사용할 수 있다.
    • 클래스 내부의 기능을 사용할 때, 정적 메서드는 static이 붙은 정적 메서드나 정적 변수만을 사용할 수 있다. - >main 메서드가 생성되어 있는 class에서 호출할 메서드를 생성할 때 정적 메서드로 선언 하는 이유이다.
    • 클래스 내부의 기능을 사용할 때, 정적 메서드는 인스턴스 변수나, 인스턴스 메서드를 사용할 수 없다.
  • 반대로 모든 곳에서 static을 호출 할 수 있다.
    • 정적 메서드는 공용 기능이다. 따라서, 접근 제어자만 허락한다면 클래스를 통해 모든 곳에서 static을 호출할 수 있다.

왜? 정적 메서드는 인스턴스의 기능을 사용할 수 없을 까?

package static2;
public class DecoData {
 	private int instanceValue;
 	private static int staticValue;
 	public static void staticCall() {
 
 //instanceValue++; //인스턴스 변수 접근, compile error
 //instanceMethod(); //인스턴스 메서드 접근, compile error
 
 	staticValue++; //정적 변수 접근
 	staticMethod(); //정적 메서드 접근
 }
 public void instanceCall() {
 
 	instanceValue++; //인스턴스 변수 접근
 	instanceMethod(); //인스턴스 메서드 접근
 	staticValue++; //정적 변수 접근
 	staticMethod(); //정적 메서드 접근
 
 }
 
 private void instanceMethod() {
 
 	System.out.println("instanceValue=" + instanceValue);
 }
 private static void staticMethod() {
 	System.out.println("staticValue=" + staticValue);
 }
}
  • 위 코드에서 주석이 된 부분은 에러가 나는 코드이다.

정적 메서드가 인스턴스의 기능을 사용할 수 없는 이유

정적 메서드는 클래스의 이름을 통해 바로 호출할 수 있다. 그래서 인스턴스처럼 참조값의 개념이 없다. 특정 인스턴스의 기능을 사용하려면 참조값을 알아야 하는데, 정적 메서드는 참조값 없이 호출된다. 따라서 정ㄹ적 메서드 내부에서 인스턴스 변수나 인스턴스 메서드를 사용할 수 없다.

##참고: 객체의 참조 값을 직접 매개변수로 전달하면, 정적 메서드도 인스턴스의 변수나 메서드를 호출 할 수 있다.

모각소 소감

오늘은 java 메모리 처리에 대해서 공부했다. 면접 때 CS지식이나 언어에 대한 이해가 필요하다고 하는 것에 대해서 처음에 이해가 안갔지만(개발만 잘하면 될 줄 알았다), 모각소를 통해서 같이 공부해나갈때마다 막히는 부분을 보면 결국 처음보는 문법이나 CS 지식 부족이 문제였다. 주중에 혼자 개발하고, 모각소 하는 시간은 언어에 대한 이론 공부를 하는 것도 서로 공유할 수 있을 것 같아서 좋겠다는 생각을 했다. 오늘도 잘 견뎌냈다.

profile
현재진행중

0개의 댓글