001 package com.croftsoft.core.util; 002 003 import java.lang.ref.*; 004 import java.util.*; 005 006 /********************************************************************* 007 * A Map implementation that dumps its content when memory runs low. 008 * 009 * <P> 010 * 011 * Backed by a WeakHashMap. Note that an entry will not be garbage 012 * collected if its key remains strongly reachable. 013 * 014 * <P> 015 * 016 * @see 017 * java.util.WeakHashMap 018 * @see 019 * java.lang.ref.SoftReference 020 * 021 * @version 022 * 1999-04-20 023 * @author 024 * <a href="https://www.croftsoft.com/">David Wallace Croft</a> 025 *********************************************************************/ 026 027 public class SoftHashMap extends AbstractMap 028 ////////////////////////////////////////////////////////////////////// 029 ////////////////////////////////////////////////////////////////////// 030 { 031 032 private WeakHashMap weakHashMap = new WeakHashMap ( ); 033 private ReferenceQueue referenceQueue = new ReferenceQueue ( ); 034 private Set softSet = new HashSet ( ); 035 036 ////////////////////////////////////////////////////////////////////// 037 ////////////////////////////////////////////////////////////////////// 038 039 public static void main ( String [ ] args ) 040 ////////////////////////////////////////////////////////////////////// 041 { 042 System.out.println ( test ( ) ); 043 } 044 045 public static boolean test ( ) 046 ////////////////////////////////////////////////////////////////////// 047 { 048 try 049 { 050 SoftHashMap softHashMap = new SoftHashMap ( ); 051 052 softHashMap.put ( "key", "value" ); 053 054 if ( !softHashMap.remove ( "key" ).equals ( "value" ) 055 || ( softHashMap.size ( ) > 0 ) ) 056 { 057 return false; 058 } 059 060 Runtime runtime = Runtime.getRuntime ( ); 061 062 for ( int i = 0; i < 1000000; i++ ) 063 { 064 if ( i % 10000 == 0 ) 065 { 066 System.out.println ( 067 i + ": " 068 + softHashMap.size ( ) 069 + " entries, " 070 + runtime.freeMemory ( ) 071 + " / " 072 + runtime.totalMemory ( ) 073 + " memory usage" ); 074 } 075 076 Integer value = new Integer ( i ); 077 softHashMap.put ( value.toString ( ), value ); 078 } 079 } 080 catch ( Throwable t ) 081 { 082 t.printStackTrace ( ); 083 084 return false; 085 } 086 087 return true; 088 } 089 090 ////////////////////////////////////////////////////////////////////// 091 ////////////////////////////////////////////////////////////////////// 092 093 public Set entrySet ( ) 094 ////////////////////////////////////////////////////////////////////// 095 { 096 clearQueue ( ); 097 098 return weakHashMap.entrySet ( ); 099 } 100 101 public Object put ( Object key, Object value ) 102 ////////////////////////////////////////////////////////////////////// 103 { 104 clearQueue ( ); 105 106 softSet.add ( new SoftReference ( key, referenceQueue ) ); 107 108 return weakHashMap.put ( key, value ); 109 } 110 111 ////////////////////////////////////////////////////////////////////// 112 ////////////////////////////////////////////////////////////////////// 113 114 public void clearQueue ( ) 115 ////////////////////////////////////////////////////////////////////// 116 { 117 Reference reference = null; 118 while ( ( reference = referenceQueue.poll ( ) ) != null ) 119 { 120 softSet.remove ( reference ); 121 } 122 } 123 124 ////////////////////////////////////////////////////////////////////// 125 ////////////////////////////////////////////////////////////////////// 126 }