> > Yes, if runtime stripes that instance before it is exposed anywhere > (e.g. scalarizes the weakref)
If you look at escape analysis code ( http://hg.openjdk.java.net/jdk9/hs-comp/hotspot/file/a60bd3d34158/src/share/vm/opto/escape.cpp#l803), Reference and subclasses get special treatment and marked as GlobalEscape. On Wed, Oct 21, 2015 at 1:08 PM, Aleksey Shipilev < [email protected]> wrote: > On 10/21/2015 06:53 PM, Andrew Haley wrote: > > On 10/21/2015 04:44 PM, Aleksey Shipilev wrote: > >> Of course, this does not tell another (scary) part of the story, what if > >> the Reference itself is not discovered as strong ref by GC, e.g. when it > >> isn't published on heap, or scalarized by compiler, etc. > >> reachabilityFence, as currently implemented, extends the "liveness" > >> scope of the local variable, but does not convey anything special to the > >> GC/runtime otherwise. > > > > If the Reference itself is not reachable from a strong root then the > > Reference is dead so we don't care what happens to it. But if the > > Reference is put on a reachable ReferenceQueue, then it's fine. > > Yes, if runtime stripes that instance before it is exposed anywhere > (e.g. scalarizes the weakref), or those references are dead (e.g. the > weakref is buried somewhere deep in garbage subgraph, and purged on > sweep), then everything goes awry. > > But the thing is, a WeakReference is put on ReferenceQueue by the GC > itself. In the object graph, ReferenceQueue does not normally reference > weakrefs back. Before enqueueing the reference GC has to first discover > that WeakReference -- but from where? In other words, "registering" on a > reachable RefQueue does not make weakref to be reachable. > > Case in point: > > public class WhereIsWaldo { > > public static void main(String... args) throws Exception { > for (int c = 0; true; c++) { > new WhereIsWaldo().work(c); > } > } > > final ReferenceQueue<Object> rq = new ReferenceQueue<>(); > > void work(int id) throws Exception { > hideWaldo(id); > findWaldo(id); > } > > WeakReference<Object> gwr; > > void hideWaldo(int id) { > // Does not work, d'uh > new WeakReference<>(new Object(), rq); > > // Does not work either :( > WeakReference<Object> wr = > new WeakReference<>(new Object(), rq); > > // This also does not help... once you leave the method, > // the weakref is gone. > Reference.reachabilityFence(wr); > > // This one helps, makes Waldo reachable > // gwr = wr; > } > > void findWaldo(int id) throws Exception { > while (Thread.currentThread().isAlive()) { > System.gc(); > Reference ref = rq.remove(1000); > if (ref != null) { > return; > } else { > System.out.println("Where's Waldo #" + id + "?"); > } > } > } > } > > > Thanks, > -Aleksey > >
