Java直接内存读写的例子

18 篇文章 0 订阅
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  
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值