NIO-直接内存
写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:
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");
} }
代码2:
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()方法能有效及时回收直接缓存。
NIO-直接内存的更多相关文章
- JAVA NIO FileChannel 内存映射文件
文件通道总是阻塞式的. 文件通道不能创建,只能通过(RandomAccessFile.FileInputStream.FileOutputStream)getChannel()获得,具有与File ...
- Java NIO之内存映射文件——MappedByteBuffer
大多数操作系统都可以利用虚拟内存实现将一个文件或者文件的一部分"映射"到内存中.然后,这个文件就可以当作是内存数组来访问,这比传统的文件要快得多. 内存映射文件的一个关键优势是操作 ...
- NIO内存映射
磁盘的IO因为速度较慢,可能成为系统运行的瓶颈.所以磁盘的IO在操作系统级实现了提前读,延迟写的机制来提升IO的性能. 提前读就是一次读取需求的数据的同时多读接下来的一段数据至OS缓冲区中,延迟写就是 ...
- JAVA NIO之浅谈内存映射文件原理与DirectMemory
JAVA类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...
- JAVA NIO 内存映射(转载)
原文地址:http://blog.csdn.net/fcbayernmunchen/article/details/8635427 Java类库中的NIO包相对于IO 包来说有一个新功能是内存 ...
- Java IO和Java NIO在文件拷贝上的性能差异分析
1. 在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区 ...
- JAVA NIO学习一:NIO简介、NIO&IO的主要区别
在前面学习了IO之后,今天我们开始进入NIO学习环节,首先我们会NIO做一个简单的介绍,让大家认识NIO,然后会和IO进行一个对比认识进行区分.好了,下面我们就开始学习: 一.NIO简介 1.概述 从 ...
- Java IO和Java NIO 和通道 在文件拷贝上的性能差异分析
1. 在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区 ...
- Java NIO2:NIO概述
一.概述 从JDK1.4开始,Java提供了一系列改进的输入/输出处理的新特性,被统称为NIO(即New I/O).新增了许多用于处理输入输出的类,这些类都被放在java.nio包及子包下,并且对原j ...
- 文件拷贝, 使用 BIO,NIO的对比,四种写法性能分析。
测试环境: jdk 1.7 + 2G内存 测试代码基本上复制了: http://blog.csdn.net/tabactivity/article/details/9317143 1 2 3 4 5 ...
随机推荐
- 让别人能登陆你的mysql
线上的数据库肯定是不能轻易在开发新功能的时候动的,如果你的数据库跟线上不一样了又没有新数据库的备份,就很麻烦. 当然去动线上数据库,出了什么问题我是不想背锅的. 最稳健的办法!让管理线上数据库的同学, ...
- leetcode563
/** * Definition for a binary tree node. * public class TreeNode { * public int val; * public TreeNo ...
- 如何让自己的exe程序开机自启动
方法一. ①鼠标右键自己的exe程序,创建快捷方式 ②win+R,打开运行对话框,输入shell:startup,如下图: 将exe文件的的快捷方式拷贝到这个目录下,然后下次重启的时候自己的应用程序就 ...
- 7.25 6figting!
TEXT 82 Proton 马来西亚宝腾汽车 A fork in the road 何去何从?(陈继龙编译) Nov 30th 2006 | HONG KONG From The Economist ...
- __stdcall详解
对_stdcall 的理解(上) 在C语言中,假设我们有这样的一个函数:int function(int a,int b) 调用时只要用result = function(1,2)这样的方式就可以使用 ...
- sqoop安装配置
下载 sqoop-1.4.5 安装包 配置 sqoop-env.sh #Set path to where bin/hadoop is available 配置Hadoop export HADOOP ...
- linux 查看文件夹文件大小数目等信息
1. 查看当前目录所有文件和文件夹的大小 方法一: $du -sh * 或 $du -h -d 0 * '-d 0' 代表查询目录的深度为0 ,也就是当前目录,'-d 3' 表示文件目录深度为3,可以 ...
- 转)bash快捷键
粗体表示推荐,也许对每个人不同. Ctrl-A 相当于HOME键,用于将光标定位到本行最前面 Ctrl-E 相当于End键,即将光标移动到本行末尾 Ctrl-B 相当于左箭头键,用于将光标向左移动一格 ...
- Code First 之类继承
关于Entity Framework 的code first 模式,相信大家都不陌生了.本文就来看看实体继承在 codefirst里的用法. 第一步 添加 code first 的环境 这里为了方便 ...
- Golang笔记之变量
哈哈 package main // 关键字var 声明变量 类型信息放在变量名后 //声明一个int型变量 var v1 int //声明一个string类型 var v2 string //声明多 ...