æè¿å ãã£ãããã«è¦ãã¦å®ã¯ãããæããåå¨ãã¦ãã java.lang.ref.Reference ã¨ãã®å®è£ ã¯ã©ã¹ã§ãã PhantomReference, SoftReference, WeakReference ã® 3 ã¤ãä»æ¥ã¯ããã¤ãã®åä½ã«ã¤ãã¦è»½ãè¦ã¦ããã
ãã ãã®åã«ãjava6 ã®å¹¾ã¤ãããã¯ã·ã©ã³ãã© jvisualvm ãªã jvm ã®æåã GUI ã§è¦ãããã¼ã«ãæä¾ããã¦ããã
ã¨ãããããä¸è¨ã®ä½ã®æå³ãç¡ãã³ã¼ããèµ°ãããã¨ãã® jvisualvm ã®æåã¯ãããªæãã
long c = 0; List<BigDecimal> list = new ArrayList<BigDecimal>(); while (true) { Random r = new Random(); long l = r.nextLong(); list.add(new BigDecimal(l)); c++; }
å½ç¶ã®ãã¨ããã¼ããé£ãã¤ã¶ããã¦ããã®ã¨ããããã㨠CPU ã®ç¨¼åã GC ã®æ´»åã¨ã¤ã³ã¼ã«ã«ãªã£ã¦ããã®ãè¦ã¦åãã¾ããã¾ãå½ç¶ã£ããªã
空æ°ãèªãã§é©å½ã«å¼±åç §ãªãã¸ã§ã¯ããã¯ãªã¢ãã SoftReference
Java ã®ãå¼·å°éå¯è½ãªããã½ããå°éå¯è½ãªããå¼±å°éå¯è½ãªãããã¡ã³ãã å°éå¯è½ãªãã®ã¡ããã¨ããå®ç¾©ã¯ Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle ãªã©ãèªãã§ãããã¨ãã¦ããã ãããããããã®ããã¥ã¡ã³ãã¯ãã¸ã§ã¼ã«ãããã«ãããã¨ããã®ãããã½ããå°éå¯è½ãªããªãã¸ã§ã¯ãã¨ã¯ãå¼·å°éå¯è½ã§ã¯ãªãããã½ããåç §ããã©ãã¼ã¹ãããã¨ã§å°éã§ãããªãã¸ã§ã¯ããã¨ãæ¸ãã¦ãã£ãããã¦ãå®ç¾©ã®èª¬æã«å®ç¾©ã®èª¬æãå«ã¾ããã¨ããæ§é ã«ãªã£ã¦ããããã§ããããã ã¾ããç´æè¡çã«å³å¯ãªå®ç¾©ããããã¨ããã¨ãããªãã®ã¯ããæ®éã®ãã¨ãjavadoc ãç¹å¥ãããããªè¨è¿°ã¨ããããã§ã¯ãªãã
ã¨ããããã§ãã³ã³ã®ã¨ã³ããªã¼ã§ã¯èªåã®è¨èã§ã³ã¤ãããï¼èªåã«ã¨ã£ã¦ï¼ãããããã説æããªããã¦ã¾ããã¤ã¾ããæ£ç¢ºãªè¡¨ç¾ã§ã¯ãªãå¯è½æ§ãããã®ã§ããããããã£ã¦ã³ãã§ãã
ã¡ãã£ã¨æ¨ªéã«ããã¾ããããã¾ãã¯ä¸çªãããããã SoftReference ãããjavadoc ãè¦ãã¨ããããªãã¸ã§ã¯ããã½ããå°éå¯è½ã«ãªã£ãã GC 対象ã«ãªããã¨ããããªãã¼ãªãã¨ãæ¸ãã¦ãããã½ããå°éå¯è½ã£ã¦ãªãããã£ã¦è©±ã§ãããããããå¼±åç §ã¨èãã¦ãããã§ãå¼±åç §ã®ãã¡ GC ããããã¤æ¶ãã¦ããã ããã£ã¦å¤å®ããããããã¤ãã½ããå°éå¯è½ãã¨ãããã¨ã®ããã ã
ã¨ãããããã§ãä¸ã®ãããªã³ã¼ããå®è¡ããjvisualvm ã§æ§åãè¦ã¦ã¿ãã
import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; public class SoftReferenceTest { public static void main(String[] args) throws InterruptedException { new SoftReferenceTest().doMain(); } private void doMain() throws InterruptedException { while (true) { m(); } } private List<Reference<Byte[]>> list = new ArrayList<Reference<Byte[]>>(); private void m() { for (int i=0; i<10; i++) { Byte[] t = new Byte[10000]; list.add(new SoftReference<Byte[]>(t)); } } }
list ã«ç¡éã«ãããã¼ãªãµã¤ãºã®ãªãã¸ã§ã¯ããã¬ã³ã¬ã³çªã£è¾¼ãã§ããã ãã®ã³ã¼ãã§ããããã¼ã«èããã¨å³ OutOfMemoryError ã«ãªããããªããã§ãããããã¯ãªãããã¼ãã¯ãã³ãã³ã«ãªã£ã¦ãã空ãã¦ããç¹°ãè¿ãåä½ã«ãªãã¾ããlist ã«çªã£è¾¼ã¾ãããªãã¸ã§ã¯ãã¯ãm ã¡ã½ããã®ã«ã¼ãã®éã ãã¯å¼·åç §ã§ããããããæãã㨠list ãªãã¸ã§ã¯ãããã®ã¿ããåç §ãç¡ããªããã¨ãããã¨ã¯ã¤ã¾ãã誰ã使ããªãããï¼ããã¤æ¶ãã¦ããã ããã¨å¤å®ãããããã§ããã§ãå®éããããã¼ãªã¿ã¤ãã³ã°ã§ Reference ãæãã¦ã Byte[] ã®ãªãã¸ã§ã¯ãã¯æ¶ããã¦ããã®ã jvisualvm ã§è¦ã¦åãã¾ãã
å®ã¯ãã®ããã°ã©ã ãé·æéæ¾ç½®ãã㨠OutOfMemoryError åºããã§ããâ¦â¦ããã¯ã¾ãå¾ã§è§¦ããäºå®ã
ããã¼ã®å¼±åç § WeakReference
ããã¯ã³ã¼ã㨠jvisualvm ã®åãè¦ãæ¹ãéãã®ã§ã
import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; public class WeakReferenceTest { public static void main(String[] args) throws InterruptedException { new WeakReferenceTest().doMain(); } private void doMain() throws InterruptedException { while (true) { m(); } } private List<Reference<Byte[]>> list = new ArrayList<Reference<Byte[]>>(); private void m() { for (int i=0; i<10; i++) { Byte[] t = new Byte[10000]; list.add(new WeakReference<Byte[]>(t)); } } }
SoftReference ã WeakReference ã«ãªã£ãã ããªãã§ãããã©ãåä½ã¯ããªãå¤ãã£ã¦ãã¾ãã
SoftReference ã¨éã£ã¦ãGC ããããã¼ãªã¿ã¤ãã³ã°ã§ãªãã¸ã§ã¯ããæ¶ãã¦ã¾ããããã§ã¯ãªãã®ã大ããªéããã¡ããã¨ããå®ç¾©ã¯è¦ javadoc åç §ã§ãããå¼±åç §ãæ¶ãã®ã« GC ã®ç¬èªå¤æãä»å¨ããã®ãã©ããã SoftReference 㨠WeakReference ã®ä¸çªã®éãã§ãããã
ã§ãã³ã¬ã ãè¦ã㨠WeakReference ã®ä½¿ãã©ãããããããªããã§ãã
ã¾ããSoftReference 㯠GC ã®è³¢ãã«ä¾åããã®ã§ãããããã¯ã«ãªãå ´åã«ã¯ä½¿ããªããã¾ãâ¦â¦ä¸¦ã®æ¥åã¢ããªã§ã¯å¤§ãã¦åé¡ã«ãªããªãã¨æããã§ãããã¦ãã®ã±ã¼ã¹ã¯ SoftReference 使ã£ã¨ãã°ãï½ã ã¨ã¯æããã§ããã
ã¾ããReference ãªãã¸ã§ã¯ããã®ãã®ã¯ååãããªããã¨ã«ã注æãããããã㯠WeakReference ã SoftReference ãåãã ãã©ãã
private ConcurrentHashMap<K, SoftReference<V>> map = new ConcurrentHashMap<K, SoftReference<V>>();
å®ç´ã«èãããªãâã¿ããã«ããã°ãã£ãã·ã¥ãå®ç¾ã§ããããã§ã¾ããå®éãã¨ãããããã¯ä¸æãããããããã㯠OutOfMemoryError ã®å±éºæ§ãåãã§ãããã¨ããã®ãå ã«è¿°ã¹ãããã« Reference ãªãã¸ã§ã¯ããæãã¦ãããªãã¸ã§ã¯ã㯠null ã«ãªããã®ã®ãReference ãªãã¸ã§ã¯ããã®ãã®ã¯ map ã«æºã¾ãç¶ããããã§ãããã¨ã¯ãããç¸å½éã® Reference ãªãã¸ã§ã¯ããæºãè¾¼ã¾ãªãéã OutOfMemoryError ã«ã¯ãªããã®ã§ãåé¡ã表é¢åãããã¨ã¯ãªãããã§ã¯ããããã©ã
ã¨ãªãã¨ããã¼ãå¼±åç §ã«ãªã£ããå¤ã GC ããã Map ãããã°ããã®ã«â¦â¦ã¨ã¯ãã¿ããªãæãã¨ãããªããã§ããã¨ãããã㧠Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle ãç¨æããã¦ããã
ã¨ããããã§ã使ã£ã¦ã¿ãã
import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.TimeUnit; public class WeakHashMapTest { public static void main(String[] args) throws InterruptedException { new WeakHashMapTest().doMain(); } private void doMain() throws InterruptedException { while (true) { m(); System.out.println(map.size()); } } private Map<String, Byte[]> map = new WeakHashMap<String, Byte[]>(); private void m() throws InterruptedException { for (int i=0; i<10; i++) { Byte[] v = new Byte[10000]; TimeUnit.MILLISECONDS.sleep(30); String k = String.valueOf(System.currentTimeMillis()); map.put(k, v); } } }
ç°å¢ã«ãä¾ããã§ãããããmap ã®ãµã¤ãºã¯ 0 ã 100 ã®éããããè¡ã£ããæ¥ããããã
ãã¼ãã®åããããªãã»ã©ã¨ãã£ãæãã
ãã¼ã SoftReference ãªã®ã¯ç¡ãã®ããªï¼ãã¨ä¸ç¬æã£ããã©ãGC ã®ãããµãå¤æã§å¤ãæ¶ãããæ¶ããªãã£ããã«ãªã Map ã¯ãããã«ç¡ããã ããªã¼ã¨æããªãããã
ã¤ããã©ããã®ããããªã PhantomReference
ã¶ã£ã¡ããç¨éä¸æãªã®ã PhantomReference ã§ãããjavadoc ã«ããã¨ããã¡ã³ãã åç §ã¨ã¯ãããã¡ã³ãã å°éå¯è½ãªããªãã¸ã§ã¯ãã¨ã¯ãå¼·å°éå¯è½ã§ããã½ããå°éå¯è½ã§ããå¼±å°éå¯è½ã§ããªãããã¡ã¤ãã©ã¤ãºããã¦ããããã¡ã³ãã åç §ããããæãã¦ãããªãã¸ã§ã¯ããã¨ãããã¨ãæ¸ãã¦ããã
è¦ã¯ããªãã¸ã§ã¯ãã® finalize ã¨å®éã® GC ã§ãã¼ããã¯ãªã¢ãããå¦çã¨ã®éã§ãªããå¦çãã«ããããå ´åã«ä½¿ããã®ãã¨ãããã¨ã®ããã ãããã¼ã®æ¥åã¢ããªã§ããã¾ã§ãã¼ãé åãæèããä½ããã¿ãããã±ã¼ã¹ã£ã¦ã®ãæ³å®ã§ããªããã§ãããâ¦â¦ã²ã¼ã ã¨ãã ã¨å¿ è¦ã«ãªããã§ããããï¼
PhantomReference ã«ã¤ãã¦ã¯ Java Programming Tips:java.lang.ref パッケージの利用方法(SoftReference/WeakReference/PhantomReference) ãããªãããã¾ã¨ã¾ã£ã¦ãã¾ããPhantomReference ã ããããªã㦠SoftReference, WeakReference ã«ã¤ãã¦ãããããªãã解説ãè¼ã£ã¦ã¾ãã