【Java深入研究】8、Java中Unsafe类详解
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类详解的更多相关文章
- JDK中Unsafe类详解
Java中Unsafe类详解 在openjdk8下看Unsafe源码 浅析Java中的原子操作 Java并发编程之LockSupport http://hg.openjdk.java.net/jdk7 ...
- Java中Unsafe类详解
http://www.cnblogs.com/mickole/articles/3757278.html Java不能直接访问操作系统底层,而是通过本地方法来访问.Unsafe类提供了硬件级别的原子操 ...
- Java中dimension类详解
Java中dimension类详解 https://blog.csdn.net/hrw1234567890/article/details/81217788
- Java基础-进程与线程之Thread类详解
Java基础-进程与线程之Thread类详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.进程与线程的区别 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 ...
- Java双刃剑之Unsafe类详解
前一段时间在研究juc源码的时候,发现在很多工具类中都调用了一个Unsafe类中的方法,出于好奇就想要研究一下这个类到底有什么作用,于是先查阅了一些资料,一查不要紧,很多资料中对Unsafe的态度都是 ...
- Java中ArrayList类详解
1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和ILis ...
- Java中Class类详解、用法及泛化
Java中Class类及用法 Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI.这项信息纪录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方 ...
- java中File类详解
构造函数 代码如下: public class FileDemo { public static void main(String[] args){ //构造函数File(St ...
- 4、Python中的类详解(0601)
<大话数据结构>的作者程杰在博客园也有博客,网址是:http://cj723.cnblogs.com/ 面向对象编程(OOP) 1.程序 = 指令 + 数据 代码可以选择以指令为核心或以数 ...
随机推荐
- Codeforces Round #541--1131F. Asya And Kittens(基础并查集)
https://codeforces.com/contest/1131/problem/F #include<bits/stdc++.h> using namespace std; int ...
- 第三周Access的总结
一.问;这节课你学到了什么知识? 答:这周我学得比较少,主要是学Access的数据库进行基本的维护. 2.3数据库的基本维护 对Access定期检查,修复是整个数据库重要部分: 1.Access可修复 ...
- Buffer cache hit ratio性能计数器真的可以作为SQL Server 内存瓶颈的判断指标吗?
SQL Server中对于Buffer cache hit ratio的理解: Buffer cache hit ratio官方是这么解释的:“指示在缓冲区高速缓存中找到而不需要从磁盘中读取的页的百分 ...
- [算法专题] LinkedList
前段时间在看一本01年出的旧书<effective Tcp/Ip programming>,这个算法专题中断了几天,现在继续写下去. Introduction 对于单向链表(singly ...
- AJPFX简述:MetaTrader 4移动交易平台
(AJPFX)移动交易平台可以让客户随时通过客户手中的移动设备例如智能手机.PDA等管理自己帐户和进行交易.移动交易平台提供了完整的交易帐户管理分析选项,当客户无法使用台式计算机的时候,移动交易平台为 ...
- [Swift]扩展UIColor:实现十六进制颜色字符串与UIColor之间的相互转换
对[UIColor]进行扩展 import UIKit extension UIColor { // Hex String -> UIColor convenience init(hexStri ...
- Win10 Hyper-v下虚拟机使用无线网络
首先要承认一点的是写这个随笔更大的初衷是想吐槽,搜了半天,全是一种方法,就是创建一个新的网络适配器,配置为外部网络啥啥啥,用倒是能用,就是网速那叫一个感人,我的是电信百兆光纤网页打开都如蜗牛爬,无法忍 ...
- Jupyter中python3之numpy练习
---恢复内容开始--- Numpy_pratice In [2]: n = 10 L = [i for i in range(n)] In [3]: L * 2 Out[3]: [0, 1, 2, ...
- python3中的range函数返回的是列表吗?
注意,这里说的Python3里面的range函数,和Python2是不同的,返回的不是列表,是可迭代对象. 在python3中,如果执行下面的语句 print(range(10)) 得到结果是 ran ...
- 从零开始学 Web 之 JavaScript(二)变量
大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...