SoftReferences and WeakReferences
clebert.suconic Mar 10, 2006 1:58 PMAnyone know in detail when a SoftReference is supposed to be cleared?
I'm creating a testcase, using jbossProfiler interface, to validate classUnloading in a javaSerialization, and the class is not being unloaded when I expect.
the reason why I'm testing JavaSerialization, is because I was having problems with SoftReferences on JBossSerialization, and I wanted to validate the behavior of these references on a regular JavaSerialization.
There are still references on a SoftCache somewhere:
This is the testcase...
public void testJavaSerialization() throws Exception { JVMTIInterface jvmtiInterface = new JVMTIInterface(); try { serializeJava(jvmtiInterface); ClassMetamodelFactory.clear(); ArrayList newList = new ArrayList(); // forcing a OutOfMemoryError, just to see if the SoftCache is cleared as stated on SoftCache javadoc try { int count=0; while (true) { newList.add("sdflkjsdlf jsflkja dflaj df;lkjas dfokjas dfkajs dfakjsdf sdfklj sdflkjs dflksjd flskjdf slkdjf slkdfj sldkfj sldfkj sfdlkj oadsjf oaidjf aosidjf aosidjf aosdijf aoidsfj aosidjf " + (count++)); } } catch (OutOfMemoryError e) { System.out.println("Clearing newList"); jvmtiInterface.forceGC(); newList.clear(); jvmtiInterface.forceGC(); } Class clazz = jvmtiInterface.getClassByName(CLASS_NAME); if (clazz!=null) { Object obj = clazz; Object[] referenceHolders = printReferences(jvmtiInterface, obj); // You can use JBossProfiler to analyze this snapshot jvmtiInterface.heapSnapshot("./memory-tst","mem"); } assertNull("Class org.jboss.serial.memory.SomePojo should been unloaded already",clazz); } catch (Exception e) { e.printStackTrace(); Class clazz = jvmtiInterface.getClassByName(CLASS_NAME); if (clazz!=null) { Object obj = clazz; Object[] referenceHolders = printReferences(jvmtiInterface, obj); // You can use JBossProfiler to analyze this snapshot jvmtiInterface.heapSnapshot("./memory-ex2","mem"); } System.out.println("Class org.jboss.serial.memory.SomePojo should been unloaded already" + clazz); throw e; } }
And this is the serializeJava method:
Notice that if I comment out writeObject, the class is cleared from the Heap
private void serializeJava(JVMTIInterface jvmtiInterface) throws Exception { Thread newThread = new Thread() { public void run() { try { URLClassLoader loader = newClassLoader(); Class testClass = loader.loadClass(CLASS_NAME); Object someInstance = testClass.newInstance(); ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream objOut = new ObjectOutputStream(byteOut); objOut.writeObject(someInstance); objOut.flush(); loader=null; testClass=null; someInstance=null; objOut=null; } catch (Exception e) { e.printStackTrace(); } } }; newThread.start(); newThread.join(); }
I'm getting this output, for objects holding references:
References for class org.jboss.serial.memory.test.SomePojo
Reference[0]=[Ljava.lang.Object;
Reference[1]=java.util.HashMap$Entry