sun.misc.Unsafe

原创 2013年12月04日 00:55:35


Unsafe在JUC里用的非常普遍,所以花时间看了看其实现, 贴先源码吧,其实并不复杂:

 

 sun.misc.Unsafe.java 源码:

 

 http://www.javasourcecode.org/html/open-source/jdk/jdk-6u23/sun/misc/Unsafe.java.html

 

从源码实现来看,Unsafe是个单例,其实例只能通过静态方法获得:

Java代码  收藏代码
  1. public static Unsafe getUnsafe() {  
  2.     Class cc = sun.reflect.Reflection.getCallerClass(2);  
  3.     if (cc.getClassLoader() != null)  
  4.         throw new SecurityException("Unsafe");  
  5.     return theUnsafe;  
  6.     }  

 

 

如果我们正常的应用程序去调用的话,会抛出SecurityException,获取实例时先看调用的类是否启动类加载器加载,不是的话就抛出异常,其comment也强调Unsafe是应用于安全性代码的.那如果我们的确需要使用时,可以通过反射,将私有变量theUnsafe(唯一实例的引用)可见,再获取:

 

Java代码  收藏代码
  1. Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");    
  2. theUnsafe.setAccessible(true);    
  3. Unsafe unsafe = (Unsafe) theUnsafe.get(null);    

 

Unsafe 也是基于CAS(compare and swap)的,CAS是现代CPU提供给并发程序使用的原语操作. 不同的CPU有不同的使用规范.在 Intel 处理器中,比较并交换通过指令的 cmpxchg 系列实现。CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B).JUC里的原子类的实现都是通过CAS,CAS能更高效的从机器码层面提供并发操作.

 

 另,相应的sun.misc.natUnsafe.cc 源码:

C代码  收藏代码
  1. #include <gcj/cni.h>  
  2. #include <gcj/field.h>  
  3. #include <gcj/javaprims.h>  
  4. #include <jvm.h>  
  5. #include <sun/misc/Unsafe.h>  
  6. #include <java/lang/System.h>  
  7. #include <java/lang/InterruptedException.h>  
  8. #include <java/lang/Thread.h>  
  9. #include <java/lang/Long.h>  
  10. #include "sysdep/locks.h"  
  11.   
  12.   
  13. // Use a spinlock for multi-word accesses  
  14.   
  15. class spinlock  
  16.   
  17. {  
  18.   
  19.   static volatile obj_addr_t lock;  
  20.   
  21. public:  
  22.   
  23. spinlock ()  
  24.   
  25.   {  
  26.   
  27.     while (! compare_and_swap (&lock, 0, 1))  
  28.   
  29.       _Jv_ThreadYield ();  
  30.   
  31.   }  
  32.   
  33.   ~spinlock ()  
  34.   
  35.   {  
  36.   
  37.     release_set (&lock, 0);  
  38.   
  39.   }  
  40.   
  41. };  
  42.   
  43. // This is a single lock that is used for all synchronized accesses if  
  44.   
  45. // the compiler can't generate inline compare-and-swap operations.  In  
  46.   
  47. // most cases it'll never be used, but the i386 needs it for 64-bit  
  48.   
  49. // locked accesses and so does PPC32.  It's worth building libgcj with  
  50.   
  51. // target=i486 (or above) to get the inlines.  
  52.   
  53. volatile obj_addr_t spinlock::lock;  
  54.   
  55. static inline bool  
  56.   
  57. compareAndSwap (volatile jint *addr, jint old, jint new_val)  
  58.   
  59. {  
  60.   
  61.   jboolean result = false;  
  62.   
  63.   spinlock lock;  
  64.   
  65.   if ((result = (*addr == old)))  
  66.   
  67.     *addr = new_val;  
  68.   
  69.   return result;  
  70.   
  71. }  
  72.   
  73. static inline bool  
  74.   
  75. compareAndSwap (volatile jlong *addr, jlong old, jlong new_val)  
  76.   
  77. {  
  78.   
  79.   jboolean result = false;  
  80.   
  81.   spinlock lock;  
  82.   
  83.   if ((result = (*addr == old)))  
  84.   
  85.     *addr = new_val;  
  86.   
  87.   return result;  
  88.   
  89. }  
  90.   
  91. static inline bool  
  92.   
  93. compareAndSwap (volatile jobject *addr, jobject old, jobject new_val)  
  94.   
  95. {  
  96.   
  97.   jboolean result = false;  
  98.   
  99.   spinlock lock;  
  100.   
  101.   if ((result = (*addr == old)))  
  102.   
  103.     *addr = new_val;  
  104.   
  105.   return result;  
  106.   
  107. }  
  108.   
  109. jlong  
  110.   
  111. sun::misc::Unsafe::objectFieldOffset (::java::lang::reflect::Field *field)  
  112.   
  113. {  
  114.   
  115.   _Jv_Field *fld = _Jv_FromReflectedField (field);  
  116.   
  117.   // FIXME: what if it is not an instance field?  
  118.   
  119.   return fld->getOffset();  
  120.   
  121. }  
  122.   
  123. jint  
  124.   
  125. sun::misc::Unsafe::arrayBaseOffset (jclass arrayClass)  
  126.   
  127. {  
  128.   
  129.   // FIXME: assert that arrayClass is array.  
  130.   
  131.   jclass eltClass = arrayClass->getComponentType();  
  132.   
  133.   return (jint)(jlong) _Jv_GetArrayElementFromElementType (NULL, eltClass);  
  134.   
  135. }  
  136.   
  137. jint  
  138.   
  139. sun::misc::Unsafe::arrayIndexScale (jclass arrayClass)  
  140.   
  141. {  
  142.   
  143.   // FIXME: assert that arrayClass is array.  
  144.   
  145.   jclass eltClass = arrayClass->getComponentType();  
  146.   
  147.   if (eltClass->isPrimitive())  
  148.   
  149.     return eltClass->size();  
  150.   
  151.   return sizeof (void *);  
  152.   
  153. }  
  154.   
  155. // These methods are used when the compiler fails to generate inline  
  156.   
  157. // versions of the compare-and-swap primitives.  
  158.   
  159. jboolean  
  160.   
  161. sun::misc::Unsafe::compareAndSwapInt (jobject obj, jlong offset,  
  162.   
  163.                                            jint expect, jint update)  
  164.   
  165. {  
  166.   
  167.   jint *addr = (jint *)((char *)obj + offset);  
  168.   
  169.   return compareAndSwap (addr, expect, update);  
  170.   
  171. }  
  172.   
  173. jboolean  
  174.   
  175. sun::misc::Unsafe::compareAndSwapLong (jobject obj, jlong offset,  
  176.   
  177.                                             jlong expect, jlong update)  
  178.   
  179. {  
  180.   
  181.   volatile jlong *addr = (jlong*)((char *) obj + offset);  
  182.   
  183.   return compareAndSwap (addr, expect, update);  
  184.   
  185. }  
  186.   
  187. jboolean  
  188.   
  189. sun::misc::Unsafe::compareAndSwapObject (jobject obj, jlong offset,  
  190.   
  191.                                                 jobject expect, jobject update)  
  192.   
  193. {  
  194.   
  195.   jobject *addr = (jobject*)((char *) obj + offset);  
  196.   
  197.   return compareAndSwap (addr, expect, update);  
  198.   
  199. }  
  200.   
  201. void  
  202.   
  203. sun::misc::Unsafe::putOrderedInt (jobject obj, jlong offset, jint value)  
  204.   
  205. {  
  206.   
  207.   volatile jint *addr = (jint *) ((char *) obj + offset);  
  208.   
  209.   *addr = value;  
  210.   
  211. }  
  212.   
  213. void  
  214.   
  215. sun::misc::Unsafe::putOrderedLong (jobject obj, jlong offset, jlong value)  
  216.   
  217. {  
  218.   
  219.   volatile jlong *addr = (jlong *) ((char *) obj + offset);  
  220.   
  221.   spinlock lock;  
  222.   
  223.   *addr = value;  
  224.   
  225. }  
  226.   
  227. void  
  228.   
  229. sun::misc::Unsafe::putOrderedObject (jobject obj, jlong offset, jobject value)  
  230.   
  231. {  
  232.   
  233.   volatile jobject *addr = (jobject *) ((char *) obj + offset);  
  234.   
  235.   *addr = value;  
  236.   
  237. }  
  238.   
  239. void  
  240.   
  241. sun::misc::Unsafe::putIntVolatile (jobject obj, jlong offset, jint value)  
  242.   
  243. {  
  244.   
  245.   write_barrier ();  
  246.   
  247.   volatile jint *addr = (jint *) ((char *) obj + offset);  
  248.   
  249.   *addr = value;  
  250.   
  251. }  
  252.   
  253. void  
  254.   
  255. sun::misc::Unsafe::putLongVolatile (jobject obj, jlong offset, jlong value)  
  256.   
  257. {  
  258.   
  259.   volatile jlong *addr = (jlong *) ((char *) obj + offset);  
  260.   
  261.   spinlock lock;  
  262.   
  263.   *addr = value;  
  264.   
  265. }  
  266.   
  267. void  
  268.   
  269. sun::misc::Unsafe::putObjectVolatile (jobject obj, jlong offset, jobject value)  
  270.   
  271. {  
  272.   
  273.   write_barrier ();  
  274.   
  275.   volatile jobject *addr = (jobject *) ((char *) obj + offset);  
  276.   
  277.   *addr = value;  
  278.   
  279. }  
  280.   
  281. #if 0  // FIXME  
  282.   
  283. void  
  284.   
  285. sun::misc::Unsafe::putInt (jobject obj, jlong offset, jint value)  
  286.   
  287. {  
  288.   
  289.   jint *addr = (jint *) ((char *) obj + offset);  
  290.   
  291.   *addr = value;  
  292.   
  293. }  
  294.   
  295. #endif  
  296.   
  297. void  
  298.   
  299. sun::misc::Unsafe::putLong (jobject obj, jlong offset, jlong value)  
  300.   
  301. {  
  302.   
  303.   jlong *addr = (jlong *) ((char *) obj + offset);  
  304.   
  305.   spinlock lock;  
  306.   
  307.   *addr = value;  
  308.   
  309. }  
  310.   
  311. void  
  312.   
  313. sun::misc::Unsafe::putObject (jobject obj, jlong offset, jobject value)  
  314.   
  315. {  
  316.   
  317.   jobject *addr = (jobject *) ((char *) obj + offset);  
  318.   
  319.   *addr = value;  
  320.   
  321. }  
  322.   
  323. jint  
  324.   
  325. sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset)  
  326.   
  327. {  
  328.   
  329.   volatile jint *addr = (jint *) ((char *) obj + offset);  
  330.   
  331.   jint result = *addr;  
  332.   
  333.   read_barrier ();  
  334.   
  335.   return result;  
  336.   
  337. }  
  338.   
  339. jobject  
  340.   
  341. sun::misc::Unsafe::getObjectVolatile (jobject obj, jlong offset)  
  342.   
  343. {  
  344.   
  345.   volatile jobject *addr = (jobject *) ((char *) obj + offset);  
  346.   
  347.   jobject result = *addr;  
  348.   
  349.   read_barrier ();  
  350.   
  351.   return result;  
  352.   
  353. }  
  354.   
  355. jlong  
  356.   
  357. sun::misc::Unsafe::getLong (jobject obj, jlong offset)  
  358.   
  359. {  
  360.   
  361.   jlong *addr = (jlong *) ((char *) obj + offset);  
  362.   
  363.   spinlock lock;  
  364.   
  365.   return *addr;  
  366.   
  367. }  
  368.   
  369. jlong  
  370.   
  371. sun::misc::Unsafe::getLongVolatile (jobject obj, jlong offset)  
  372.   
  373. {  
  374.   
  375.   volatile jlong *addr = (jlong *) ((char *) obj + offset);  
  376.   
  377.   spinlock lock;  
  378.   
  379.   return *addr;  
  380.   
  381. }  
  382.   
  383. void  
  384.   
  385. sun::misc::Unsafe::unpark (::java::lang::Thread *thread)  
  386.   
  387. {  
  388.   
  389.   natThread *nt = (natThread *) thread->data;  
  390.   
  391.   nt->park_helper.unpark ();  
  392.   
  393. }  
  394.   
  395. void  
  396.   
  397. sun::misc::Unsafe::park (jboolean isAbsolute, jlong time)  
  398.   
  399. {  
  400.   
  401.   using namespace ::java::lang;  
  402.   
  403.   Thread *thread = Thread::currentThread();  
  404.   
  405.   natThread *nt = (natThread *) thread->data;  
  406.   
  407.   nt->park_helper.park (isAbsolute, time);  
  408.   
  409. }  

 

sun.misc.Unsafe源码

  • 2017年12月04日 22:42
  • 9KB
  • 下载

sun.misc.Unsafe的各种神技

sun.misc.Unsafe源码解析,各种有趣的玩法,实例化私有构造类 创建超级数组, park阻塞 unpark恢复阻塞...

【JAVA笔记——道】JAVA内存操作 sun.misc.Unsafe类

TIP:这是一个很危险的类,不熟悉情况下别用于生产环境我们知道JAVA作为高级语言的重要创新一点就是在于JVM的内存管理功能,这完全区别于C语言开发过程中需要对变量的内存分配小心控制,JVM很大程度解...

源码剖析之sun.misc.Unsafe

转载于:http://zeige.iteye.com/blog/1182571 首先介绍一下什么是Compare And Swap(CAS)?简单的说就是比较并交换。 CAS 操作包含三个...
  • zgmzyr
  • zgmzyr
  • 2013年05月08日 21:52
  • 7825

sun.misc.Unsafe实例介绍

java.util.concurrent 包下很多类的实现用到了基于硬件的CAS算法, 不再使用synchronized关键来进行并发控制,查看相关的源码后会发现最后都指向了一个类 ,这就是SUN未开...

sun.misc.Unsafe的后启示录

come from:http://www.infoq.com/cn/articles/A-Post-Apocalyptic-sun.misc.Unsafe-WorldJava语言和JVM平台已经度过了...

sun.misc.Unsafe源码解析

sun.misc.Unsafe源码解析 CAS原子操作

java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值

我们利用JDK中的sun.misc.Unsafe来计算下字段的偏移地址,一则验证下之前文章中的结论,再则跟jol输出结果对比下。通过上面的几段代码,我们可以成功获取类中各个字段的偏移地址,这跟jol工...

聊聊序列化(二)使用sun.misc.Unsafe绕过new机制来创建Java对象

在序列化的问题域里面有一个常见的问题,就是反序列化时用何种方式来创建Java对象,因为反序列化的目的是把一段二进制流转化成一个对象。 在Java里面创建对象有几种方式: 1. 显式地调用new语句...
  • ITer_ZC
  • ITer_ZC
  • 2014年11月05日 11:59
  • 3165

关于sun.misc.Unsafe类的使用(待完善)

http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
  • wz408
  • wz408
  • 2014年12月17日 20:31
  • 850
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:sun.misc.Unsafe
举报原因:
原因补充:

(最多只允许输入30个字)