`
flychao88
  • 浏览: 753308 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

NIO DirectByteBuffer 内存泄露的测试

 
阅读更多

    写NIO程序经常使用ByteBuffer来读取或者写入数据,那么使用ByteBuffer.allocate(capability)还是使用ByteBuffer.allocteDirect(capability)来分配缓存了?第一种方式是分配JVM堆内存,属于GC管辖范围,由于需要拷贝所以速度相对较慢;第二种方式是分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝所以速度相对较快。

 

    我们肯定想选择比较快的,但问题是直接内存不属于GC管辖范围,需要弄清楚这部分内存如何管理,否则造成内存泄露就麻烦了。本地内存在JAVA中有一个对应的包装类DirectByteBuffer,该类属于Java类,适当的时候会被GC回收,当它被回收前会调用本地方法把直接内存给释放了,所以本地内存可以随DirectByteBuffer对象被回收而自动回收,貌似没有问题;但如果不断分配本地内存,堆内存很少使用,那么JVM就不需要执行GC,DirectByteBuffer对象们就不会被回收,这时候堆内存充足,但本地内存可能已经使用光了,再次尝试分配本地内存就会出现OutOfMemoryError,那程序就直接崩溃了。

 

    有没有解决方案?自动释放不靠谱,我们是否可以手动释放本地内存,把握主动权?果然DirectByteBuffer持有一个Cleaner对象,该对象有一个clean()方法可用于释放本地内存,所以需要的时候我们可以调用这个方法手动释放本地内存。

 

以下代码与测试场景帮助理解与证实以上描述。

 

代码1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.stevex.app.nio;
 
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
 
public class DirectByteBufferTest {
    public static void main(String[] args) throws InterruptedException{
            //分配128MB直接内存
        ByteBuffer bb = ByteBuffer.allocateDirect(1024*1024*128);
         
        TimeUnit.SECONDS.sleep(10);
        System.out.println("ok");
    }
 
}

 

测试用例1:设置JVM参数-Xmx100m,运行异常,因为如果没设置-XX:MaxDirectMemorySize,则默认与-Xmx参数值相同,分配128M直接内存超出限制范围。

1
2
3
4
5
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
    at java.nio.Bits.reserveMemory(Bits.java:658)
    at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
    at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:306)
    at com.stevex.app.nio.DirectByteBufferTest.main(DirectByteBufferTest.java:8)

 

测试用例2:设置JVM参数-Xmx256m,运行正常,因为128M小于256M,属于范围内分配。

1
 

 

测试用例3:设置JVM参数-Xmx256m -XX:MaxDirectMemorySize=100M,运行异常,分配的直接内存128M超过限定的100M。

1
2
3
4
5
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
    at java.nio.Bits.reserveMemory(Bits.java:658)
    at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
    at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:306)
    at com.stevex.app.nio.DirectByteBufferTest.main(DirectByteBufferTest.java:8)

 

代码2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.stevex.app.nio;
 
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import sun.nio.ch.DirectBuffer;
 
public class DirectByteBufferTest {
    public static void main(String[] args) throws InterruptedException{
        //分配512MB直接缓存
        ByteBuffer bb = ByteBuffer.allocateDirect(1024*1024*512);
         
        TimeUnit.SECONDS.sleep(10);
         
        //清除直接缓存
        ((DirectBuffer)bb).cleaner().clean();
         
        TimeUnit.SECONDS.sleep(10);
         
        System.out.println("ok");
    }
 
}

测试用例4:设置JVM参数-Xmx768m,运行程序观察内存使用变化,会发现clean()后内存马上下降,说明使用clean()方法能有效及时回收直接缓存。

分享到:
评论

相关推荐

    java nio与io性能测试

    本文将深入探讨Java NIO与IO的性能测试,并通过代码实例来展示它们之间的差异。 首先,我们来看传统的Java IO模型。IO模型基于流,数据是从输入流到输出流的单向传输。例如,`FileInputStream`和`FileOutputStream`...

    Java NIO测试示例

    使用MappedByteBuffer,NIO可以将文件映射到内存,使得文件操作如同操作内存一样快速,特别适合大数据处理。 在实际应用中,Java NIO通常用于高性能的服务器编程,例如在开发聊天服务器、Web服务器或游戏服务器时...

    nio压力测试

    5. **内存管理**:包括缓冲区分配、复用、释放等,测试需要确保在大量并发操作下,内存使用合理且无泄漏。 6. **性能指标**:如吞吐量(每秒处理的请求数)、延迟(请求到响应的时间)、CPU占用率、系统负载等都是...

    NIO服务端测试代码

    详情查看博客地址详情查看博客地址详情查看博客地址详情查看博客地址http://blog.csdn.net/g290095142/article/details/77848088

    nio测试代码

    在"nioTest"这个压缩包文件中,可能包含的是使用Java NIO编写的测试代码。这些代码可能涉及到创建通道、配置缓冲区、注册选择器以及进行非阻塞I/O操作。通过阅读和理解这些代码,你可以更深入地了解NIO的工作原理和...

    默蓝网络通信测试工具(NIOSocket工具)支持TCP/IP和HTTP通信-网络通信开发人员必备

    《网络通信测试与Java NIO Socket编程详解》 在信息技术高速发展的今天,网络通信成为了软件开发中的重要一环。为了确保网络应用的稳定性和效率,网络通信测试工具扮演了不可或缺的角色。"默蓝网络通信测试工具(NIO...

    Java-NIO-Programming-Cookbook(含源码)

    直接缓冲区使用了底层操作系统内存,避免了Java堆的分配和释放,减少了系统调用,但可能会有内存泄漏风险。 5. **缓冲区操作**:包括`put()`和`get()`方法进行数据存取,`flip()`将缓冲区从填充模式切换到读取模式...

    nio2test:测试对NIO.2 AsynchronousSocketChannel的连续写入

    NIO.2插座测试仪 一个演示应用程序,用于检查是否可以使用在TCP套接字的另一端读取所有成功的写入。 建造 仅通过从命令行运行ant即可在NetBeans中构建NetBeans ant项目: ant 跑步 在dist文件夹中创建的jar文件包含...

    Java NIO 应用使用内存映射文件实现进程间通信

    在Java NIO中,内存映射文件(MappedByteBuffer)是一个重要的特性,它允许将文件直接映射到内存中,以便于快速访问和修改文件内容。这一特性不仅提高了读写效率,而且还能用于进程间通信(IPC)。 内存映射文件的...

    java NIO.zip

    NIO允许将文件直接映射到内存,使得读写文件就像操作普通缓冲区一样快速。通过MappedByteBuffer类,可以直接在内存中对文件进行操作,提高大文件处理的性能。 7. **管道(Pipes)**: 管道用于在两个线程间创建...

    JavaNIO内存文件系统ParallelGit.zip

    ParallelGit 是为 Git 应用准备的高性能 Java NIO 内存文件系统。ParallelGit 是基于 JGit 构建的, 可以帮助 Java 项目快速的访问 Git 文件。ParallelGit 可以帮助你操作本地 Git仓库,允许你通过 Java 7 nio 文件...

    NIO与零拷贝_javanio_nio和零拷贝_

    - **直接内存(Direct Byte Buffer)**:Java NIO中的直接缓冲区可以分配在JVM堆外内存,减少从Java对象到本机内存的拷贝,从而实现零拷贝。 - **mmap(Memory Mapped File)**:Java的FileChannel提供了一个映射...

    commons-mmf.rar_java nio_java共享内存_共享内存

    在Java中,可以通过`java.nio.MappedByteBuffer`类来实现共享内存功能,这被称为内存映射文件(Memory-Mapped File,MMF)。 `MappedByteBuffer`是NIO中的一种特殊缓冲区,它将文件的一部分映射到内存中,使得文件...

    NIO客户端测试代码

    详情查看博客地址详情查看博客地址详情查看博客地址详情查看博客地址详情查看博客地址http://blog.csdn.net/g290095142/article/details/77848088

    NIO 入门.chm,NIO 入门.chm

    2. **缓冲区(Buffer)**:缓冲区是NIO中数据存储的主要对象,它是内存块的抽象,用于在通道和应用程序之间传输数据。Java NIO提供了多种类型的缓冲区,如ByteBuffer、CharBuffer、IntBuffer、FloatBuffer等,每种...

    深入浅出NIO

    - **零拷贝**:NIO通过直接内存访问(DirectByteBuffer)和通道间的复制操作,减少了数据在用户空间和内核空间之间的多次拷贝,提升了I/O效率。 在NIO中,有两种常见的通道间复制数据的方法: 1. **使用缓冲区的...

    java nio 包读取超大数据文件

    ### Java NIO 处理超大数据文件的知识点详解 ...综上所述,使用Java NIO处理超大数据文件时,关键是利用好内存映射文件技术和合理的数据读取策略,通过适当的分块和数据解析方法,可以有效地提升读取速度和处理能力。

    nio入门 IBM教材,pdf格式

    - **直接缓冲区**:NIO 还支持直接缓冲区,这是一种特殊的缓冲区,数据可以直接从它写入或读出到物理内存中,从而避免了 Java 堆上的额外拷贝操作。 #### 三、NIO 的编程实践 - **缓冲区的基本操作**:在使用 ...

Global site tag (gtag.js) - Google Analytics