Java直接内存读写的例子

Posted 一片黑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java直接内存读写的例子相关的知识,希望对你有一定的参考价值。

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

本文将通过sun.misc.Unsafe给出一个直接读写内存的例子。 

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

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

Java代码  技术分享图片
  1. /** 
  2.           * Fetches a native pointer from a given memory address.  If the address is 
  3.           * zero, or does not point into a block obtained from {@link 
  4.           * #allocateMemory}, the results are undefined. 
  5.           * 
  6.           * <p> If the native pointer is less than  bits wide, it is extended as 
  7.           * an unsigned number to a Java long.  The pointer may be indexed by any 
  8.           * given byte offset, simply by adding that offset (as a simple integer) to 
  9.           * the long representing the pointer.  The number of bytes actually read 
  10.           * from the target address maybe determined by consulting {@link 
  11.           * #addressSize}. 
  12.           * 
  13.           * @see #allocateMemory 
  14.           */  
  15.          public native long getAddress(long address);  
  16.        
  17.          /** 
  18.           * Stores a native pointer into a given memory address.  If the address is 
  19.           * zero, or does not point into a block obtained from {@link 
  20.           * #allocateMemory}, the results are undefined. 
  21.           * 
  22.           * <p> The number of bytes actually written at the target address maybe 
  23.           * determined by consulting {@link #addressSize}. 
  24.           * 
  25.           * @see #getAddress(long) 
  26.           */  
  27.          public native void putAddress(long address, long x);  
  28.        
  29.          /// wrappers for malloc, realloc, free:  
  30.        
  31.          /** 
  32.           * Allocates a new block of native memory, of the given size in bytes.  The 
  33.           * contents of the memory are uninitialized; they will generally be 
  34.           * garbage.  The resulting native pointer will never be zero, and will be 
  35.           * aligned for all value types.  Dispose of this memory by calling {@link 
  36.           * #freeMemory}, or resize it with {@link #reallocateMemory}. 
  37.           * 
  38.           * @throws IllegalArgumentException if the size is negative or too large 
  39.           *         for the native size_t type 
  40.           * 
  41.           * @throws OutOfMemoryError if the allocation is refused by the system 
  42.           * 
  43.           * @see #getByte(long) 
  44.           * @see #putByte(long, byte) 
  45.           */  
  46.          public native long allocateMemory(long bytes);  

    

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


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

下面就是一个直接访问内存的一个例子: 

Java代码  技术分享图片
  1. import java.lang.reflect.Field;  
  2.   
  3. import sun.misc.Unsafe;  
  4.   
  5. public class DirectMemoryAccess {  
  6.   
  7.     public static void main(String[] args) {  
  8.   
  9.         /* 
  10.          * Unsafe的构造函数是私有的,不能通过new来获得实例。 
  11.          *  
  12.          *  通过反射来获取 
  13.          */  
  14.         Unsafe unsafe = null;  
  15.         Field field = null;  
  16.         try {  
  17.             field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");  
  18.             /* 
  19.              * private static final Unsafe theUnsafe = new Unsafe(); 
  20.              *  
  21.              * 因为field的修饰符为 private static final, 
  22.              * 需要将setAccessible设置成true,否则会报java.lang.IllegalAccessException 
  23.              */  
  24.             field.setAccessible(true);  
  25.             unsafe = (Unsafe) field.get(null);  
  26.         } catch (SecurityException e) {  
  27.             // TODO Auto-generated catch block  
  28.             e.printStackTrace();  
  29.         } catch (NoSuchFieldException e) {  
  30.             // TODO Auto-generated catch block  
  31.             e.printStackTrace();  
  32.         } catch (IllegalArgumentException e) {  
  33.             // TODO Auto-generated catch block  
  34.             e.printStackTrace();  
  35.         } catch (IllegalAccessException e) {  
  36.             // TODO Auto-generated catch block  
  37.             e.printStackTrace();  
  38.         }  
  39.   
  40.         long oneHundred = 100;  
  41.         byte size = 1;  
  42.   
  43.         /* 
  44.          * 调用allocateMemory分配内存 
  45.          */  
  46.         long memoryAddress = unsafe.allocateMemory(size);  
  47.   
  48.         /* 
  49.          * 将100写入到内存中 
  50.          */  
  51.         unsafe.putAddress(memoryAddress, oneHundred);  
  52.   
  53.         /* 
  54.          * 内存中读取数据  
  55.          */  
  56.         long readValue = unsafe.getAddress(memoryAddress);  
  57.   
  58.         System.out.println("Val : " + readValue);  
  59.     }  
  60. }  



输出结果: 
Val : 100 

如果,想要查阅Unsafe的源代码,请参考下面的链接. 
http://www.docjar.com/html/api/sun/misc/Unsafe.java.html 

原文 转自 :http://blog.csdn.net/joe_007/article/details/38964407





























以上是关于Java直接内存读写的例子的主要内容,如果未能解决你的问题,请参考以下文章

JVM之直接内存

关于对象的描述和JVM直接内存区

JVM 专题十三:运行时数据区直接内存

11_直接内存

NIO堆外内存与零拷贝

Java Unsafe 常用API 例子。