Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There are a lot of things which might be going on, but with respect to your test program using soft values: you can get OutOfMemoryError even if you have SoftReferences which have not yet been garbage collected. That bears repeating: you can get an OutOfMemoryError even if you have SoftReferences which have not yet be cleared.</p> <p>SoftReferences are a little weird, see <a href="http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html" rel="nofollow noreferrer">http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html</a> for a description of current mechanics. Likely in your test case, the GC just didn't have time to do two full GCs.</p> <p>When you were using weakKeys, the CG cleared them right away, and didn't have to wait for a full GC pause. (b/c WeakReferences are collected aggressively.)</p> <p>In my opinion, if you want a memory-sensitive cache with Integer keys, I'd think the following is appropriate:</p> <pre><code>data = new MapMaker().softValues().makeMap(); </code></pre> <p>You can easily make a test program which throws OutOfMemoryError, but if your real application is somewhat well behaved, and doesn't get under too much pressure, you might be OK. SoftReferences are pretty hard to get right.</p> <p>If you need to use System.gc() avoid out-of-memory, I would instead recommend you switch to an LRU map with a fixed max size (See the javadoc of java.util.LinkedHashMap for an example.) It's not concurrent, but I expect it's going to give you better throughput in the end than asking the system to do a full-pause garbage collection a bunch of extra times.</p> <p>Oh, and a final note about integer keys and weakKeys(): MapMaker uses identity comparison for keys when using weak or soft keys, and that's pretty hard to do correctly. Witness the following:</p> <pre><code>Map&lt;Integer,String&gt; map = new MapMaker().weakKeys().makeMap(); Integer a = new Integer(1); Integer b = new Integer(1); Integer c = 1; //auto box Integer d = 1; //auto box map.put(a, "A"); map.put(b, "B"); map.put(c,"C"); map.put(d,"D"); map.size() // size is 3; </code></pre> <p>Good luck.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload