울음참고 개발공부
article thumbnail
728x90

 

 

출처 : https://www.artima.com/insidejvm/ed2/jvm2.html

 

 

 

 

 

자바의 메모리 구조중에 Stack 영역Heap 영역에 대해서 알아보자 

 

 

 

Stack 영역

 

  • 각 메소드가 호출될 때마다 그 메소드 내에서 사용되는 지역 변수(로컬 변수)들이 저장됨
  • 메소드가 끝나면 그 메소드에 대한 스택 영역은 사라짐
  • 일시적인 데이터들(메소드 실행 중에만 유효한 데이터)을 저장하는 공간
  • 빠르게 접근 가능

 

public class Example {
    public static void main(String[] args) {
        int x = 10; // Stack에 저장되는 지역 변수
        int y = 20; // Stack에 저장되는 지역 변수
        int sum = add(x, y); // Stack에 메소드 호출 정보 저장
        System.out.println(sum);
    }

    public static int add(int a, int b) {
        int result = a + b; // Stack에 저장되는 지역 변수
        return result;
    }
}

 

 

-> main() 메소드가 실행될 때 x,y는 스택에 저장되었다가 메소드가 끝나면 사라짐

 

 


 

Heap 영역

 

  • new 키워드를 사용해 생성된 객체(instance)들이 저장됨
  • 힙 영역에 저장된 객체는 프로그램이 끝날 때 까지 또는 GC(Garbage Collector)에 의해 제거될 때 까지 살아있음
  • 힙에 저장된 객체는 전역적으로 접근 가능하고, 메소드가 끝나도 사라지지 않음

 

public class Example {
    public static void main(String[] args) {
        Person person = new Person(); // Heap에 저장되는 객체 : person
        person.setName("John"); // Heap에 있는 객체의 필드를 설정
    }
}

class Person {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

 

 

만약 다른 메소드에서 person 객체를 참조하고 있지 않다면, 가비지 컬렉터가 해당 객체를 삭제할 수 있음

 

 

 

 

 

JAVA 메모리 공간

Stack: 메소드 안에서 사용되는 지역 변수들이 저장되며, 메소드가 끝나면 사라지는 메모리 공간.
Heap: new 키워드로 생성된 객체들이 저장되고, 프로그램이 끝나거나 가비지 컬렉터가 실행되기 전까지 유지되는 메모리 공간.
Method 영역: 클래스, 메소드 정보, 상수, static 변수 등이 저장되어 프로그램 전체에서 공유되는 메모리 공간.
PC Register: 현재 실행 중인 명령어의 주소를 기억하는 메모리 공간.

 

 

 


 

[ 메모리 개념을 알아보게된 배경 ] 

 

나만 알아들을수도있지만......기록하고 보는..........

 

// 생략 .. 
List<ExampleVO> Elist = // ExampleVO 의 list. Elist 의 name 에 name1, name2, name3 이 있다고 가정 
List<ExampleVO> exampleVOList = ArrayList<>();

ExampleVO exampleVO = new ExampleVO(); // for문 밖에서 인스턴스 생성
for(ExampleVO example : Elist) {
	exampleVO.setName(example.getName());
    exampleVOList.add(exampleVO);
}

class ExampleVO {
	private String name;
    
    public void setName(String name){
    	this.name = name;
    }
    public void getName(){
    	return name;
    }
}

 

 

 

다음은 ExampleVO 를 받는 리스트인 exampleVOList를 생성해서 사용해야하는 경우의 일부 코드이다. 

 

내가 원하는 것은 새로 생성한 exampleVOList 에 'name1, name2, name3' 이 들어가는 것이다.

 

하지만 위 코드의 결과 for 문밖에서 exampleVOList 를 꺼내보면 'name3, name3, name3' 만 들어있다. 

 

이유는 for 문밖에서 인스턴스를 하나만 생성했기 때문에 리스트에 들어가는 exampleVO 객체의 값이 마지막에 할당된 name3의 값으로 계속 덮어씌워졌기 때문이다. 

 

 

내가원하는 결과를 얻기위해서는 다음과 같이 코드를 수정해야했다. 

 

 

for(ExampleVO example : Elist) {
    ExampleVO exampleVO = new ExampleVO(); // for문 안에서 인스턴스 생성
    exampleVO.setName(example.getName());
    exampleVOList.add(exampleVO);
}

 

 

이렇게 하면 for문을 돌면서 매번 새로운 객체가 Heap에 생성되어 각각의 객체가 독립적으로 관리될 수 있다. 

 

 

 

exampleVOList.add(exampleVO) 

코드상으로 보기에는 setName() 으로 설정해준 exmapleVO들이 하나씩 들어가는 것 같지만
실제로는 객체의 복사본이 들어가는 것이아니라, 객체의 참조(주소)가 저장되는 것이다. 

그래서 new로 객체를 하나만 만들었다면 주소가 하나만 생성되서 계속 같은 주소가 들어가기 때문에
각각의 주소를 매번 생성해서 참조할 수있게 해주어야하는 것이다. 

 

 

 

 

 

 

 

 

728x90
profile

울음참고 개발공부

@메각이

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!