Gentle Breeze

[JAVA] 반복문 내에서 List 객체에 add 할 때 메모리 참조 오류 본문

⑨ 직무역량강화/JAVA

[JAVA] 반복문 내에서 List 객체에 add 할 때 메모리 참조 오류

재령 2013. 8. 28. 12:59

사실 이 부분은 엄밀히 개발자의 무지(無知, Call by Value / Reference)에서 오는 오류로 JAVA 프로그램 내부의 문제라고 보기는 애매하다.


하지만 여러 프로젝트를 수행하며 지켜와 본 바에 따르면 생각보다 많은 개발자들이 이 현상에 대한 원인을 명확히 알지 못해 반복적으로 이 오류를 범하고 있기에 포스팅을 남겨본다.


- 잘못 된 코드 예시

import java.util.List;

public class test {
    public static void main(String[] args) {
        String[] strArray = {"aaa", "bbb", "ccc"};

        List<VO> list = new ArrayList<VO>();
        VO vo = new VO();

        for (int i=0; i<3; i++){
            vo.setValue(strArray[i]);
            list.add(vo);
        }
    }
}


일반적으로 개발자들은 위와같이 코드를 짜고 위 프로그램을 돌려보면 list 객체에는 "ccc" 라는 값의 value 변수를 가진 vo 객체가 3번 add 되어 있는 결과를 얻고는 그 원인을 찾지 못해 엉뚱한 사람을 탓하거나 스스로 멘붕에 빠지는 결과를 얻는 경우를 종종 보게 된다.


이 상황을 겪어본 경험이 있는 개발자라면 경험을 통해 빠르게 코드를 수정하지만 단순히 짐작에 의한 수정일 뿐 오류의 근본적 원인은 알지 못하는 경우도 있었다.


결론적으로는 아래와 같이 수정하면 원하는 결과를 얻을 수 있다.


- 수정한 코드 예시

import java.util.List;

public class test {
    public static void main(String[] args) {
        String[] strArray = {"aaa", "bbb", "ccc"};

        List<VO> list = new ArrayList<VO>();

        for (int i=0; i<3; i++){
          VO vo = new VO();
            vo.setValue(strArray[i]);
            list.add(vo);
        }
    }
}


이제 맨 처음 코드에서 문제가 발생한 원인을 알아보자.


이 경우 JAVA 소스 내에서 new VO(); 를 수행하는 순간 하나의 객체가 메모리 상에 생성된다. 이 vo 안의 value 변수(이름)에 데이터를 여러번 바꾼다 하여도 결국엔 같은 메모리 주소의 값만 변경되고 마지막에 적용된 데이터인 "ccc"가 최종 데이터 값(이름)이 된다.


좀 더 이해하기 쉽게 설명하자면 아이(vo)를 3명 낳아 각각의 아이들에게 "aaa", "bbb", "ccc" 라는 이름을 부여해야 하는데 1명의 아이(vo)만 낳아 3개의 이름을 한명의 아이에게 부여하다보니 가장 마지막에 지어준 "ccc" 라는 이름이 그 아이의 이름이 되어버린 것이다.


new 를 이용해 객체를 계속 재생성 하게 된다면 그만큼 많은 메모리 공간을 사용하게 되고 gc (garbage collection) overhead 가 증가해 성능상의 문제가 발생할 수 있으나 이 경우에는 어쩔수 없이 반복문 내에서 new 를 통해 객체를 매 번 재 생성 해 각각 다른 속성을 가진 객체로 만들어 각각 다른 메모리 주소를 참조하고 있는 이 객체들을 list 로 묶어 주어야만 한다.


상황에 따라 list 에 add 하는 부분을 void 를 반환하는 별도의 method 로 구현하여도 된다. 이 때에도 해당 method 안에 new 를 이용해 VO 객체를 재생성하는 코드가 삽입되어야 한다.


'⑨ 직무역량강화 > JAVA' 카테고리의 다른 글

[JAVA] Java Heap Space OOM  (0) 2012.07.04
[JAVA] LOG4J  (0) 2012.02.29
[JAVA] javac options  (0) 2012.02.15
Comments