【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.程序 = 指令 + 数据 代码可以选择以指令为核心或以数 ...
随机推荐
- 中国移动物联网ONENET平台数据本地采集工具
吧从中国移动物联网平台上接收的数据 实时按天保存为CSV文件或者是SQL SERVER数据库中方便进行数据处理 还可设置显示最大值,最小值,报警值,报警推送,tts语音报警等贴心功能
- [ 9.29 ]CF每日一题系列—— 765B字符串规律
Description: 遇到了ogo可以变成***如果ogo后面有go统统忽略,输出结果 Solution: 哎如果我一开始对题意的解读如上的话,就不会被整的那么麻烦了 Code: #include ...
- Mac 下 Java 多版本切换
Step 1: 安装 jdk1.7 jdk1.8 路径如下: + /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk + /Library/Java/J ...
- Ngon 是啥
https://www.gamefromscratch.com/post/2011/07/11/So-whats-an-ngon-anyways.aspx 在 blender 里面 Add 一个 Cy ...
- 第二十二节:Java语言基础-详细讲解位运算符与流程控制语句
位运算符(二进制位运算) 运算符 运算 例子 << 左移 3 << 2 = 12 --> 3 * 2 * 2 =12 >> 右移 3 >> 1 = ...
- centos7.2 安装 mysql5.7
一.MySQL 5.7 主要特性: 原生支持 Systemd 更好的性能:对于多核 CPU.固态硬盘.锁有着更好的优化更好的 InnoDB 存储引擎 更为健壮的复制功能:复制带来了数据完全不丢失的方案 ...
- vertical-align css属性
vertical-align 属性设置元素的垂直对齐方式. vertical-align 的属性值: baseline:默认.元素放置在父元素的基线上. sub:垂直对齐文本的下标. super:垂直 ...
- Mac-让 Finder 显示隐藏文件和文件夹
打开「终端」,输入以下内容,然后「Return」键,这样就把隐藏的文件和文件夹显示了: defaults write com.apple.finder AppleShowAllFiles -boole ...
- django 模型关系
模型关系 关系数据库的威力体现在表之间的相互关联,Django提供了三种最常见的数据库关系:多对一 (many-to-one),多对多(many-to-many),一对一(one-to-one) 多对 ...
- C# datagridview分页功能
winform开发是或多或少都会接触datagridview控件,如果数据量大,那么必须使用分页功能,但是datagridview自身并没有分页,所以我们要自己实现.在网上搜了一些发现没有太适合自己的 ...