Unsafe类

Unsafe类

Unsafe类中的重要方法

JDK的rt.jar包中的Unsafe类提供了硬件级别的原子性操作,Unsafe类中的方法都是native方法,它们使用JNI的方式访问本地C++实现库。下面我们来了解一下Unsafe提供的几个主要的方法以及编程时如何使用Unsafe类做一些事情。

long objectFieldOffset(Field field)方法

返回指定的变量在所属类中的内存偏移地址,该偏移地址仅仅在该Unsafe函数中访问指定字段时使用。如下代码使用Unsafe类获取变量value在AtomicLong对象中的内存偏移。
在这里插入图片描述

int arrayBaseOffset(Class arrayClass)方法

获取数组中第一个元素的地址。

int arrayIndexScale(Class arrayClass)方法

获取数组中一个元素占用的字节。

boolean compareAndSwapLong(Object obj,long offset,long expect,long update)方法

比较对象obj中偏移量为offset的变量的值是否与expect相等,相等则使用update值更新,然后返回true,否则返回false。

public native long getLongvolatile(Object obj,long offset)方法

获取对象obj中偏移量为offset的变量对应volatile语义的值。

void putLongvolatile(Object obj,long offset,long value)方法

设置obj对象中offset偏移的类型为long的field的值为value,支持volatile语义。

void putOrderedLong(Object obj,long offset,long value)方法

设置obj对象中offset偏移地址对应的long型field的值为value。这是一个有延迟的putLongvolatile方法,并且不保证值修改对其他线程立刻可见。只有在变量使用volatile修饰并且预计会被意外修改时才使用该方法。

void park(boolean isAbsolute,long time)方法

阻塞当前线程,其中参数isAbsolute等于false且time等于0表示一直阻塞。

time大于0表示等待指定的time后阻塞线程会被唤醒,这个time是个相对值,是个增量值,也就是相对当前时间累加time后当前线程就会被唤醒。

如果isAbsolute等于true,并且time大于0,则表示阻塞的线程到指定的时间点后会被唤醒,这里time是个绝对时间,是将某个时间点换算为ms后的值。

另外,当其他线程调用了当前阻塞线程的interrupt方法而中断了当前线程时,当前线程也会返回,而当其他线程调用了unPark方法并且把当前线程作为参数时当前线程也会返回。

void unpark(Object thread)方法

唤醒调用park后阻塞的线程。下面是JDK8新增的函数,这里只列出Long类型操作。

long getAndSetLong(Object obj,long offset,long update)方法

获取对象obj中偏移量为offset的变量volatile语义的当前值,并设置变量volatile语义的值为update。
在这里插入图片描述

由以上代码可知,首先(1)处的getLongvolatile获取当前变量的值,然后使用CAS原子操作设置新值。

这里使用while循环是考虑到,在多个线程同时调用的情况下CAS失败时需要重试。

long getAndAddLong(Object obj,long offset,long addValue)方法

获取对象obj中偏移量为offset的变量volatile语义的当前值,并设置变量值为原始值+addValue。
在这里插入图片描述
类似getAndSetLong的实现,只是这里进行CAS操作时使用了原始值+传递的增量参数addValue的值。

如何使用Unsafe类

看到Unsafe这个类如此厉害,你肯定会忍不住试一下下面的代码,期望能够使用Unsafe做点事情。

在这里插入图片描述

代码(2.2.1)获取了Unsafe的一个实例,代码(2.2.3)创建了一个变量state并初始化为0。

代码(2.2.4)使用unsafe.objectFieldOffset获取TestUnSafe类里面的state变量,在TestUnSafe对象里面的内存偏移量地址并将其保存到stateOffset变量中。

代码(2.2.6)调用创建的unsafe实例的compareAndSwaplnt方法,设置test对象的state变量的值。

具体意思是,如果test对象中内存偏移量为stateOffset的state变量的值为0,则更新该值为1。

我们期望输出true,然而执行后会输出如下结果。
在这里插入图片描述
为找出原因,必然要查看getUnsafe的代码。

在这里插入图片描述
代码(2.2.7)获取调用getUnsafe这个方法的对象的Class对象,这里是TestUnSafe.class。

代码(2.2.8)判断是不是Bootstrap类加载器加载的localClass,在这里是看是不是Bootstrap加载器加载了TestUnSafe.class。

很明显由于TestUnSafe.class是使用AppClassLoader加载的,所以这里直接抛出了异常。

思考一下,这里为何要有这个判断?我们知道Unsafe类是rt.jar包提供的,rt.jar包里面的类是使用Bootstrap类加载器加载的,而我们的启动main函数所在的类是使用AppClassLoader加载的,所以在main函数里面加载Unsafe类时,根据委托机制,会委托给Bootstrap去加载Unsafe类。

如果没有代码(2.2.8)的限制,那么我们的应用程序就可以随意使用Unsafe做事情了,而Unsafe类可以直接操作内存,这是不安全的,所以JDK开发组特意做了这个限制,不让开发人员在正规渠道使用Unsafe类,而是在rt.jar包里面的核心类中使用Unsafe功能。

如果开发人员真的想要实例化Unsafe类,那该如何做?

方法有多种,既然从正规渠道访问不了,那么就玩点黑科技,使用万能的反射来获取Unsafe实例方法。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/329379.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

江科大STM32

目录 STM32简介 STM32简介 我们主要学习的就是STM32的外设。 NVIC:内核里面用于管理中断的设备,比如配置中断优先级这些东西SysTick:内核里面的定时器,主要用来给操作系统提供定时服务的,STM32是可以加入操作系统的&am…

OpenSource - 基于Netty的网络扩展库HServer

文章目录 概述官网Hserver的理念特点原理图代码案例HelloWorld 概述 HServer是一个基于Netty开发网络扩展库.使用插件方式来扩展我们的业务 HServer提供 web,gateway,rpc 等插件 同时用户也可以自定义插件,来完成各种各样的业务场景。 官网 https://gitee.com/HSe…

OpenGuass 之顺序扫描和索引扫描的代价估算

一. 前言 在OepnGuass中,一条路径的执行代价估算值将直接决定一条路径是否会被取舍。本文主要对OpenGuass中对于普通表的顺序扫描和索引扫描两种路径的的代价估算进行代码走读了解代价估算的整体过程。 二. 顺序扫描代价估算 顺序扫描的路径代价估算在OpenGuass中实…

如何找到 niche 出海细分市场的 IDEA

先说结论就是:看榜单 Why:为什么看榜单? 大家会问为什么?原因很简单: 熟读唐诗三百首,不会作诗也会吟不天天看榜单上相关的优秀同行,你想干啥 心法就是下苦功夫坚持,量变引起质变…

经典八股文之RocketMQ

核心概念 NameServer nameserver是整个rocketmq的大脑,是rocketmq的注册中心。broker在启动时向所有nameserver注册。生产者在发送消息之前先从 NameServer 获取 Broker 服务器地址列表(消费者一 样),然后根据负载均衡算法从列表中选择一台服务器进行消…

通用web自动扩缩容_智能运维引擎CudgX

一、概述 CudgX是星汉未来自主研发的面向云原生时代的智能运维引擎,支持根据 MetricQPS 分段耗时指标进行自动扩缩容。 通过各类服务的多维度、大规模的日志数据采集以及机器学习训练分析,对服务进行数字化、指标化度量,并基于部署的…

现有网络模型的使用及修改(VGG16为例)

VGG16 修改默认路径 import os os.environ[TORCH_HOME] rD:\Pytorch\pythonProject\vgg16 # 下载位置太大了(140多G)不提供直接下载 train_set torchvision.datasets.ImageNet(root./data_image_net, splittrain, downloadTrue, transformtorchvis…

PHP文件代码加密系统,可批量全开源

代码文件加密系统 在程序运行时,实质上是在执行机器码,而虚拟机语言的基本概念是将程序加密到一定程度,也就是说,经过加密的PHP程序在执行时会被解密成opcode继续执行。 PHP在执行时会生成opcode,然后由Zend虚拟机继…

PiflowX组件 - Filter

Filter组件 组件说明 数据过滤。 计算引擎 flink 组件分组 common 端口 Inport&#xff1a;默认端口 outport&#xff1a;默认端口 组件属性 名称展示名称默认值允许值是否必填描述例子conditioncondition“”无是过滤条件。age > 50 or age < 20 Filter示例…

Docker安装WebRTC下TURN服务

详细实现方式以及代码下载请前往 https://www.passerma.com/article/90 实现效果 一、手动构建镜像 1.新建Dockerfile文件 文件用于编译镜像 以alpine为基础镜像 添加coturn需要的依赖库 获取coturn并进行编译 通过start.sh启动turnserver服务 Dockerfile FROM alpineRUN ap…

Java学习苦旅(二十七)——Java中的集合框架

本篇博客将初略讲解Java中的集合框架及背后的数据结构。 集合框架介绍 Java 集合框架 Java Collection Framework&#xff0c;又被称为容器 &#xff08;container&#xff09;&#xff0c;是定义在java.util包下的一组接口 interfaces 和其实现类 classes 。其主要表现为将多…

OpenHarmony南向之LCD显示屏

OpenHarmony南向之LCD显示屏 概述 LCD&#xff08;Liquid Crystal Display&#xff09;驱动&#xff0c;通过对显示器上下电、初始化显示器驱动IC&#xff08;Integrated Circuit&#xff09;内部寄存器等操作&#xff0c;使其可以正常工作。 HDF Display驱动模型 LCD器件驱…