文章出處

在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


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()