Duplicate :
|
|
Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
The java.nio package added DirectByteBuffer and MappedByteBuffer classes that allocate native memory on the native C heap and via a platform specific memory mapping function (mmap()). The current implementation provides no api to allow Java applications to deallocate these memory regions, but instead relys upon finalizers to perform the deallocation. In some cases, particularly with applications with large heaps and light to moderate loads where collections happen infrequently, the Java process can consume memory to the point of process address space exhaustion. This problem is not unique to nio, as any native resources that rely upon finalizers for cleanup can also exhibit similar issues. However, nio exposes this issue in new ways. This problem is observable by running a nio file copy program that uses a small (8K) MappedByteBuffer to repeatedly copy a large (~7m) file within the same VM with a 50m heap. 100 iterations result in the process size growing from 84m to 564m, with pmap reporting large numbers, >60K , of 8K mapped pages. After the only minor GC, finialization kicks in and reduces the number of mapped pages. java -server -Xms50m -Xmx50m CopyFile 7 100 <src_file> <dest_file> 8192 This problem is also reproducible with the same copy program using ByteBuffer objects. With the same heap, buffer, and file sizes, the native C heap grows to nearly 2G before a minor GC event occurs. On Solaris, the C heap size does not retract. Note the collection takes 9.6s and collects 4.4K of Java heap space. The large native heap is the result of nio allocating a new DirectByteBuffer for each read and write call that uses a heap allocated ByteBuffer, creating many DirectByteBuffer objects. java -server -Xms50m -Xmx50m 3 100 <src_file> <dst_file> 8192 In a more realistic scenario, the nio HttpServer also exhibits native C heap growth when subjected to moderate loads with a 96mb Eden and 256mb heap. While ramping up load to 100 request/s, the process size grows to 437mb (248mb RSS, 142mb native C heap size) before the first minor GC (5 min after start of load). Growth eventually returns as load ramps up. Although these examples may seem dubious, they do expose some real problems. Some communication between the native allocation mechanisms and the Java garbage collectors are needed to force a GC of the Java heap when native resources exceed some threshold, possibly set by a hueristic or tunable. Otherwise, java.nio will need to provide deallocation api's so native resources can be freed long before finalization.
|