가비지 컬렉터 : 메모리 관리를 자동으로 해줌
메모리의 스택, 힙 영역에서 객체들이 존재하는 힙영역에서 행해진다. ==> 가능한 많은 여유 메모리를 갖도록 관리함
가비지 컬렉터는 언제 실행될까?
JVM 제어 하에 있으며, 실행 시기도 JVM이 결정한다.
사용 가능한 메모리가 적다고 감지될 때, JVM이 가비지 컬렉터를 실행시킨다.
객체가 가비지 컬렉션 대상이 되도록 만드는 코드
1. 참조를 null로 만들기
| public class Garbage{ public static void main(String[] args){ StringBuffer sb = new StringBuffer("hello"); System.out.println(sb); sb = null; // 이제 가비지 컬렉터의 대상이된다. } } | cs |
sb는 StringBuffer 객체의 유일한 참조이므로 sb가 null이 되면 StringBuffer 객체는 가비지 컬렉션의 대상이 된다.
2. 참조 변수를 다시 지정하기
| public class Garbage{ public static void main(String[] args){ StringBuffer s1 = new StringBuffer("hello"); StringBuffer s2 = new StringBuffer("goodbye"); System.out.println(s1); s1 = s2; // s1의 참조 값을 변경한다. // "hello" StringBuffer 객체는 이제 가비지 컬렉터의 대상이된다. } } | cs
|
** 메서드가 호출되면, 메서드가 실행되는 동안만 존재하는 지역 변수가 생긴다.
메서드 실행이 끝나고 복귀되면, 그 메서드 내에서 생성된 객체는 가비지 컬렉션의 대상이 된다.
예외! 만일 메서드가 객체를 반환한다면, 그 객체의 참조를 갖는 참조 변수가 호출된 메서드에 존재할 것이므로, 가비지 컬렉션의 대상이 되지 않는다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import java.util.Date; public class GarbageFactory { public static void main(String[] args) { Date d = getDate(); // Date 객체를 반환하는 메서드 System.out.println("d =" + d); } /* * 이 메서드는 Date, StringBuffer 두가지 객체를 생성 * Date 객체를 반환하므로, 메서드의 실행이 끝나고 복귀하더라도 메서드에서 생성한 Date 객체는 가비지 컬렉션의 대상이 아님. * 반면, StringBuffer 객체는 now 참조 변수에 null을 넣지 않더라도 가비지 컬렉션의 대상이 된다. * */ public static Date getDate(){ Date d2 = new Date(); StringBuffer now = new StringBuffer(d2.toString()); System.out.println(now); return d2; } } | cs |
3. 참조를 고립시키기
적법한 참조를 갖고 있는 객체조차도 가비지 컬렉션의 대상이 될 수 있는 방법이 있다.
클래스의 인스턴스 변수는 같은 클래스의 다른 인스턴스를 참조하는 참조 변수이다.
이 클래스 인스턴스는 두 개 있고, 상호 간에 참조를 한다고 해보자.
만일 이 두개의 인스턴스를 참조하는 모든 다른 참조가 제거된다면, 두 인스턴스가 상호 참조를 갖고 있더라고 살아있는 스레드에서 두 인스턴스에 접근할 방법이 없으므로
가비지 컬렉터의 제거 대상이 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class Island{ Island i; public static void main(String[] args){ Island i2 = new Island(); Island i3 = new Island(); Island i4 = new Island(); i2.i = i3; // i2는 i3를 참조 i3.i = i4; // i3는 i4를 참조 i4.i = i2; // i4는 i2를 참조 i2 = null; i3 = null; i4 = null; // i2, i3, i4는 가비지 컬렉션의 대상이 된다. } } | cs
|

** 문제
1. 다음 코드에서 가비지 컬렉션의 대상이 되는 객체는 몇개인가?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class CardBoard { Short story = 200; private CardBoard go(CardBoard cb) { cb = null; return cb; } public static void main(String[] args) { CardBoard c1 = new CardBoard(); CardBoard c2 = new CardBoard(); CardBoard c3 = c1.go(c2); c1 = null; } } | cs |
답: 2개 . c1이 가비지 컬렉션 대상이 되고, 그 객체는 Short 래퍼 객체를 갖고 있으므로, 이 객체도 가비지 컬렉션의 대상이 된다.
2. main() 메서드에서 생성된 객체 수와 가비지 컬렉션의 대상이 되는 객체 수는?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Dozens { int[] dz = {1,2,3,4,5,6,7,8,9,0}; } public class Eggs { public static void main(String[] args) { Dozens[] da = new Dozens [3]; da[0] = new Dozens(); Dozens d = new Dozens(); da[1] = d; d = null; da[1] = null; } } | cs |
답:
5 객체 / 2개의 객체가 GC의 대상이된다.
da는 Dozens 객체를 저장하는 배열 참조이다. 각각의 Dozens객체는 int 값을 저장하는 배열을 갖고 있다.
따라서, 생성된 객체 수는 5개 ( da 배열 객체 1개, Dozens 객체 2개, 각 Dozens 객체들이 가지는 int배열 객체 두개)
가비지 컬렉션 대상이 되는 객체는 2개 ( d가 참조했던 Dozens객체 한개, 그 객체가 갖는 int 배열 객체 한개)
3. 가비지 컬렉션의 대상이 되는 객체는 몇개?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Beta {} class Alpha { static Beta b1; Beta b2; } public class Tester { public static void main(String[] args) { Beta b1 = new Beta(); Beta b2 = new Beta(); Alpha a1 = new Alpha(); Alpha a2 = new Alpha(); a1.b1 = b1; a1.b2 = b1; a2.b2 = b2; a1 = null; b1 = null; b2 = null; } } | cs |
답 : 1개.
a2가 참조하는 Alpha 객체 참조는 아직 살아 있고, a1만 null값이므로, a1이 참조하는 Alpha 객체만 가비지 컬렉션의 대상이 된다.