sun.misc.Unsafe 实例

1. sun.misc.Unsafe包下载



2. 实例化私有类


 正常情况下没法实例化一个私有构造函数的类,但是Unsafe可以做到。
[java]  view plain  copy
  1. import java.lang.reflect.Field;  
  2.   
  3. import sun.misc.Unsafe;  
  4.   
  5. public class UnsafePlayer {  
  6.       
  7.     public static void main(String[] args) throws Exception {    
  8.     //通过反射实例化Unsafe  
  9.         Field f = Unsafe.class.getDeclaredField("theUnsafe");  
  10.         f.setAccessible(true);    
  11.         Unsafe unsafe = (Unsafe) f.get(null);    
  12.     
  13.         //实例化Player  
  14.         Player player = (Player) unsafe.allocateInstance(Player.class);   
  15.         player.setName("li lei");  
  16.         System.out.println(player.getName());  
  17.           
  18.     }    
  19. }    
  20.     
  21. class Player{   
  22.       
  23.     private String name;  
  24.       
  25.     private Player(){}  
  26.       
  27.     public String getName() {  
  28.         return name;  
  29.     }  
  30.     public void setName(String name) {  
  31.         this.name = name;  
  32.     }  
  33. }  

3. cas原子级操作&&通过内存偏移地址修改变量值

  
[java]  view plain  copy
  1. import java.lang.reflect.Field;  
  2.   
  3. import sun.misc.Unsafe;  
  4.   
  5. public class UnsafePlayer {  
  6.       
  7.     public static void main(String[] args) throws Exception {    
  8.         //通过反射实例化Unsafe  
  9.         Field f = Unsafe.class.getDeclaredField("theUnsafe");  
  10.         f.setAccessible(true);    
  11.         Unsafe unsafe = (Unsafe) f.get(null);    
  12.     
  13.         //实例化Player  
  14.         Player player = (Player) unsafe.allocateInstance(Player.class);   
  15.         player.setAge(18);  
  16.         player.setName("li lei");  
  17.         for(Field field:Player.class.getDeclaredFields()){  
  18.             System.out.println(field.getName()+":对应的内存偏移地址"+unsafe.objectFieldOffset(field));  
  19.         }  
  20.         System.out.println("-------------------");  
  21.           
  22.         int ageOffset= 8;  
  23.         //修改内存偏移地址为8的值(age),返回true,说明通过内存偏移地址修改age的值成功  
  24.         System.out.println(unsafe.compareAndSwapInt(player, ageOffset, 1820));  
  25.         System.out.println("age修改后的值:"+player.getAge());  
  26.         System.out.println("-------------------");  
  27.           
  28.         //修改内存偏移地址为8的值,但是修改后不保证立马能被其他的线程看到。  
  29.         unsafe.putOrderedInt(player, 833);  
  30.         System.out.println("age修改后的值:"+player.getAge());  
  31.         System.out.println("-------------------");  
  32.           
  33.         //修改内存偏移地址为12的值,volatile修饰,修改能立马对其他线程可见  
  34.         unsafe.putObjectVolatile(player, 12"han mei");  
  35.         System.out.println("name修改后的值:"+unsafe.getObjectVolatile(player, 12));  
  36.     }    
  37. }    
  38.     
  39. class Player{   
  40.       
  41.     private int age;  
  42.       
  43.     private String name;  
  44.       
  45.     private Player(){}  
  46.       
  47.     public String getName() {  
  48.         return name;  
  49.     }  
  50.     public void setName(String name) {  
  51.         this.name = name;  
  52.     }  
  53.   
  54.     public int getAge() {  
  55.         return age;  
  56.     }  
  57.   
  58.     public void setAge(int age) {  
  59.         this.age = age;  
  60.     }  
  61.       
  62. }  


3. 创建超级数组


     java中数组的最大长度为 Integer.MAX_VALUE,正常情况下如果想创建一个大于Integer.MAX_VALUE的数组是做不到的,但是Unsafe可以,通过对内存进行直接分配实现。
[java]  view plain  copy
  1. import java.lang.reflect.Field;  
  2.   
  3. import sun.misc.Unsafe;  
  4.   
  5. public class SuperArray {  
  6.           
  7.     public static void main(String[] arg) throws Exception{  
  8.           
  9.         //通过反射实例化Unsafe  
  10.         Field f = Unsafe.class.getDeclaredField("theUnsafe");  
  11.         f.setAccessible(true);    
  12.          Unsafe unsafe = (Unsafe) f.get(null);    
  13.           
  14.          //只要内存够大,可以把这个调大,大于Integer.MAX_VALUE  
  15.          long size = (long)Integer.MAX_VALUE/2 ;    
  16.          long addr = unsafe.allocateMemory(size);  
  17.          System.out.println("unsafe address :"+addr);  
  18.            
  19.          for (int i = 0; i < size; i++) {    
  20.              unsafe.putByte(addr+i, (byte)6);   
  21.              if(unsafe.getByte(addr+i) !=6){  
  22.                  System.out.println("failed at offset");  
  23.              }   
  24.         }    
  25.     }  
  26.       
  27. }  
把size调大,size =  (long)Integer.MAX_VALUE*2,错误信息如下。
[java]  view plain  copy
  1. unsafe address :15817328  
  2. #  
  3. # A fatal error has been detected by the Java Runtime Environment:  
  4. #  
  5. #  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x61cc0350, pid=31240, tid=31324  
  6. #  
  7. # JRE version: Java(TM) SE Runtime Environment (8.0_45-b14) (build 1.8.0_45-b14)  
  8. # Java VM: Java HotSpot(TM) Client VM (25.45-b02 mixed mode windows-x86 )  
  9. # Problematic frame:  
  10. # V[thread 30484 also had an error]  
  11.   [jvm.dll+0x40350]  
  12. #  
  13. # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows  
  14. #  
  15. # An error report file with more information is saved as:  
  16. # C:\welab\workspace\Person\hs_err_pid31240.log  


4.线程挂起与恢复


  将一个线程进行挂起是通过park方法实现的,调用 park后,线程将一直阻塞直到超时或者中断等条件出现。unpark可以终止一个挂起的线程,使其恢复正常。整个并发框架中对线程的挂起操作被封装在 LockSupport类中,LockSupport类中有各种版本pack方法,但最终都调用了Unsafe.park()方法。
[java]  view plain  copy
  1. public class LockSupport {    
  2.   
  3.     /** 
  4.      * 恢复阻塞线程 
  5.      */  
  6.     public static void unpark(Thread thread) {    
  7.         if (thread != null)    
  8.             unsafe.unpark(thread);    
  9.     }    
  10.     
  11.     /** 
  12.      * 一直阻塞当前线程,调用Unsafe.park()方法 
  13.      */  
  14.     public static void park(Object blocker) {    
  15.         Thread t = Thread.currentThread();    
  16.         setBlocker(t, blocker);    
  17.         unsafe.park(false, 0L);    
  18.         setBlocker(t, null);    
  19.     }    
  20.     /** 
  21.      * 阻塞当前线程nanos纳秒 
  22.      */  
  23.     public static void parkNanos(Object blocker, long nanos) {    
  24.         if (nanos > 0) {    
  25.             Thread t = Thread.currentThread();    
  26.             setBlocker(t, blocker);    
  27.             unsafe.park(false, nanos);    
  28.             setBlocker(t, null);    
  29.         }    
  30.     }    
  31.     
  32.     public static void parkUntil(Object blocker, long deadline) {    
  33.         Thread t = Thread.currentThread();    
  34.         setBlocker(t, blocker);    
  35.         unsafe.park(true, deadline);    
  36.         setBlocker(t, null);    
  37.     }    
  38.     
  39.     /** 
  40.      * 一直阻塞当前线程 
  41.      */  
  42.     public static void park() {    
  43.         unsafe.park(false, 0L);    
  44.     }    
  45.      
  46.    /** 
  47.      * 阻塞当前线程nanos纳秒 
  48.      */  
  49.     public static void parkNanos(long nanos) {    
  50.         if (nanos > 0)    
  51.             unsafe.park(false, nanos);    
  52.     }    
  53.     
  54.     public static void parkUntil(long deadline) {    
  55.         unsafe.park(true, deadline);    
  56.     }    
  57. }    
最后看下阻塞和恢复的例子
[java]  view plain  copy
  1. import java.util.concurrent.locks.LockSupport;  
  2.   
  3. public class Lock {  
  4.      
  5.     public static void main(String[] args) throws InterruptedException {  
  6.           
  7.         ThreadPark threadPark = new ThreadPark();  
  8.         threadPark.start();  
  9.         ThreadUnPark threadUnPark = new ThreadUnPark(threadPark);  
  10.         threadUnPark.start();  
  11.         //等待threadUnPark执行成功  
  12.         threadUnPark.join();  
  13.         System.out.println("运行成功....");  
  14.     }  
  15.       
  16.       
  17.   static  class ThreadPark extends Thread{  
  18.         
  19.        public void run(){  
  20.             System.out.println(Thread.currentThread() +"我将被阻塞在这了60s....");  
  21.             //阻塞60s,单位纳秒  1s = 1000000000  
  22.             LockSupport.parkNanos(1000000000l*60);  
  23.               
  24.             System.out.println(Thread.currentThread() +"我被恢复正常了....");  
  25.        }  
  26.    }  
  27.      
  28.   static  class ThreadUnPark extends Thread{  
  29.       
  30.        public Thread thread = null;  
  31.          
  32.        public ThreadUnPark(Thread thread){  
  33.            this.thread = thread;  
  34.        }  
  35.        public void run(){  
  36.              
  37.             System.out.println("提前恢复阻塞线程ThreadPark");  
  38.             //恢复阻塞线程  
  39.             LockSupport.unpark(thread);  
  40.           
  41.        }  
  42.    }  
  43. }  

猜你喜欢

转载自blog.csdn.net/yangaliang/article/details/79729786