Item 7. Obsolete Object

๋‹ค ์“ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๋ผ

Java๋Š” ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๋ฅผ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์—, C/C++๊ณผ ๊ฐ™์€ ์–ธ์–ด์ฒ˜๋Ÿผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋ ‡๋‹ค๊ณ  ์ „ํ˜€ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•„๋„ ๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์˜ˆ์‹œ

public class Stack {
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    private Object[] elements;
    private int size = 0;

    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        return elements[--size];
    }

    /**
     * ์›์†Œ๋ฅผ ์œ„ํ•œ ๊ณต๊ฐ„์„ ์ ์–ด๋„ ํ•˜๋‚˜ ์ด์ƒ ํ™•๋ณด
     * ๋ฐฐ์—ด ํฌ๊ธฐ๋ฅผ ๋Š˜๋ ค์•ผ ํ•  ๋•Œ๋งˆ๋‹ค ์•ฝ ๋‘ ๋ฐฐ์”ฉ ์ฆ๊ฐ€
     */
    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}

์œ„ ์ฝ”๋“œ์˜ pop() ๋ฉ”์„œ๋“œ์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. pop() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด elements ๋ฐฐ์—ด์—์„œ ์›์†Œ๋ฅผ ๊บผ๋‚ด ๋ฐ˜ํ™˜ํ•˜๊ณ , size๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๊ณ  ์žˆ์ง€๋งŒ, ๋ฐฐ์—ด์ด ์—ฌ์ „ํžˆ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ํšŒ์ˆ˜ํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” pop() ๋ฉ”์„œ๋“œ์—์„œ elements ๋ฐฐ์—ด์—์„œ ๊บผ๋‚ธ ์›์†Œ๋ฅผ null ์ฒ˜๋ฆฌํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

public class Stack {

    // ...

    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        Object result = elements[--size];
        elements[size] = null; // ๋‹ค ์“ด ์ฐธ์กฐ ํ•ด์ œ
        return result;
    }
    
    // ...
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด pop ์ฒ˜๋ฆฌํ•œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•ด๋„ NullPointerException์ด ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์˜๋„ํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ํšจ๊ณผ๋„ ์žˆ๋‹ค.

์Šค์ฝ”ํ”„์— ์˜ํ•œ ์ฐธ์กฐ ํ•ด์ œ

์‚ฌ์‹ค ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•  ๋•Œ ์œ„ ๊ฒฝ์šฐ์ฒ˜๋Ÿผ ์ผ์ผ์ด null ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค„ ํ•„์š”๋Š” ์—†๋‹ค.(์œ„ ์˜ˆ์‹œ๋Š” Stack ํด๋ž˜์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ ‡๋‹ค.) ๋‹ค ์“ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ํ•ด๋‹น ์ฐธ์กฐ๋ฅผ ๋‹ด์€ ๋ณ€์ˆ˜๋ฅผ ์œ ํšจ ๋ฒ”์œ„(scope) ๋ฐ–์œผ๋กœ ๋ฐ€์–ด๋‚ด๋Š” ๊ฒƒ์ด๋‹ค. ์ข‹์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์Šต๊ด€์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ๋ณ€์ˆ˜์˜ ์œ ํšจ ๋ฒ”์œ„๋ฅผ ์ตœ์†Œํ™”ํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋Š” ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ด๊ฒฐ๋œ๋‹ค.

์บ์‹œ

์บ์‹œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์ผ์œผํ‚ค๋Š” ์ฃผ๋ฒ” ์ค‘ ํ•˜๋‚˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•๋“ค ์ค‘ ํ•˜๋‚˜๋กœ, ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ WeakHashMap์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. (๋‹จ, ์ด ๋ฐฉ๋ฒ•์€ ์บ์‹œ ์™ธ๋ถ€์—์„œ ํ‚ค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋™์•ˆ๋งŒ ๊ฐ’์ด ์‚ด์•„์žˆ๋Š” ์บ์‹œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.)

class Test {
    public static void main(String[] args) {
        /*
         WeakHashMap์˜ ์ฃผ์š” ํŠน์ง•์€ ํ‚ค์— ๋Œ€ํ•ด ์•ฝํ•œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์œผ๋กœ,
         ์•ฝํ•œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ•๋ ฅํ•œ ์ฐธ์กฐ๊ฐ€ ์—†์„ ๋•Œ ๊ฐ์ฒด๊ฐ€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์˜ ๋Œ€์ƒ์ด ๋œ๋‹ค. 
         */
        WeakHashMap<Integer, Integer> weakHashMap = new WeakHashMap<>();
        Integer key1 = 59;
        Integer key2 = 95;
        weakHashMap.put(key1, 1);
        weakHashMap.put(key2, 2);

        System.out.println("before call gc() : " + weakHashMap.size()); // 2

        key1 = null; // ํ‚ค๋ฅผ null๋กœ ๋งŒ๋“ค์–ด์„œ GC ๋Œ€์ƒ์ด ๋˜๋„๋ก ํ•œ๋‹ค.
        System.gc(); // ์œ„ ์ฝ”๋“œ์—์„œ testWeakKey1์€ null์ด ๋˜์—ˆ์œผ๋ฏ€๋กœ GC ๋Œ€์ƒ์ด ๋œ๋‹ค.(๋ณด์žฅ๋˜์ง„ ์•Š์Œ)

        System.out.println("after call gc() : " + weakHashMap.size()); // GC๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด 2, ๋™์ž‘ํ–ˆ๋‹ค๋ฉด 1
    }
}

Last updated