ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 멤버변수의 종류와 자바의 메모리 구조(메서드, 스택, 힙)
    JAVA/개념 - 김영한 강의 2024. 9. 15. 09:49

     

    멤버 변수의 종류

    1. 인스턴스 변수: static이 붙지 않은 멤버 변수 

    • 인스턴스를 만들 때 마다 새로 만들어진다. 
    class Dog {
        String name;
        int age;
    
        void bark() {
            System.out.println(name + " is barking!");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            // 클래스 Dog의 인스턴스를 생성
            Dog myDog = new Dog();  // myDog는 Dog 클래스의 인스턴스
            myDog.name = "Buddy";
            myDog.age = 3;
    
            // 인스턴스를 통해 메서드 호출
            myDog.bark();  // "Buddy is barking!" 출력
        }
    }

     

     

    * 인스턴스 변수를 사용할 때 주의할점!

    캡슐화 (Encapsulation)

    • 객체의 데이터를 안전하게 보호: 클래스 내부의 데이터 멤버를 private으로 선언하고, 외부에서 접근할 때는 getter와 setter 메서드를 통해 접근하는 것이 좋다. 이를 통해 데이터를 직접 수정하는 것을 방지하고, 객체의 무결성을 유지할 수 있다.
    public class Person {
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

     

     

    2. 클래스 변수: static이 붙은 멤버 변수

    • 클래스 변수, 정적 변수, static 변수 등으로 부른다. 이 용어를 모두 사용한다.
    • static이 붙은 멤버 변수는 인스턴스와 무관하게 클래스에 바로 접근해서 사용할 수 있고, 클래스 자체에 소속되어 있다. 따라서 클래스 변수라고 한다. 
    • 클래스 변수는 자바 프로그램을 시작할 때 딱 1개가 만들어진다. 인스턴스와는 다르게 보통 여러곳에서 공
      유하는 목적으로 사용된다.

     

     

     

    static 변수는 클래스를 통해 바로 접근할 수도 있고, 인스턴스를 통해서도 접근할 수 있다.

     

     

    public class Data3 { public String name;
     	public static int count; //static
     		public Data3(String name) {
     		this.name = name;
     		count++;
     		}
     }
    public class DataCountMain3 {
     	public static void main(String[] args) {
            
     		//인스턴스를 통한 접근
    		Data3 data4 = new Data3("D");
    		System.out.println(data4.count);
            
    		//클래스를 통합 접근
    		System.out.println(Data3.count);
     		}
    	}

     

     

    • data4.count : 인스턴스를 통한 접근
      • 추천하지 않음. 인스턴스 변수에 접근하는 것 같아서
    • Data3.count : 클래스를 통한 접근
      • 정적 변수는 클래스에서 공용으로 관리하기 때문에 클래스를 통해 접근하는 것이 더욱 명확하게 느껴진다. 

     

     

     

    자바 메모리 구조

     

    1. 메서드(Method) 영역

    메서드 영역은 JVM이 시작될 때 생성되며, 프로그램을 실행하는데 필요한 공통 데이터를 관리하여 프로그램의 모든 영역에서 공유한다. 

    • 클래스 정보: 클래스의 실행코드(바이트 코드), 메서드, 생성자 코드 등 모든 실행코드가 존재
    • 정적 변수: static 변수
    • 상수 풀(Constant Pool): 클래스와 메서드에 사용되는 상수 값들(문자열 상수, 숫자 상수 등)이 저장된다. 

     

    public class Person {
        public static String species = "Human"; // 정적 변수
        public void sayHello() {
            System.out.println("Hello");
        }
    }

     

    • Person 클래스의 메타데이터와 species 정적 변수는 메서드 영역에 저장된다. 
    • sayHello() 메서드의 바이트코드도 메서드 영역에 저장된다. 

    *static이 붙은 정적 변수에 접근라혀면 '클래스명 + .(dot) + 변수명'으로 접근하면 된다. 

     

    메서드 영역의 특징:

    • 프로그램이 종료될 때까지 메모리에 유지된다.
    • 모든 쓰레드가 공유하는 영역이다.
    • 객체가 생성될 때, 인스턴스 변수에는 힙 메모리가 할당되지만, 메서드에 대한 새로운 메모리 할당은 없다. 메서드는 메서드 영역에서 공통으로 관리되고 실행된다.

     

     

     

    2. 스택(Stack) 영역

    스택 영역은 각 쓰레드마다 별도로 할당되는 메모리 공간으로, 메서드 호출과 지역변수(매개변수 포함)를 관리한다.  메서드가 호출될 때마다 프레임(Stack Frame)이 생성되고, 메서드 실행이 끝나면 해당 프레임이 제거된다. 

    • 지역 변수: 메서드 내부에서 선언된 변수는 스택 영역에 저장된다. 
    • 메서드 호출 시 생성되는 데이터: 각 메서드 호출 시 생성되는 매개변수, 반환 주소, 임시 데이터 등이 저장된다. 
    • LIFO 구조: 스택 영역은 후입선출(Last In First Out, LIFO) 구조로, 가장 나중에 호출된 메서드가 먼저 종료된다. 
    public class Example {
        public void methodA() {
            int x = 10;   // x는 스택 영역에 저장
            methodB();
        }
        public void methodB() {
            int y = 20;   // y는 스택 영역에 저장
        }
    }
    • methodA()가 호출되면 스택 프레임이 생성되고, x 변수는 스택에 저장
    • methodB()가 호출되면 새로운 스택 프레임이 생성되고, y 변수는 스택에 저장
    • methodB()가 종료되면 해당 스택 프레임이 제거되고, 다시 methodA()의 스택 프레임으로 돌아온다. 

     

    스택 영역의 특징:

    • 메서드의 실행 흐름을 관리한다. 
    • 스택 영역에 저장된 데이터는 메서드 호출이 끝나면 자동으로 소멸된다. 
    • 쓰레드별로 독립적인 영역입니다. 각 쓰레드는 자신의 스택을 가지고, 서로 공유하지 않는다. 

     

     

     

    3. 힙(Heap) 영역

    힙 영역은 JVM이 동적으로 생성한 객체(인스턴스)를 저장하는 공간이다. 자바에서 new 키워드를 통해 생성된 객체는 모두 힙 영역에 저장되며, 객체의 실제 데이터(필드 값 등)가 힙에 존재한다. 

    • 동적 메모리 할당: 힙 영역은 런타임 중에 동적으로 할당된 객체를 저장한다. 
    • 참조 변수: 객체를 참조하는 참조 변수는 스택 영역에 저장되며, 그 변수가 가리키는 실제 객체는 힙 영역에 저장된다. 
    • 가비지 컬렉션: 더 이상 사용되지 않는 객체는 가비지 컬렉터에 의해 제거된다. 
    public class Person {
        String name;
        public Person(String name) {
            this.name = name;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Person person = new Person("Alice");  // 힙 영역에 Person 객체 생성
        }
    }
    • new Person("Alice")를 호출하면, Person 객체는 힙 영역에 저장됩니다.
    • person 변수는 스택 영역에 저장되지만, 이는 힙에 있는 Person 객체를 참조하는 변수입니다.

    힙 영역의 특징:

    • 힙에 저장된 객체는 명시적으로 삭제되지 않고, 더 이상 참조되지 않을 때 가비지 컬렉션에 의해 자동으로 정리됩니다.
    • 모든 쓰레드가 공유하는 영역입니다.
    • 큰 객체나 많은 메모리를 요구하는 데이터는 주로 힙 영역에 저장됩니다.

     

    자바 메모리 구조 간 상호작용

    • 스택에서 생성된 참조 변수에 있는 객체를 가리킵니다.
    • 메서드 영역에는 클래스와 정적 멤버 정보가 저장되어 있으며, 이 정보는 모든 쓰레드에서 공유됩니다.
    • 힙에 있는 객체는 참조 변수가 더 이상 없으면, 가비지 컬렉션에 의해 메모리에서 해제됩니다.

    자바 메모리 구조 요약

    1. 메서드 영역: 클래스 메타데이터, 정적 변수, 상수 및 메서드 코드 저장.
    2. 스택 영역: 메서드 호출 시 필요한 지역 변수, 매개변수, 반환 값 등이 저장되며, 각 쓰레드별로 독립적.
    3. 힙 영역: 런타임 시 동적으로 생성된 객체가 저장되며, 가비지 컬렉션에 의해 관리됨.

    댓글

Designed by Tistory.