DircetBuffer
- directBuffer是和Java堆相区分的,更合适的是HeapBuffer,理论上DirectBuffer大小由操作系统可以给用户进程的内存大小所决定(虚拟内存,操作系统位数)。JVM提供了虚拟机参数可以配置直接内存的大小,理论上可以配置很大,但是和操作系统紧密相关。
DirectBuffer优缺点
-
堆外内存的申请与普通的Java对象是有巨大的差别的。在以后的课程里,大家会发现,Java对象在Java堆里申请内存的时候,实际上是比malloc要快的,所以DirectBuffer的创建效率往往是比Heap Buffer差的。
-
但是,如果进行网络读写或者文件读写的时候,DirectBuffer就会比较快了,说起来好笑,这个快是因为JDK故意把非HeapBuffer的读写搞慢的,我们看一下JDK的源代码。
static int write(FileDescriptor fd, ByteBuffer src, long position,
NativeDispatcher nd)
throws IOException
{
if (src instanceof DirectBuffer)
return writeFromNativeBuffer(fd, src, position, nd);
// Substitute a native buffer
int pos = src.position();
int lim = src.limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
try {
bb.put(src);
bb.flip();
关键点在这个方法的第一行,如果src是DirectBuffer,就直接调用writeFromNativeBuffer,如果不是,则要先创建一个临时的DirectBuffer,把src拷进去,然后再调用真正的写操作。为什么要这么干呢?还是要从DirectBuffer不会被GC移动说起。
writeFromNativeBuffer的实现,最终会把Buffer的address传给操作系统,让操作系统把address开始的那一段内存发送到网络上。这就要求在操作系统进行发送的时候,这块内存是不能动的。而我们知道,GC是会乱搬Java堆里的东西的,所以无奈,我们必须得弄一块地址不会变化的内存,然后把这个地址发给操作系统。
DirectBuffer当然还有一个直观的优点,不被GC管理,所以发生GC的时候,整理内存的压力就会小。当然,我后面也会讲,它并不是完全不被GC管理,它还是能被回收的,但是在GC平常整理内存的时候确实是不会去管它的。
网友评论