Java中的Unsafe

在阅读AtomicInteger的源码时,看到了这个类:sum.msic.Unsafe,之前从没见过。所以花了点时间google了一下。

 

Unsafe的源码:http://www.docjar.com/html/api/sun/misc/Unsafe.java.html

 

Unsafe源码中的描述如下:

 

 写道

A
collection of methods for performing low-level, unsafe operations.
Although the class and all methods are public, use of this class is
limited because only trusted code can obtain instances of it.

  这个类是用于执行低级别、不安全操作的方法集合。尽管这个类和所有的方法都是公开的(public),但是这个类的使用仍然受限,你无法在自己的java程序中直接使用该类,因为只有授信的代码才能获得该类的实例。

从上面的描述,可以了解到该类是用来执行较低级别的操作的,比如获取某个属性在内存中的位置,不过一般人很少会有这样的需求。在AtomicInteger的源码中相关的代码如下:

 

Java代码  

  1. // setup to use Unsafe.compareAndSwapInt for updates  
  2. private static final Unsafe unsafe = Unsafe.getUnsafe();  

  上面这行代码是获取Unsafe实例的。一般情况下,我们是拿不到该类的实例的,当然jdk库里面是可以随意使用的。

 

Java代码  

  1. static {  
  2.      try {  
  3.        valueOffset = unsafe.objectFieldOffset  
  4.            (AtomicInteger.class.getDeclaredField("value"));  
  5.      } catch (Exception ex) { throw new Error(ex); }  
  6.    }  

 

  上面这几行代码,是用来获取AtomicInteger实例中的value属性在内存中的位置。这里使用了Unsafe的objectFieldOffset方法。这个方法是一个本地方法, 该方法用来获取一个给定的静态属性的位置。

 

Java代码  

  1. public native long objectFieldOffset(Field f);  

 

这里有个疑问,为什么需要获取属性在内存中的位置?通过查看AtomicInteger源码发现,在这样几个地方使用到了这个valueOffset值:

 

Java代码  

  1. public final void lazySet(int newValue) {  
  2.         unsafe.putOrderedInt(this, valueOffset, newValue);  
  3.     }  

 

Java代码  

  1. public final boolean compareAndSet(int expect, int update) {  
  2.     return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  
  3.     }  

 

Java代码  

  1. public final boolean weakCompareAndSet(int expect, int update) {  
  2.     return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  
  3.     }  

 

  查找资料后,发现lazySet方法大多用在并发的数据结构中,用于低级别的优化。compareAndSet这个方法多见于并发控制中,简称CAS(Compare
And
Swap),意思是如果valueOffset位置包含的值与expect值相同,则更新valueOffset位置的值为update,并返回true,否则不更新,返回false。(valueOffset代表内存地址)

这里可以举个例子来说明compareAndSet的作用,如支持并发的计数器,在进行计数的时候,首先读取当前的值,假设值为a,对当前值
+
1得到b,但是+1操作完以后,并不能直接修改原值为b,因为在进行+1操作的过程中,可能会有其它线程已经对原值进行了修改,所以在更新之前需要判断原值是不是等于a,如果不等于a,说明有其它线程修改了,需要重新读取原值进行操作,如果等于a,说明在+1的操作过程中,没有其它线程来修改值,我们就可以放心的更新原值了。

 

Unsafe类中还包含有很多其它的方法,如果想使用其中的方法,可以通过反射机制拿到Unsafe中的一个静态属性theUnsafe ,这个静态属性本身已经初始化了,所以拿到以后可以直接使用。

原文链接:[http://wely.iteye.com/blog/2326344]

时间: 2024-08-30 21:11:12

Java中的Unsafe的相关文章

求教java中的unsafe.allocateMemory() 会导致内存申请失败吗?

问题描述 求教java中的unsafe.allocateMemory() 会导致内存申请失败吗? 在jre 1.6.0_26中,unsafe.allocateMemory()函数的调用后, 出现 malloc.c 5147:malloc_consolidate: Assertionnextchunk->fd_nextsize->bk_nextsize == nextchunk failed. java程序崩溃. 请问这这个是什么情况? 是段错误,还是内存不足? 解决方案 这个方法就是申请内存的

由ArrayList来深入理解Java中的fail-fast机制_java

1. fail-fast简介"快速失败"也就是fail-fast,它是Java集合的一种错误检测机制.某个线程在对collection进行迭代时,不允许其他线程对该collection进行结构上的修改. 例如:假设存在两个线程(线程1.线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fa

java中为什么有的变量声明而不赋值?

问题描述 java中为什么有的变量声明而不赋值? java中为什么有的变量声明而不赋值?而有的就值,那什么情况下要赋值,什么情况下不赋值 解决方案 比如对象变量,而调用这个变量的构造函数非常耗费时间,所以我们等用到的时候再创建,如果程序运行完都不访问它,就根本不创建,这样可以提高效率. 对于简单变量,比如int float一类的,建议随手给一个初始值. 解决方案二: 你这个问题给你举个例子,你应该就能理解了 例如: int a; 这是只声明不赋值,则只会在内存的栈区创建引用,堆中并无此引用的指向

Java中透明和不规则Swing窗口

支持透明和不规则窗口已经成为 AWT 和 Swing 团队长久以来梦寐以求的功能.尽管本机应用程序在主要操作系统上使用这项功能已经为时 已久,但在核心 Java 中还不能使用它.即将发布的 "Consumer JRE"正在进行修改,也就是对 Java SE 6 进行重大更新.Java SE 6 将为 创建不规则.全透明和每个像素透明的顶级窗口提供 API. 历史 本机应用程序的开发人员通常在开发 UI 应用程序中享受了更高级的灵活性.但是为此而付出的代价是将应用程序限制在某一特定平台上

求大神解答一下-java中对象流objectstream问题

问题描述 java中对象流objectstream问题 输出的为什么不是cyh男20 ym女20求大神解答!!!!!!!!!! 解决方案 你的代码和我这个一样吗?麻烦把你的代码粘全了,我看看 解决方案二: 这个是照片......... 解决方案三: 我和你写的差不多,不知道你为啥会这样,我给你粘出我的代码package lianxi; import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOE

java中如何让setText方法读取指定标签数据的时候特意空出一点点空间

问题描述 java中如何让setText方法读取指定标签数据的时候特意空出一点点空间 如何让setText方法读取指定标签数据的时候特意空出一点点空间java当中 解决方案 http://zhidao.baidu.com/link?url=znfx-j9HEz7fJS4EcXcc-gX096uqEKQMTQo4vBNrc9bhRAlFHGGxkAP8cPTOkATWxy3DqxQwhBwFAscWkNPxe_,用空字符串占位置看看可不可以也就是字符串前面有空格,后面有空格. 解决方案二: 使用全

如何在java中实现读取一个txt文档中的随机一行

问题描述 如何在java中实现读取一个txt文档中的随机一行 如题,如何在java中实现读取一个txt文档中的随机一行? 主要就是怎么随机读取 解决方案 根据楼上的说法,来总结一下吧,总体来说,就是将文件全部都读取出来,每一行存储到一个数组或集合中,然后再通过产生随机数,来对这个数组或是 集合进行随机的访问.这样一来就解决了 解决方案二: 文本文件只能顺序读,不能随机读.你的需求只能是读取文本文件每一行到一个arraylist,然后得到下标范围,产生一个随机数,取那一行 解决方案三: http:

java循环集合-java中死循环是什么意思

问题描述 java中死循环是什么意思 java中死循环是什么意思 循环一次不再循环是死循环还是不断循环才是死循环能否简单的举个死循环单身例子 解决方案 死循环就是循环语句的条件是永远为真,那么循环体将一直执行,一楼说的并不对,循环不一定会导致内存溢出的,只是Java程序一直运行.简单的死循环实例while(true){某个操作,但是没有break语句}循环体中也没有终止循环的break,就是死循环了. 解决方案二: 不断循环直到你內存溢出 解决方案三: while(true){System.ou

java中怎样实现矢量图

问题描述 java中怎样实现矢量图 java中怎样实现矢量图的缩放,百度地图中的图片是什么格式的,其是怎样实现缩放的 解决方案 百度地图是在服务器端根据矢量图渲染好图片,传输给客户端的, 换句话说,在客户端,它已经是点阵图了.