jtulach@281: package org.apidesign.gc; jtulach@281: jtulach@281: import java.lang.ref.Reference; jtulach@281: import java.lang.ref.WeakReference; jtulach@281: import org.junit.Test; jtulach@281: import org.netbeans.junit.NbTestCase; jtulach@281: import static org.junit.Assert.*; jtulach@281: jtulach@281: // BEGIN: compiler.surprises.intro jtulach@281: public class CompilerSurprisesTest { jtulach@281: Reference cache; jtulach@281: jtulach@281: public String factory() { jtulach@281: String value = new String("Can I disappear?"); jtulach@281: cache = new WeakReference(value); jtulach@281: return value; jtulach@281: } jtulach@281: jtulach@281: @Test jtulach@281: public void checkThatTheValueCanDisapper() { jtulach@281: String retValue = factory(); jtulach@281: retValue = null; jtulach@282: assertGC("Nobody holds the string value anymore." + jtulach@282: "It can be GCed.", cache); jtulach@281: } jtulach@281: // FINISH: compiler.surprises.intro jtulach@281: jtulach@281: // BEGIN: compiler.surprises.error jtulach@281: @Test jtulach@281: public void obviouslyWithoutClearingTheReferenceItCannotBeGCed() { jtulach@281: String retValue = factory(); jtulach@281: // commented out: retValue = null; jtulach@282: assertNotGC("The reference is still on stack." + jtulach@282: "It cannot be GCed.", cache); jtulach@281: } jtulach@281: // END: compiler.surprises.error jtulach@281: jtulach@281: jtulach@281: // BEGIN: compiler.surprises.surprise jtulach@281: boolean yes = true; jtulach@281: @Test jtulach@281: public void canItBeGCedSurprisingly() { jtulach@281: String retValue; jtulach@281: if (yes) { jtulach@281: retValue = factory(); jtulach@281: } jtulach@281: assertGC("Can be GCed, as retValue is not on stack!!!!", cache); jtulach@281: } jtulach@281: // END: compiler.surprises.surprise jtulach@281: jtulach@281: jtulach@281: // BEGIN: compiler.surprises.fix jtulach@281: boolean ok = true; jtulach@281: @Test jtulach@281: public void canItBeGCedIfInitialized() { jtulach@281: String retValue = null; jtulach@281: if (ok) { jtulach@281: retValue = factory(); jtulach@281: } jtulach@281: assertNotGC("Cannot be GCed as retValue is not stack", cache); jtulach@281: } jtulach@281: // END: compiler.surprises.fix jtulach@281: jtulach@283: // BEGIN: compiler.surprises.fix.init jtulach@283: @Test public void properInitializationFixesTheProblem() { jtulach@283: String retValue; jtulach@283: if (yes) { jtulach@283: retValue = factory(); jtulach@283: } else { jtulach@283: retValue = null; jtulach@283: } jtulach@283: assertNotGC("Cannot be GCed, now the retValue is on stack", cache); jtulach@283: } jtulach@283: // END: compiler.surprises.fix.init jtulach@283: jtulach@283: // BEGIN: compiler.surprises.fix.final jtulach@284: @Test public void properUseOfFinalFixesTheProblem() { jtulach@283: final String retValue; jtulach@283: if (yes) { jtulach@283: retValue = factory(); jtulach@283: } else { jtulach@283: retValue = null; jtulach@283: } jtulach@283: assertNotGC("Cannot be GCed, now the retValue is on stack", cache); jtulach@283: } jtulach@283: // END: compiler.surprises.fix.final jtulach@283: jtulach@288: // BEGIN: compiler.surprises.scope jtulach@288: @Test public void canItBeHeldByNoLongerExistingScopeSurprisingly() { jtulach@288: { jtulach@288: Object val = factory(); jtulach@288: } jtulach@289: assertNotGC("Surprisingly this variable cannot be GCed, " + jtulach@289: "even val is out of scope!!!!", cache); jtulach@288: } jtulach@288: // END: compiler.surprises.scope jtulach@283: jtulach@281: private static void assertGC(String msg, Reference ref) { jtulach@281: NbTestCase.assertGC(msg, ref); jtulach@281: } jtulach@281: jtulach@281: private static void assertNotGC(String msg, Reference ref) { jtulach@281: try { jtulach@281: NbTestCase.assertGC("Cannot be GCed. " + msg, ref); jtulach@281: } catch (Error ex) { jtulach@281: // OK jtulach@281: return; jtulach@281: } jtulach@281: fail(msg + ref.get()); jtulach@281: } jtulach@281: }