java不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作,主要提供了以下功能:

1、通过Unsafe类可以分配内存,可以释放内存;

类中提供的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的值

数组元素定位:

Unsafe类中有很多以BASE_OFFSET结尾的常量,比如ARRAY_INT_BASE_OFFSET,ARRAY_BYTE_BASE_OFFSET等,这些常量值是通过arrayBaseOffset方法得到的。arrayBaseOffset方法是一个本地方法,可以获取数组第一个元素的偏移地址。Unsafe类中还有很多以INDEX_SCALE结尾的常量,比如 ARRAY_INT_INDEX_SCALE , ARRAY_BYTE_INDEX_SCALE等,这些常量值是通过arrayIndexScale方法得到的。arrayIndexScale方法也是一个本地方法,可以获取数组的转换因子,也就是数组中元素的增量地址。将arrayBaseOffset与arrayIndexScale配合使用,可以定位数组中每个元素在内存中的位置。

Arrays和Java别的对象一样,都有一个对象头,它是存储在实际的数据前面的。这个头的长度可以通过unsafe.arrayBaseOffset(T[].class)方法来获取到,这里T是数组元素的类型。数组元素的大小可以通过unsafe.arrayIndexScale(T[].class) 方法获取到。这也就是说要访问类型为T的第N个元素的话,你的偏移量offset应该是arrayOffset+N*arrayScale。

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);
}
}
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操作

是通过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);

CAS操作有3个操作数,内存值M,预期值E,新值U,如果M==E,则将内存值修改为B,否则啥都不做。

【Java深入研究】8、Java中Unsafe类详解的更多相关文章

  1. JDK中Unsafe类详解

    Java中Unsafe类详解 在openjdk8下看Unsafe源码 浅析Java中的原子操作 Java并发编程之LockSupport http://hg.openjdk.java.net/jdk7 ...

  2. Java中Unsafe类详解

    http://www.cnblogs.com/mickole/articles/3757278.html Java不能直接访问操作系统底层,而是通过本地方法来访问.Unsafe类提供了硬件级别的原子操 ...

  3. Java中dimension类详解

    Java中dimension类详解 https://blog.csdn.net/hrw1234567890/article/details/81217788

  4. Java基础-进程与线程之Thread类详解

    Java基础-进程与线程之Thread类详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.进程与线程的区别 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 ...

  5. Java双刃剑之Unsafe类详解

    前一段时间在研究juc源码的时候,发现在很多工具类中都调用了一个Unsafe类中的方法,出于好奇就想要研究一下这个类到底有什么作用,于是先查阅了一些资料,一查不要紧,很多资料中对Unsafe的态度都是 ...

  6. Java中ArrayList类详解

    1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和ILis ...

  7. Java中Class类详解、用法及泛化

    Java中Class类及用法 Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI.这项信息纪录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方 ...

  8. java中File类详解

    构造函数 代码如下: public class FileDemo {     public static void main(String[] args){         //构造函数File(St ...

  9. 4、Python中的类详解(0601)

    <大话数据结构>的作者程杰在博客园也有博客,网址是:http://cj723.cnblogs.com/ 面向对象编程(OOP) 1.程序 = 指令 + 数据 代码可以选择以指令为核心或以数 ...

随机推荐

  1. Alpha冲刺 - (4/10)

    Alpha冲刺 - (4/10)   Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 ...

  2. DataBrewery Cubes 连接Kylin

    问题背景 Kylin作为一个极其优秀的MOLAP,提供了完整的Cube创建.更新流程.同时提供了Sql查询.功能上看没有问题,但是在提供查询服务的时候还是有些不友好. sql查询需要常常需要关联Hiv ...

  3. 关于调试WCF时引发的异常XmlException: Name cannot begin with the '<' character, hexadecimal value 0x3C” on Client Side

    问题描述:在使用VS2015调试WCF时,偶遇抛出异常名称不能以“<”字符(十六进制0x3c)开头,平时运行时(不调试)没有问题的. 解决方法:检查后发现为了检查异常的位置,勾选了引发通用语言运 ...

  4. [.net core学习] .net core中的Rijndael取代方法

    The difference (in .NET) between Rijndael and AES is that Rijndael allows the block size to change, ...

  5. css3 动画与display:none冲突的解决方案

    概述 css不能在display:none和display:block之间进行动画,并且也不能在height:0和height:auto之间进行动画.这里我研究了一下在display:none和dis ...

  6. OpenStack-Ocata版+CentOS7.6 云平台环境搭建 — 8.仪表盘 Dashboard(horizon)安装配置

    仪表盘Dashboard(horizon)是一个web接口,使得云平台管理员以及用户可以管理不同的Openstack资源以及服务.这个部署示例使用的是 Apache Web 服务器. 节点配置信息说明 ...

  7. 机器学习技法笔记:08 Adaptive Boosting

    Roadmap Motivation of Boosting Diversity by Re-weighting Adaptive Boosting Algorithm Adaptive Boosti ...

  8. 2D转换与3D转换的区别

    2D与3D的区别——2D 转换元素能够改变元素 x 和 y 轴.3D 转换元素还能改变其 Z 轴.

  9. 【Object类、常用API】

    Object类 1.1 概述 java.lang.Object类是Java语言中的根类,即所有类的父类.它中描述的所有方法子类都可以使用.在对象实例化的时候,最终找的父类就是Object. 如果一个类 ...

  10. [视频]K8飞刀 HackIE\EXP测试\Post提交

    [视频]K8飞刀 HackIE VS Firefox Hackbar插件功能对比 视频中可看到HackBar有缺陷导致Payload无法执行 链接:https://pan.baidu.com/s/15 ...