Java 2 SE 6 doc :
Given a direct byte buffer, the Java virtual machine will make a best effort to perform native I/O operations directly upon it. That is, it will attempt to avoid copying the buffer’s content to (or from) an intermediate buffer before (or after) each invocation of one of the underlying operating system’s native I/O operations.
Java 2 SE 6 doc :
The contents of direct buffers may reside outside of the normal garbage-collected heap, and so their impact upon the memory footprint of an application might not be obvious.
//directMemory ,默认64M String s = (String) properties.remove("sun.nio.MaxDirectMemorySize"); if (s != null) if (s.equals("-1")) { directMemory = Runtime.getRuntime().maxMemory(); } else { long l = Long.parseLong(s); if (l > -1L) directMemory = l; }
DirectByteBuffer如何内存回收
实现了一个Cleaner
cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
Deallocator,实现内存回收
if (address == 0) { // Paranoia return; } unsafe.freeMemory(address); address = 0; Bits.unreserveMemory(size, capacity); }
在什么时候被调用?
看看Reference里的奥秘,它内部有一个Thread ReferenceHandler,它的run 方法会调用Cleaner.clean
//截取部分代码 Reference r; synchronized (lock) { if (pending != null) { r = pending; Reference rn = r.next; pending = (rn == r) ? null : rn; r.next = r; } else { try { lock.wait(); } catch (InterruptedException x) { } continue; } } // Fast path for cleaners if (r instanceof Cleaner) { ((Cleaner)r).clean(); continue; }
sun.nio.ch.IOUtil
static int read(FileDescriptor filedescriptor, ByteBuffer bytebuffer, long l, NativeDispatcher nativedispatcher, Object obj) throws IOException { ByteBuffer bytebuffer1; if(bytebuffer.isReadOnly()) throw new IllegalArgumentException("Read-only buffer"); if(bytebuffer instanceof DirectBuffer) return readIntoNativeBuffer(filedescriptor, bytebuffer, l, nativedispatcher, obj); bytebuffer1 = null; int j; bytebuffer1 = Util.getTemporaryDirectBuffer(bytebuffer.remaining()); int i = readIntoNativeBuffer(filedescriptor, bytebuffer1, l, nativedispatcher, obj); bytebuffer1.flip(); if(i > 0) bytebuffer.put(bytebuffer1); j = i; Util.offerFirstTemporaryDirectBuffer(bytebuffer1); return j; Exception exception; exception; Util.offerFirstTemporaryDirectBuffer(bytebuffer1); throw exception; }NativeDispatcher的实现类SocketDispatcher的read方法是native
static native int read0(FileDescriptor filedescriptor, long l, int i) throws IOException;
-XX:MaxDirectMemorySize
This option specifies the maximum total size of java.nio (New I/O package) direct buffer allocations.
-XX:MaxDirectMemorySize=size[g|G|m|M|k|K]
java -XX:MaxDirectMemorySize=2g myApp
The default value is zero, which means the maximum direct memory is unbounded.
参考:http://www.tbdata.org/archives/801