I like this suggestion. David's most recent webrev with while(true) loop could easily be extended to create linked list of reference arrays in each loop. ie.
Object[] chain = null; while (wr.get() != null) { try { Object[] allocate = new Object[1000000]; allocate[0] = chain; chain = allocate; } catch( OutOfMemoryError ) { chain = null; } System.gc(); Thread.sleep(100); } Mike On Jan 31 2013, at 05:47 , Peter Levart wrote: > Hi David, > > You could combine the B and C in the following pattern: > > - Create a WeakReference to the observed object; > - Execute the potentially "leaky" operation; > - Trigger gc with after check of WeakReference. Maybe a couple of times. > - If that does not clear the reference, fill-in heap until OOME is thrown and > after that check the reference. > > Regards, Peter > > On 01/31/2013 10:40 AM, David Buck wrote: >> Hi! >> >> I was curious to see what others have done in the past and took a look at >> about 15 different testcases for memory leaks in the jdk tree and basically >> found 3 patterns: >> >> Pattern A: Use a loop that would exercise the relevant code for a finite >> number of runs. If an OOME is not thrown, the test passes. In order for the >> test to finish quickly, most people seem to specify a very small Xmx to >> limit the number of iterations needed. (example: >> java/util/concurrent/BlockingQueue/PollMemoryLeak.java) >> >> Pattern B: Code similar to what I have submitted for this review that tries >> to leak one object, explicitly triggers a GC event, and then confirms that >> the WeakReference was nulled out. One thing to note is that in every case I >> found of this the author chose to run multiple GC events, usually somewhere >> between 5 to 10000 iterations. (example: >> javax/management/Introspector/ClassLeakTest.java) >> >> Pattern C: These cases used a WeakReference like Pattern B above, but >> instead of depending on an explicit call to System.gc(), would intentionally >> fill the heap until an OOME is thrown to trigger at least 1 "full" gc event. >> (example: >> java/rmi/server/UnicastRemoteObject/unexportObject/UnexportLeak.java) >> >> Patterns A and B were most common (with pattern B being slightly more >> common), and I only found Pattern C 2 times >> >> Strictly speaking, all 3 patters are problematic as they each depend on >> undefined behavior in some way or another. Patterns A and C require the JVM >> to handle OOMEs somewhat gracefully (Pattern A when we fail, Pattern C when >> we pass), and pattern B requires an explicit call to System.gc to collect an >> arbitrary object. >> >> The fact that we do not routinely see false positives from these cases >> indicates that in practice, they all seem to work OK for the time being. >> >> After thinking about this for a bit, I actually really like pattern C. Even >> though the JVM is not technically guaranteed to gracefully handle all OOME >> conditions, we try very hard to be as robust as possible in the face of >> Java-heap OOME. Again, the fact that we do not routinely see false positives >> from these tests proves that in practice, this works very well. Even if an >> otherwise "correct" change (say in the JVM) resulted in Pattern C suddenly >> failing, it is something we would almost certainly want to investigate as it >> would indicate that the robustness of the JVM has somehow regressed. >> >> I plan to modify my testcase to follow pattern C and resubmit for review. If >> anyone has any other ideas or comments, I would be grateful for your input. >> >> Cheers, >> -Buck >> >> On 2013/01/30 22:32, David Buck wrote: >>> Hi Alan! >>> >>> Thank you for your help. >>> >>> TL;DR version: >>> >>> Strictly speaking (going only by the specifications), this could give us >>> false positives, but I believe this is VERY unlikely to actually happen >>> in real life. >>> >>> Long version: >>> >>> Yes, I gave this some thought myself. For example, on JRockit, if the >>> object were in old space and System.gc() only did a young collection >>> (the default behavior for JRockit), this test would result in a false >>> positive. In fact, as the JVM is allowed by the specification to >>> completely ignore explicit GC calls, we could never guarantee that we >>> would the WeakReference would always get nulled out. >>> >>> That said, in pactice this works very well for both HotSpot and JRockit. >>> Every scenario I have tried it out on (with both JVMs) has provided the >>> expected result every single time (i.e. failing when expected; never >>> resulting in false positive otherwise). It seems that both of Oracle's >>> JVMs as currently implemented are very unlikely to run into any issues >>> here. Marking the test cases as "othervm" also helps to remove most edge >>> case scenarios where you could still somehow imagine this failing. (For >>> example, on a JRockit-like JVM, other tests running concurrently could >>> trigger a gc in the middle of this test resulting in the HashMap and its >>> contents being promoted to old space and the null reference not being >>> cleared during the call to System.gc() as expected.) >>> >>> One option would be to mark this as a manually-run test if we wanted to >>> be extra cautious. What do you think? >>> >>> > Minor nit, should be WeakReference<Object> to avoid the raw type. >>> >>> I will update the webrev once we have decided what (if anything) to do >>> regarding the risk of false positives. >>> >>> Cheers, >>> -Buck >>> >>> On 2013/01/30 22:09, Alan Bateman wrote: >>>> On 29/01/2013 23:36, David Buck wrote: >>>>> Hi! >>>>> >>>>> This is a review request to add only the test case for the following >>>>> OracleJDK issue : >>>>> >>>>> [ 7042126 : (alt-rt) HashMap.clone implementation should be >>>>> re-examined ] >>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7042126 >>>>> >>>>> * please note: I just marked the bug as "public" this morning, so >>>>> there will be a short delay before the above link is available. >>>>> >>>>> The issue (root cause) is not in OpenJDK (i.e. the problem was >>>>> OracleJDK specific), but the test case is valid for any Java SE >>>>> implementation so it should go into OpenJDK so we can prevent a >>>>> similar issue from ever happening in both releases moving forward. The >>>>> test case simply helps ensure that the contents of a HashMap are not >>>>> leaked when we clone the HashMap. >>>>> >>>>> webrev: >>>>> [ Code Review for jdk ] >>>>> http://cr.openjdk.java.net/~dbuck/7042126/webrev.00/ >>>> How robust is this test? I'm concerned that it might fail intermittently >>>> if the System.gc doesn't immediately GC the now un-references entries in >>>> hm. >>>> >>>> Minor nit, should be WeakReference<Object> to avoid the raw type. >>>> >>>> -Alan. >