DirectBuffer

1.如何分配,分配是哪里的内存

ByteBuffer.allocateDirect()来分配(ByteBuffer.allocate()分配堆内内存),分配的是非Heap(堆外)的内存,不排除操作系统可能把directBuffer交换到磁盘。

DirectBuffer 大体原理就是使用 JavaHeap 之外的内存,这些内存不会被通常的 GC 回收,所以就规避了 GC 对应用线程的中断影响,同时也避免了内存拷贝的开销。

2.使用场景,使用效率考量

当系统应用场景满足:

  • 大量原生类型数据使用
  • 频繁IO操作
  • 系统处理响应速度要求快且稳定

DirectBuffer 在-XX:MaxDirectMemorySize=xxM 大小限制下, 使用Heap之外的内存, GC对此”无能为力” ,也就意味着规避了在高负载下频繁的GC过程对应用线程的中断影响.

3.如何回收

DirectByteBuffer 类有一个内部的静态类 Deallocator,这个类实现了 Runnable 接口并在 run() 方法内释放了内存:

那这个 Deallocator 线程是哪里调用了呢?这里就用到了 Java 的虚引用(PhantomReference),Java 虚引用允许对象被回收之前做一些清理工作。在 DirectByteBuffer 的构造方法中创建了一个 Cleaner:

cleaner = Cleaner.create(this /* 这个是 DirectByteBuffer 对象的引用 */,
new Deallocator(address, cap) /* 清理线程 */); 

而 Cleaner 类继承了 PhantomReference 类,并且在自己的 clean() 方法中启动了清理线程,当 DirectByteBuffer 被 GC 之前 cleaner 对象会被放入一个引用队列(ReferenceQueue),JVM 会启动一个低优先级线程扫描这个队列,并且执行 Cleaner 的 clean 方法来做清理工作。

4.如何监控

通过查看Bits的maxMemory和reservedMemory属性来监控使用情况。

package com.jvm.study.part2;

import java.lang.reflect.Field;

public class CollectDirectMemoryInfo {

    /**
     * @VM args:-XX:MaxDirectMemorySize=10m
     */
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException {
        //Class c = java.nio.Bits.class; //无法访问
        Class c = Class.forName("java.nio.Bits");
        Field maxMemory = c.getDeclaredField("maxMemory");
        maxMemory.setAccessible(true);
        Field reservedMemory = c.getDeclaredField("reservedMemory");
        reservedMemory.setAccessible(true);
        synchronized (c) {
            Long maxMemoryValue = (Long)maxMemory.get(null);
            Long reservedMemoryValue = (Long)reservedMemory.get(null);
            System.out.println("maxMemoryValue:"+maxMemoryValue/(1024 * 1024) + "m");
            System.out.println("reservedMemoryValue:"+reservedMemoryValue/1024 * 1024 + "m");
        }
    }
}

结果:

maxMemoryValue:10m
reservedMemoryValue:0m

5.参考

监控使用的directBuffer大小:http://stackoverflow.com/questions/3908520/looking-up-how-much-direct-buffer-memory-is-available-to-java

《应用DirectBuffer提升系统性能》http://www.tbdata.org/archives/801

《Java 的 DirectBuffer 是什么东西?》http://www.simaliu.com/archives/274.html

时间: 2024-12-26 17:25:15

DirectBuffer的相关文章

转 深入理解DirectBuffer

https://blog.csdn.net/mc90716/article/details/80041757 介绍 最近在工作中使用到了DirectBuffer来进行临时数据的存放,由于使用的是堆外内存,省去了数据到内核的拷贝,因此效率比用ByteBuffer要高不少.之前看过许多介绍DirectBuffer的文章,在这里从源码的角度上来看一下DirectBuffer的原理. 用户态和内核态 Intel的 X86架构下,为了实现外部应用程序与操作系统运行时的隔离,分为了Ring0-Ring3四种

java NIO buffer --directBuffer (2)

HeapBuffer ----堆缓冲    :其实是在java 的内存模型中,java 虚拟机可以直接管控的 DirectBuffer ---直接缓冲 :使用的是native ,与操作系统挂钩,调用的是c 或者c++ 的代码,不在java 的内存模型中,我们称为堆外内存,因为不属于java 内存模型,所以java 虚拟机管控不到: 但是 address 维护了堆外内存的引用 (在buffer 类中维护者 long address) 那么问题来了,为什么不直接用HeapBuffer 操作,反而 使

JVM -verbose参数详解(转)

转自:http://www.javaranger.com/archives/367 java -verbose[:class|gc|jni] 在输出设备上显示虚拟机运行信息. 1.java -verbose:class 在程序运行的时候有多少类被加载!你可以用verbose:class来监视,在命令行输入java -verbose:class XXX  (XXX为程序名)你会在控制台看到加载的类的情况. verbose和verbose:class含义相同,输出虚拟机装入的类的信息,显示的信息格式

Java面试15|网络

1.查看网络的统计信息: netstat -s 结果中显示统计信息,保护收发包,建立连接的数量 netstat -at 列出所有TCP端口 netstat -au 列出所有的UDP端口 netstat -aut 目前正在运行的TCP/UDP服务 netstat常用的参数如下: -s或–statistice 显示网络工作信息统计表. -t或–tcp 显示TCP传输协议的连线状况. -u或–udp 显示UDP传输协议的连线状况. -a或–all 显示所有连接中的Socket. -n或–numeric

关于写的Java书籍进展

大家好,去年说要写本Java书,近期就快出版了.眼下已经開始打印样书了,最快于本月中旬左右就能够在互动网www.china-pub.com上看到消息,其它各个站点何时会发售要看详细进货情况. 去年我预期是半年写好这本书,6个月左右确实将手稿写好,但因为是第一次写书,所以没有意料到很多review的成本也是非常高的.另外须要在每次review过后与出版社沟通,一直拖到如今才准备出版(并且还仅仅出了上冊),非常多小伙伴已经等得花儿都谢了.哈哈!我也有类似的感觉,去年写的有些内容如今已经快过时了,呵呵

java命令行

Launches a Java application. Synopsis java [options] classname [args] java [options] -jar filename [args] javaw [options] classname [args] javaw [options] -jar filename [args] options Command-line options separated by spaces. See Options. classname T

zookeeper启动流程简单梳理

等着测试童鞋完工,顺便里了下zookeeper的启动流程 zk3.4.6 启动脚本里面 nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \ -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_D

Android NDK开发篇(五):Java与原生代码通信(数据操作)

尽管说使用NDK能够提高Android程序的运行效率,可是调用起来还是略微有点麻烦.NDK能够直接使用Java的原生数据类型,而引用类型,由于Java的引用类型的实如今NDK被屏蔽了,所以在NDK使用Java的引用类型则要做对应的处理. 一.对引用数据类型的操作 尽管Java的引用类型的实如今NDK被屏蔽了,JNI还是提供了一组API,通过JNIEnv接口指针提供原生方法改动和使用Java的引用类型. 1.字符串操作 JNI把Java的字符串当作引用来处理,在NDK中使用Java的字符串,须要相

idea中使用maven运行wordcount代码

1.创建maven项目 pom文件: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apach