`

Java直接内存读写

阅读更多

        在Hotspot JVM上,我们能够直接对内存进行读写操作。该类的allocateMemory方法用于申请分配内存,putAddress和getAddress方法用于对直接内存进行读写。

        下面将通过sun.misc.Unsafe演示直接读写内存的例子。

        注意:这只是一个例子,只是用来验证通过sun.misc.Unsafe来实现直接读写内存的可能性。但是,这样做并没有安全保证,而且稍微有点疏忽将可能导致JVM崩溃。

        Unsafe类的三个方法:allocateMemory,putAddress和getAddress如下:

1. long allocateMemory(long bytes)
        申请分配内存
2. long getAddress(long address) 和void putAddress(long address, long x)
        对直接内存进行读写

3.putByte、getByte方法,这两个方法deprecated了

        因为Unsafe这个类的访问是受限的,只有rt.jar中的类才能使用Unsafe的功能,它的构造方法是私有的,所以,我们不能通过new来创建实例。但是,可以通过反射的方法来获取Unsafe实例。

实例一:

package my.memory;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class DirectMemoryAccess {

    public static void main(String[] args) {

        /*
         * Unsafe的构造函数是私有的,不能通过new来获得实例。
         * 
         *  通过反射来获取
         */
        Unsafe unsafe = null;
        Field field = null;
        try {
            field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
            /*
             * private static final Unsafe theUnsafe = new Unsafe();
             * 
             * 因为field的修饰符为 private static final,
             * 需要将setAccessible设置成true,否则会报java.lang.IllegalAccessException
             */
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        long oneHundred = 100;
        byte size = 1;

        /*
         * 调用allocateMemory分配内存
         */
        long memoryAddress = unsafe.allocateMemory(size);

        /*
         * 将100写入到内存中
         */
        unsafe.putAddress(memoryAddress, oneHundred);

        /*
         * 内存中读取数据 
         */
        long readValue = unsafe.getAddress(memoryAddress);

        System.out.println("Val : " + readValue);
    }
}

输出结果:

Val : 100

 

实例二:

package my.memory;

import java.lang.reflect.Field;
import java.util.Arrays;
import sun.misc.Unsafe;

public class DirectMemoryTest {
    
    private static int byteArrayBaseOffset;

    public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException {
        
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe UNSAFE = (Unsafe) theUnsafe.get(null);
        System.out.println(UNSAFE);

        byte[] data = new byte[10];
        System.out.println(Arrays.toString(data));
        byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class);

        System.out.println("byteArrayBaseOffset:" + byteArrayBaseOffset);
        UNSAFE.putByte(data, byteArrayBaseOffset, (byte) 1);
        UNSAFE.putByte(data, byteArrayBaseOffset + 5, (byte) 5);
        
        System.out.println(Arrays.toString(data));
    }
}

运行结果:

sun.misc.Unsafe@de6ced
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
byteArrayBaseOffset:12
[1, 0, 0, 0, 0, 5, 0, 0, 0, 0]

 

实例三:

package my.memory;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class SuperArray {
    
    private final static int BYTE = 1;    
    private long size;    
    private long address;    
             
    public SuperArray(long size) {    
        this.size = size;    
        //得到分配内存的起始地址    
        address = getUnsafe().allocateMemory(size * BYTE);    
    }    
    
    public void set(long i, byte value) {    
        getUnsafe().putByte(address + i * BYTE, value);    
    }    
    public int get(long idx) {    
        return getUnsafe().getByte(address + idx * BYTE);    
    }    
    public long size() {    
        return size;    
    }
    
    private static Unsafe getUnsafe() {
        Unsafe unsafe = null;
        Field field = null;
        try {
            field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
            /*
             * private static final Unsafe theUnsafe = new Unsafe();
             * 因为field的修饰符为 private static final,
             * 需要将setAccessible设置成true,否则会报java.lang.IllegalAccessException
             */
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return unsafe;
    }
    
    public static void main(String[] args) {
        int sum = 0;
        long SUPER_SIZE = (long)Integer.MAX_VALUE * 2;    
        SuperArray array = new SuperArray(SUPER_SIZE);    
        System.out.println("Array size:" + array.size()); // 4294967294    
        for (int i = 1; i <= 100; i++) {    
            array.set((long)i, (byte)3);    
            sum += array.get((long)i);    
        }    
        System.out.println("Sum of 100 elements:" + sum);  // 300
    }
}

运行结果:

Array size:4294967294
Sum of 100 elements:300

 

参考文章:

http://mouselearnjava.iteye.com/blog/1922390

http://tech.ddvip.com/2014-06/1403069715211221_2.html

 

PS:Unsafe的源代码,请参考下面的链接
http://www.docjar.com/html/api/sun/misc/Unsafe.java.html

分享到:
评论

相关推荐

    baro:简单的基于 JNA 的本机内存读写器

    baro是一个简单的基于 JNA 的 Windows 原生内存读写器。 #####搜索进程 Baro . processByID( int processID) Baro . processByName( String processName) Baro . processByWindow( String windowName) #####写入...

    Java直接(堆外)内存使用详解

    本篇主要讲解如何使用直接内存(堆外内存),并按照下面的步骤进行说明:  相关背景–&gt;读写操作–&gt;关键属性–&gt;读写实践–&gt;扩展–&gt;参考说明  希望对想使用直接内存的朋友,提供点快捷的参考。  数据类型  ...

    JAVA上百实例源码以及开源项目

    Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非对称加密源程序代码实例,本例中使用RSA加密技术,...

    java源码包---java 源码 大量 实例

    Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非对称加密源程序代码实例,本例中使用RSA加密技术,...

    JAVA上百实例源码以及开源项目源代码

    Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非对称加密源程序代码实例,本例中使用RSA加密技术,...

    基于javadbf-0.4.0版本修改支持中文读写

    javadbf-0.4.0版本本已增加setCharactersetName方法支持中文读写,但在写入时会发生写入中文数据丢失问题。资源压缩文件包含有修改后的jar文件和读写测试类。 @Test public void testWrite1(){ File file=new File...

    Java内存模型与volatile关键字

    线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量,工作内存是线程之间独立的,线程之间变量值的传递均需要通过主内存来完成。  Volatile关键字  平时在阅读jdk源码的时候,经常看到...

    java开源包11

    DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一个完整的虚拟机以及一个 javap 字节码反汇编器。 brap(Java远程调用框架 BRAP) 一个Java远程调用框架,它将原生Java对象序列...

    java开源包4

    DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一个完整的虚拟机以及一个 javap 字节码反汇编器。 brap(Java远程调用框架 BRAP) 一个Java远程调用框架,它将原生Java对象序列...

    java开源包6

    DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一个完整的虚拟机以及一个 javap 字节码反汇编器。 brap(Java远程调用框架 BRAP) 一个Java远程调用框架,它将原生Java对象序列...

    java开源包101

    DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一个完整的虚拟机以及一个 javap 字节码反汇编器。 brap(Java远程调用框架 BRAP) 一个Java远程调用框架,它将原生Java对象序列...

    java开源包9

    DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一个完整的虚拟机以及一个 javap 字节码反汇编器。 brap(Java远程调用框架 BRAP) 一个Java远程调用框架,它将原生Java对象序列...

    java源码包4

    Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非对称加密源程序代码实例,本例中使用RSA加密技术...

    java开源包5

    DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一个完整的虚拟机以及一个 javap 字节码反汇编器。 brap(Java远程调用框架 BRAP) 一个Java远程调用框架,它将原生Java对象序列...

    java源码包3

    Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非对称加密源程序代码实例,本例中使用RSA加密技术...

    java开源包8

    DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一个完整的虚拟机以及一个 javap 字节码反汇编器。 brap(Java远程调用框架 BRAP) 一个Java远程调用框架,它将原生Java对象序列...

    java开源包10

    DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一个完整的虚拟机以及一个 javap 字节码反汇编器。 brap(Java远程调用框架 BRAP) 一个Java远程调用框架,它将原生Java对象序列...

    java内存模型(JMM).docx

    由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题:由于 CPU 执行速度很快,而从内存读取数据和向内存写入数据的过程跟 CPU 执行指令的速度比起来要差几个数量级,因此如果任何时候...

    Gazelle是一款高性能用户态协议栈 它基于DPDK在用户态直接读写网卡报文,共享大页内存传递报文,使用轻量级LwIP协议栈

    它基于DPDK在用户态直接读写网卡报文,共享大页内存传递报文,使用轻量级LwIP协议栈。能够大幅提高应用的网络I/O吞吐能力。专注于数据库网络性能加速,如MySQL、redis等。兼顾高性能与通用性:高性能。报文零拷贝,...

    java源码包2

    Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密  Java非对称加密源程序代码实例,本例中使用RSA加密技术...

Global site tag (gtag.js) - Google Analytics