[ http://issues.apache.org/jira/browse/HARMONY-38?page=comments#action_12363944 ]
Paulex Yang commented on HARMONY-38: ------------------------------------ Sorry, there is a typo on my comment above, I meant the patches for AbstractMemorySpy and RuntimeMemorySpy, as what the attachments' names imply > com.ibm.platform.struct.AbstractMemorySpy doesn't actually autoFree native > memory > --------------------------------------------------------------------------------- > > Key: HARMONY-38 > URL: http://issues.apache.org/jira/browse/HARMONY-38 > Project: Harmony > Type: Bug > Components: Classlib > Reporter: Paulex Yang > Assignee: Tim Ellison > Priority: Critical > Attachments: Harmony38-AbstractMemorySpy-patch.txt, > Harmony38-RuntimeMemorySpy-patch.txt > > com.ibm.platform.struct.IMemorySpy is a memory watcher, and the > AbstractMemorySpy is a default implementation working with nio direct buffers > to free the native memories when direct buffer instances are garbage > collected. But currently its auto free donsn't work. > Look inside the orphanedMemory(Object obj) method, the memory is freed only > if the local variable wrapper can be found from the memoryInUse, a Map which > records the native memories used by direct buffers, but actually it will be > removed when autoFree(PlatfromAddress) is invoked. Checking the autoFree() > reference, I found that all DirectByteBuffer will invoke autoFree() in > constructor, which means no memory will be freed. > A simple fix: > modify the Ln 94 in autoFree() from: > wrapper = (AddressWrapper) memoryInUse.remove(address); > to: > wrapper = (AddressWrapper) memoryInUse.get(address); > and it should work. > The steps to reproduce the bug: > 1. Add the following line in the the Ln109, which indicates the memory is > auto freed by AbstractMemorySpy > System.out.println("MemorySpy autofree:"+wrapper.shadow); > 2. Run the test below: > public class MemorySpyTest { > public static void main(String[] args) throws Exception { > for (int i = 0; i < 1000; i++) { > try{ > ByteBuffer buffer = ByteBuffer.allocateDirect(1024); > buffer = null; > }catch(Exception e){ > e.printStackTrace(); > } > System.gc(); > } > } > Before modification: application exits silently. > After modification, hundres of lines printed out, like this: > ..... > MemorySpy autofree:PlatformAddress[9310024] > MemorySpy autofree:PlatformAddress[9311056] > MemorySpy autofree:PlatformAddress[9312088] > MemorySpy autofree:PlatformAddress[9313120] > MemorySpy autofree:PlatformAddress[9314152] > MemorySpy autofree:PlatformAddress[9315184] > MemorySpy autofree:PlatformAddress[9316216] > MemorySpy autofree:PlatformAddress[9317248] > ....... > Another possible pitfall in AbstractMemorySpy is it uses WeakReference and > ReferenceQueue to get notification when the buffers are ready to be garbage > collected. But it is not so safe yet to free the native memory, because the > weakly-reachable object has its chance to be resurrected to > strongly-reachable, if only some finalize() method doing this is executed. A > safer solution is to use PhantomReference instead, because phantom-reachable > object has no chance to survive. The only concern is the PhantomReference > should be explicitly cleared by application, but that's OK because the > orphanedMemory() method is a perfect candidate to do this. > I will attach the patch soon. -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: http://issues.apache.org/jira/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira
