자바 서버개발자보다는 자바 임베디드 개발자 내부 캐쉬 용도 용도로 쓰기 위해서 java.lang.ref.Reference클래스를 사용하기도 한다. 잘만 쓰면 메모릭 릭을 잘 방지하면서 사용할 수 있다.
* SoftReference(SR)
풍부하게 메모리를 넉넉히 쓰지만, 최초의 GC가 돌아간 후, JVM은 메모리 공간이 없으면 SoftRefernece 인스턴스를 gc 대상으로 잡는다. OOME 가 발생할 수 있는 상황에서 softly-reachable objects가 있다면, 이 objects를 모두 메모리에서 정리한다. 언제 gc될지는 모른다.
안드로이드 API(http://developer.android.com)에 따르면, as late as possible이다.
실제 구현 예) Tomcat의 jdbc 쪽 SoftReferenceObjectPool.java을 참조하면 좋음
간단하게 new SoftReference(객체인스턴스)로 해서 만든다.
http://www.docjar.com/html/api/org/apache/commons/pool/impl/SoftReferenceObjectPool.java.html
| package org.apache.commons.pool.impl; import java.lang.ref.SoftReference; import org.apache.commons.pool.BaseObjectPool; public synchronized void addObject() throws Exception { boolean success = true; boolean shouldDestroy = !success; if(shouldDestroy) { |
* WeakReference(WR) , WeakHashMap
객체가 사용 중이기는 하지만, 더 이상 사용하지 않을 것 같으면 컨테이너에서 삭제한다.
쉽게 말해서 일종의 잠깐 동안의 캐쉬로서 gc가 실행되면 메모리에서 정리한다.
아래 코드를 실행하면, 설명은 그다지 필요하지 않다.
| public class ReferenceTest { class Student { |
결과는 다음과 같다. gc이후에 WeakReference 객체는 모두 메모리에서 정리된다.
| 1: [id=1] |
톰캣 컨테이너에서 사용하고 있는 ConcurrentCache.java를 예로 든다.
package org.apache.el.util;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
public final class ConcurrentCache<K,V> {
private final int size;
private final Map<K,V> eden;
private final Map<K,V> longterm;
public ConcurrentCache(int size) {
this.size = size;
this.eden = new ConcurrentHashMap<K,V>(size);
this.longterm = new WeakHashMap<K,V>(size);
}
public V get(K k) {
V v = this.eden.get(k);
if (v == null) {
synchronized (longterm) {
v = this.longterm.get(k);
}
if (v != null) {
this.eden.put(k, v);
}
}
return v;
}
public void put(K k, V v) {
if (this.eden.size() >= size) {
synchronized (longterm) {
this.longterm.putAll(this.eden);
}
this.eden.clear();
}
this.eden.put(k, v);
}
}
|
java의 ThreadLocal.ThreadLocalMap에서도 WeakReference를 사용하고 있다.
|
static class ThreadLocalMap { Entry(ThreadLocal k, Object v) {
private static final int INITIAL_CAPACITY = 16;
for (int j = 0; j < len; j++) {
…..
|
안드로이드 API(http://developer.android.com)에서는 구현체에 대해서 더욱 세밀하게 설명이 들어가 있다.
|
Implements a weak reference, which is the middle of the three types of references. Once the garbage collector decides that an object
|
* PhantomReference(PR)
soft, weak보다 엄청 약하다. gc가 돌기 전(즉, 이것은 gc 대상이야 라고 결정할 때, finalize() 호출 후 ) 메모리에서 정리된다. 아무래도 gc 되기 전에 cleanup 해야 할 때 사용한다. 내부적으로는 유지하고 있지만, 객체를 다시 꺼내오면 null이 된다.
아주 특수한 경우에 쓰인다. sun.misc.Cleaner 클래스가 PhantomReference를 사용하고 있다.
http://knight76.tistory.com/1548
재미있는 블로그(http://weblogs.java.net/blog/kcpeppe/archive/2011/09/29/mysterious-phantom-reference)가 있는데, PhantomReference 썼다가 이상하게 (미스테리하게) 나와서, 조금 수정해서 해결했다는 내용이다.
|
package snippet; import java.lang.ref.PhantomReference;
public class ReferenceTest {
for (int i = 0; i < 10; i++) {
// make sure the garbage collector does it’s magic
// lets see what we’ve got
for (PhantomReference<Foo> reference : list) {
public static void test2() {
public Foo(String bar) {
public String get() {
|
테스트 결과는 다음과 같다.
|
x: true
|
'java core' 카테고리의 다른 글
| java default max heap size 파악 및 오픈 소스에서의 heap memory 설정 (0) | 2013.04.22 |
|---|---|
| Google Collection Package & Google Guava (0) | 2013.03.14 |
| String의 codePointCount 메서드 (0) | 2012.03.13 |
| 자바의 FileDescriptor 클래스의 native 메소드 내부 찾아보기 (0) | 2012.03.05 |
| java 7 은 glic 2.4 이상의 linux에서 동작 (0) | 2012.02.16 |


