`
newslxw
  • 浏览: 207781 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

MappedByteBuffer小结

阅读更多

java的内存映射文件有如下特点:

 

1,使用虚拟内存,因此分配(map)的内存大小不受JVM的-Xmx参数限制,但是也是有大小限制的,首先他理论上不能超过Integer.MAX_VALUE也就是32位操作系统的2G,其次,其实际值在不用操作系统还不一样,在win7 32位操作系统下,他不能超过1.5G,具体多少,没测出来,也不知道什么原因。

 

2, 对应读大文件,当文件超出1.5G限制是,可以重新MAP下,通过POSITION参数来获取文件后面的内容。

 

3,它的读取和来回读取要不普通IO快的多,但是单纯的写入还不如普通I/O的一般速度。此结论来自以下测试代码

package com.chat;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;


public class FileChannelStudy
{


    static String filename1 = "d:\\work\\code\\filechannelstudy.txt";
    static String filename2 = "d:\\work\\code\\file.txt";
    static String content = "abcdefghijk\r\n";
    static long size =  1024000000l;
    static long num = size / 10*6;
    static long startT = 0;
    static long endT = 0;
    
    public static void setStartT()
    { mbb = null;
                    if(cnt %50 == 0) 
                        {
                        System.gc();
                        System.out.println("call gc");
                        } 
        startT = System.currentTimeMillis();
    }
    
    public static long ellipseT()
    {
        endT = System.currentTimeMillis();
        long consumeT = endT - startT;
        System.out.println("consume time :"+ consumeT/1000 + " second");
        return consumeT / 1000;
    }
    
    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException
    {
       // readFile1();
        createFile(true);
        preparedFile1();
        preparedFile2();
        
    }
    
    public static void createFile(boolean bReCreate) throws IOException
    {
        if(!bReCreate)
        {
            File f = new File(filename1);
            if(!f.exists()) f.createNewFile();
            f = new File(filename2);
            if(!f.exists()) f.createNewFile();
        }
        else
        {
            File f = new File(filename1);
            if(f.exists()) f.delete();
            f.createNewFile();
            f = new File(filename2);
            if(f.exists()) f.delete();
            f.createNewFile();
        }
    }
    
    public static void preparedFile2() throws IOException
    {
        
        BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(filename2));
        try
        {
            System.out.println("fill file by io");
            setStartT();
            for (int i = 0; i < num; i++)
            {
                bo.write(content.getBytes());
            }
            ellipseT();
        }
        finally
        {
            if(bo != null) bo.close();
        }
    }
    
    public static void preparedFile1() throws IOException
    {
        long mapsize = content.getBytes().length*1000000*100;
        long position = 0;
        FileChannel ch = new RandomAccessFile(filename1,"rw").getChannel();
        MappedByteBuffer mbb = ch.map(MapMode.READ_WRITE, position, mapsize);
        int cnt = 0;
        try
        {
            System.out.println("fill file by nio");
            setStartT();
            for (int i = 0; i < num; i++)
            {
                if(mbb.remaining() < content.getBytes().length) 
                {
                    cnt ++;
                    position += mbb.position();
                    mbb = null;
                    if(cnt %50 == 0) 
                        {
                        System.gc();
                        System.out.println("call gc");
                        }
                    mbb =  ch.map(MapMode.READ_WRITE, position, mapsize);
                }
                mbb.put(content.getBytes());
            }
            ellipseT();
        }
        finally
        {
            if(ch != null) ch.close();
        }
    }
    
    public static void readFile1() throws IOException
    {
        long mapsize = content.getBytes().length*1000000;
        long position = 0;
        //long rper = 2000000000;
        long rper =   1300000000;
        FileChannel ch = new RandomAccessFile(filename1,"rw").getChannel();
        MappedByteBuffer mbb = ch.map(MapMode.READ_WRITE, 0, rper);
        int rs = 102400;
        byte dst[] = new byte[rs];
        int cnt = 0;
        while(mbb.hasRemaining())
        {
            ByteBuffer bb = mbb.get(dst);
            cnt ++;
            if(cnt %50 == 0) System.out.println(bb.toString());
        }
    }

}
 

4,谁然FileOutputStream也有channel功能,但是如果要用内存映射文件方式写文件,则只能使用RandomAccessFile,视乎是因为写时就有读,所以只能用它。

 

5, 他跟其他ByteBuffer不一样的地方,其他ByteBuffer需要用channel.write/read来写入/读取目标的数据,而MappedByteBuffer直接就是对于目标,它的修改会自动写入到磁盘中,除非你设定了PRIVATE。

 

6, 内存溢出问题,除了尺寸限制,在写大文件时,由于要不停的重新map,会导致内存溢出,或者说gc来不及回收内存,如上面程序,如果把prepareFile1中的

 mbb = null;
                    if(cnt %50 == 0) 
                        {
                        System.gc();
                        System.out.println("call gc");
                        }

 代码删除,则在3G左右就会报内存溢出;如果只保留mbb=null;则在5G左右报内存溢出,都保留则不报内存溢出。因此需要手工运行System.gc().

 

 

7, 对于中文读写,需要转码。

    当然原来io也需要转码,不过有InputStreamReader中可以指定字符集因此可以不自己写代码。

    如果不转码,则用UE等工具打开文件看到的是乱码,但是用java的MappedByteBuffer读取处理还是中文。

    转码代码:

 

 public static ByteBuffer getBytes(String str)
    {// 将字符转为字节(编码)
        Charset cs = Charset.forName("GBK");
        ByteBuffer bb = ByteBuffer.wrap(str.getBytes(cs));
        return bb;
    }

    public static String getChars(ByteBuffer bb)
    {// 将字节转为字符(解码)
        Charset cs = Charset.forName("GBK");
        bb.flip();
        CharBuffer cb = cs.decode(bb);

        return cb.toString();
    }
 

 

分享到:
评论

相关推荐

    深入浅出MappedByteBuffer.pdf

    深入浅出MappedByteBuffer

    Bug ID 4724038 (fs) Add unmap method to MappedByteBuffer

    Bug ID 4724038 (fs) Add unmap method to MappedByteBuffer

    文件分割和合并(您的文件大的不能传输怎么办?)

    本人初学c++,写了一个小软件,能把大文件分割问小文件,然后可以统国网络传输,到了网络另一端,再用此软件拼接! 希望用过的人能提宝贵意见! 13521825644 qq 362192302

    读取文件数据并解析成bean实体类

    很多时候需要文件做数据交互,接收到文件后需要对文件解析成bean实体类,这里提供的是工具类,任意文件转任意实体都可以,只要简单的配置一下Class类,很实用

    j2se项目源码及介绍_last指令

    函数原型 private MappedByteBuffer mappedFile2Buffer(File f) throws Exception 函数说明 把日志文件映射成内存缓冲 参数说明 @param File f日志文件 返回说明 @return MappedByteBuffer 内存映射缓冲。 异常说明 ...

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

    java的共享内存管理.基于MMF设计。封装了java.nio.MappedByteBuffer.在大流量实时业务系统时,可以极大的提高处理效率

    Android代码-BitMap

    a pratise of bigdata sorting,use some common util or class,like File,FileOutputStream,RandomAccessFile,HashMap,BufferedOutputStream,ByteBuffer,MappedByteBuffer,FileInputStream. as a newer of ...

    【密码:5261】Oracle官网下载64位-JDK14

    jdk14新特性:改进NullPointerExceptions,通过准确描述哪些变量为null...非易失性映射的字节缓冲将添加新的JDK特定文件映射模式,该模式允许FileChannel API用于创建引用非易失性内存(NVM)的MappedByteBuffer实例。

    CsvReader:CsvReader

    the performance improvement is not so much as against using MappedByteBuffer. -&gt; Otherwise I will totally use MappedByteBuffer 我无法在symbol.txt上进行验证。 单元测试:我找不到足够的时间来运行所有...

    mmf4j:MemoryMappedFiles4Java

    与已经存在的MappedByteBuffer相比,目标是更好地控制创建,修改和销毁。 它试图统一在不同操作系统上使用此类映射的接口,这意味着许多细节无法实现。 此外,在某些情况下,您可能需要完成目标平台上可能不需要的...

    mmfinvoker:简单的进程间 java 请求-响应库

    mmfinvoker 这是一个简单的 java 库,它使用 nio.MappedByteBuffer 在内存映射文件上实现请求/响应功能。

    javaredis源码-jredis-master:java实现redis

    java redis源码杰里迪斯 Java的redis实现,与redis服务器相同。 特征 ...MappedByteBuffer 2.fixed unit size ,head 4 byte write in last item position, and then each item write in 4 byte with i

    java8源码-netty-learn:这是一个用于netty学习的工程

    MappedByteBuffer DirectByteBuffer HeapByteBuffer ShortBuffer IntBuffer LongBuffer FloatBuffer DoubleBuffer CharBuffer Selector选择器 Selector的作用就是配合一个线程来管理多个channel,获取这些channel上...

    sambox:一个PDFBox分支,打算用作Sejda和PDFsam的PDF处理程序

    SAMBox使用允许使用基于java.nio.channels.FileChannel , java.io.InputStream和java.nio.MappedByteBuffer的提供的实现之一(是否缓冲)。 通过使用java.lang.StringBuilder池最小化GC。 通过绑定视图的概念直接...

    百度地图开发java源码-inertiaSearch:挑战赛

    百度地图开发java源码 tmp #inertiaSearch 2016年写的代码,现在觉得思路有很多提升的地方,但是毕竟...项目大量的使用了nio中的mmap(MappedByteBuffer) 对于原始的数据文件做内存映射,并做对应索引,所有索引做hash

    txt文档阅读器

    import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.text.DecimalFormat; import java.util.Vector; import android.graphics.Bitmap; import android.graphics.Canvas; import...

    ip地址库 很全的库

    import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.regex.Matcher; import java...

    jdk-14_linux-x64_bin.rpm

    非易失性映射的字节缓冲将添加新的 JDK 特定文件映射模式,该模式允许 FileChannel API 用于创建引用非易失性内存(NVM)的 MappedByteBuffer 实例。 358:Helpful NullPointerExceptions 改进 ...

    Android渠道打包工具packer-ng-plugin.zip

    }读取ZIP文件注释,有两个版本的实现,这里使用的是 RandomAccessFile ,另一个版本使用的是 MappedByteBuffer ,经过测试,对于特别长的注释,使用内存映射文件读取性能要稍微好一些,对于特别短的注释(比如渠道名...

Global site tag (gtag.js) - Google Analytics