最近看java.util.concurrent.atomic包,发现其中大量的用到Unsafe这个类。就在网上查了一下这个类到底是来干嘛的.java不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作,主要提供了以下功能:

1、内存操作

类中提供的3个本地方法allocateMemory、reallocateMemory、freeMemory分别用于分配内存,扩充内存和释放内存,与C语言中的3个方法对应.

/** 分配内存 */
public native long allocateMemory(long l);
/** 扩充内存 */
public native long reallocateMemory(long l, long l1);
/** 释放内存 */
public native void freeMemory(long l);

2、字段的定位与修改

可以定位对象某字段的内存位置,也可以修改对象的字段值,即使它是私有的;

字段的定位:
JAVA中对象的字段的定位可能通过staticFieldOffset方法实现,该方法返回给定field的内存地址偏移量,这个值对于给定的filed是唯一的且是固定不变的。

getIntVolatile方法获取对象中offset偏移地址对应的整型field的值,支持volatile load语义。

getLong方法获取对象中offset偏移地址对应的long型field的值。
数组元素定位:
1. Unsafe类中有很多以BASE_OFFSET结尾的常量,比如ARRAY_INT_BASE_OFFSET,ARRAY_BYTE_BASE_OFFSET等,这些常量值是通过arrayBaseOffset()方法得到的.arrayBaseOffset()方法是一个本地方法,可以获取数组第一个元素的偏移地址.
2. Unsafe类中还有很多以INDEX_SCALE结尾的常量,比如 ARRAY_INT__SCALE,
ARRAY_BYTE_INDEX_SCALE等,这些常量值是通过方法得到的.arrayIndexScale方法也是一个本地方法,可以获取数组的转换因子,也就是数组中元素的增量地址.

结论:
将arrayBaseOffset与arrayIndexScale配合使用,可以定位数组中每个元素在内存中的位置。

public final class Unsafe {public static final int ARRAY_INT_BASE_OFFSET;public static final int ARRAY_INT_INDEX_SCALE;public native long staticFieldOffset(Field field);public native int getIntVolatile(Object obj, long l);public native long getLong(Object obj, long l);public native int arrayBaseOffset(Class class1);public native int arrayIndexScale(Class class1);static {ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset([I);ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale([I);}
}

下面这个例子演示了简单的修改一个byte[]的数据。
这个例子在eclipse里不能直接编译,要到项目的属性,Java Compiler,Errors/Warnings中Forbidden reference(access rules)中设置为warning。

另外,因为sun.misc.Unsafe包不能直接使用,所有代码里用反射的技巧得到了一个Unsafe的实例。

public class Test {private static int byteArrayBaseOffset;public static void main(String[] args) throws SecurityException,NoSuchFieldException, IllegalArgumentException,IllegalAccessException {Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);Unsafe UNSAFE = (Unsafe) theUnsafe.get(null);System.out.println(UNSAFE);byte[] data = new byte[10];System.out.println(Arrays.toString(data));byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class);System.out.println(byteArrayBaseOffset);UNSAFE.putByte(data, byteArrayBaseOffset, (byte) 1);UNSAFE.putByte(data, byteArrayBaseOffset + 5, (byte) 5);System.out.println(Arrays.toString(data));}
}

运行结果:

sun.misc.Unsafe@6af62373
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
24
[1, 0, 0, 0, 0, 5, 0, 0, 0, 0]

3、挂起与恢复

将一个线程进行挂起是通过park方法实现的,调用 park后,线程将一直阻塞直到超时或者中断等条件出现。unpark可以终止一个挂起的线程,使其恢复正常。整个并发框架中对线程的挂起操作被封装在 LockSupport类中,LockSupport类中有各种版本pack方法,但最终都调用了Unsafe.park()方法。

public class LockSupport {public static void unpark(Thread thread) {if (thread != null)unsafe.unpark(thread);}public static void park(Object blocker) {Thread t = Thread.currentThread();setBlocker(t, blocker);unsafe.park(false, 0L);setBlocker(t, null);}public static void parkNanos(Object blocker, long nanos) {if (nanos > 0) {Thread t = Thread.currentThread();setBlocker(t, blocker);unsafe.park(false, nanos);setBlocker(t, null);}}public static void parkUntil(Object blocker, long deadline) {Thread t = Thread.currentThread();setBlocker(t, blocker);unsafe.park(true, deadline);setBlocker(t, null);}public static void park() {unsafe.park(false, 0L);}public static void parkNanos(long nanos) {if (nanos > 0)unsafe.park(false, nanos);}public static void parkUntil(long deadline) {unsafe.park(true, deadline);}
}

4、CAS操作(乐观锁)

首先介绍一下什么是Compare And Swap(CAS)?简单的说就是比较并交换。
CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。CAS 有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。” Java并发包(java.util.concurrent)中大量使用了CAS操作,涉及到并发的地方都调用了sun.misc.Unsafe类方法进行CAS操作。
在Unsafe中是通过compareAndSwapXXX方法实现的。

/**
* 比较obj的offset处内存位置中的值和期望的值,如果相同则更新。此更新是不可中断的。
*
* @param obj 需要更新的对象
* @param offset obj中整型field的偏移量
* @param expect 希望field中存在的值
* @param update 如果期望值expect与field的当前值相同,设置filed的值为这个新值
* @return 如果field的值被更改返回true
*/
public native boolean compareAndSwapInt(Object obj, long offset, int expect, int update);

转载地址:
源码剖析之sun.misc.Unsafe
Java中Unsafe类详解
JAVA并发编程学习笔记之Unsafe类

Java JDK Unsafe相关推荐

  1. JDK Unsafe类的使用与CAS原子特性

    JDK Unsafe类的使用与CAS原子特性 Java.util.concurrent.atomic包,其中包含了大量使用到Unsafe这个类 Java不能直接访问操作系统的底层,而是通过本地方法来访 ...

  2. java jdk 1.8 安装_下载、安装、配置 java jdk1.8

    近期配置react native的开发环境,所以就从配置环境开始.rn的环境配置有那么几项,其中重要的一个就是java jdk(Java Development Kit 的缩写),那么以下就是下载.安 ...

  3. Linux(Centos)之安装Java JDK及注意事项

    1.准备工作 a.因为Java JDK区分32位和64位系统,所以在安装之前必须先要判断以下我们的Centos系统为多少位系统,命令如下: uname -a 解释:如果有x86_64就是64位的,没有 ...

  4. Java JDK 11:现在可以使用所有新功能

    为什么80%的码农都做不了架构师?>>>    删除了CORBA,Java EE和JavaFX支持,但添加了十几个主要新功能 目录 哪里可以下载JDK 11 Java 11 JDK中 ...

  5. ubuntu14.04配置java jdk

    1.下载JDK 目前最新的JDK版本是: Java SE Development Kit 8u51 下载地址:http://www.oracle.com/technetwork/java/javase ...

  6. java jdk下载过慢 解决方案

    下载JDK的时候,10k每秒的速度简直难以忍受,下面列出了一些解决方法 可用的加速方法 将下载链接去掉https 由于下载时默认是https,所以会慢一些,使用http之后虽然还是慢,但是也能稳定在4 ...

  7. mac java jdk_mac下java JDK的下载安装和配置

    1.首先在Java SE Development Kit 8这个地址下下载如图的.dmg文件 这个是jdk1.8版本,当然你也可以选择其它版本. 2.下载并默认安装后,在电脑资源文件夹下找到java, ...

  8. Java jdk 安装笔记

    1,下载http://download.oracle.com/otn-pub/java/jdk/7u9-b05/jdk-7u9-linux-i586.tar.gz 2,解压 tar -zxvf jdk ...

  9. kali 安装java jdk

    先卸载原有java版本 kali自带的java版本为 Openjdk sudo apt-get remove openjdk* 卸载不需要的java软件 sudo apt autoremove 解压到 ...

最新文章

  1. Python之路--WEB框架本质
  2. TOJ_1003题解
  3. 2014年江苏省计算机二级c语言考试大纲,2009年江苏省计算机等级考试二级C语言考试大纲...
  4. html中设置td中内容的垂直位置
  5. mysql数据中文乱码_win10 系统解决mysql中文乱码问题
  6. SQL Server表结构和数据导入到MySQL
  7. 前端学习(1351)模板引擎
  8. ctf的php,CTF中常见的PHP漏洞
  9. PyOpenGL之3D界面详解(二)
  10. 【英语学习】【English L06】U03 House L6 Sharing an apartment
  11. 【设计模式】第七章 享元模式
  12. oracle 存储过程 存储 blob,穿越oracle存储过程的Blob参数上传文件
  13. 医学图像分析相关的会议
  14. 虹软2.0 离线人脸识别 Android 开发 Demo
  15. JSP页面中taglib的uri设置
  16. web安全:sql 注入
  17. 中兴新支点操作系统挺好用的,国内电脑应预装国产操作系统
  18. C语言处理中文字符,C语言中关于汉字的处理
  19. 解决 nvcc: command not found
  20. 数据安全与隐私保护要点整理

热门文章

  1. Java基础—break label 带标签的break语句的用法。
  2. python的标志为什么是蛇_Guido给Python语言起名的原因是他家有只宠物蛇
  3. CorelDRAW易拉宝设计
  4. JavaScript笔记之一:JS原生
  5. Mini LED电视大热,“智能化”渐行渐远?
  6. 又好气又好笑(语录)
  7. java三目运算符(三元运算符)
  8. 请教!rabbitMQ怎么确认同一个队列所有消费者收到消息?
  9. 华为p40手机自带计算机,华为P40自带哪些应用?
  10. 摄像头人数统计解决方案:Camlytics 2.2.8 Crack