我的编程空间,编程开发者的网络收藏夹
学习永远不晚

java中Unsafe类怎么用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

java中Unsafe类怎么用

这篇文章主要介绍了java中Unsafe类怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

Unsafe类使Java拥有了像C语言的指针一样操作内存空间的能力,同时也带来了指针的问题。过度的使用Unsafe类会使得出错的几率变大,因此Java官方并不建议使用的,官方文档也几乎没有。Oracle正在计划从Java 9中去掉Unsafe类,如果真是如此影响就太大了。

java中Unsafe类怎么用
一、简单介绍

首先在Oracle的Jdk8无法获取到sun.misc包的源码,想看此包的源码可以直接下载openjdk。

1、预备工作

openjdk的源码我下载的是openjdk-8u40-class="lazy" data-src-b25-10_feb_2015,有需要的可以私信我,如果是我公众号粉丝,我会直接附加上这个百度云资源。在下载完成之后,然后就可以直接导入我们的eclipse了。

java中Unsafe类怎么用
详解Unsafe类详解Unsafe类

windows->preference->installed jres->选中jre->edit->rt.jar->source attachment->external folders->openjdk源码路径。此时就可以查看我们的Unsafe类的源码了。

2、简介说明

如果你学习了一些java并发包里面的类源码的话,对这个Unsafe类一定不陌生,整个java并发包底层实现的核心就是它,在很久之前盛传着这个类将要在jdk9移除,事实上如果移除了那么一大批框架将会消失,比如说赫赫有名的Netty框架。最终jdk9出现的时候也只是对其进行了改进和优化。不过这也再一次说明了这个类的重要地位。

为什么说它一半是天使一半是魔鬼呢?要回答这个问题,我们还是要从其特性来解释。

(1)Unsafe类使Java拥有了像C语言的指针一样操作内存空间的能力,一旦能够直接操作内存,这也就意味着(1)不受jvm管理,也就意味着无法被GC,需要我们手动GC,稍有不慎就会出现内存泄漏。

(2)Unsafe的不少方法中必须提供原始地址(内存地址)和被替换对象的地址,偏移量要自己计算,一旦出现问题就是JVM崩溃级别的异常,会导致整个JVM实例崩溃,表现为应用程序直接crash掉。

(3)直接操作内存,也意味着其速度更快,在高并发的条件之下能够很好地提高效率。

因此,从上面三个角度来看,虽然在一定程度上提升了效率但是也带来了指针的不安全性。

下面我们深入到源码中看看,提供了什么方法直接操作内存。

二、源码分析

Unsafe中一共有82个public native修饰的方法,还有几十个基于这82个public native方法的其他方法。这些方法大体可以归结为以下几类:

(1)初始化操作

(2)操作对象属性

(3)操作数组元素

(4)内存管理

(5)内存屏障

(6)线程挂起和回复

(7)CAS机制

下面我们对这些方法尽进行一个大致的分析。

1、初始化

//1、注册native方法,是的Unsafe类可以操作C语言private static native void registerNatives();static {    registerNatives();    sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");}//2、构造方法private Unsafe() {}//3、初始化方法private static final Unsafe theUnsafe = new Unsafe();//4、初始化方法实现@CallerSensitivepublic static Unsafe getUnsafe() {    Class> caller = Reflection.getCallerClass();    if (!VM.isSystemDomainLoader(caller.getClassLoader()))        throw new SecurityException("Unsafe");    return theUnsafe;}

在这里我们看到Unsafe的初始化方法主要是通过getUnsafe方法的单例模式实现的,调用JVM本地方法registerNatives()和sun.reflect.Reflection,通过Reflection的getCallerClass判断当前调用的类是否是主类加载器(BootStrap classLoader)加载的,否则的话抛出一个SecurityException。这也证明了一个问题,那就是只有由主类加载器(BootStrap classLoader)加载的类才能调用这个类中的方法。

2、操作属性方法

(1)public native Object getObject(Object o, long offset);

通过给定的Java变量获取引用值。这里实际上是获取一个Java对象o中,获取偏移地址为offset的属性的值,此方法可以突破修饰符的抑制,也就是无视private、protected和default修饰符。类似的方法有getInt、getDouble等等。同理还有putObject方法。

(2)public native Object getObjectVolatile(Object o, long offset);

强制从主存中获取属性值。类似的方法有getIntVolatile、getDoubleVolatile等等。同理还有putObjectVolatile。

(3)public native void putOrderedObject(Object o, long offset, Object x);

设置o对象中offset偏移地址offset对应的Object型field的值为指定值x。这是一个有序或者有延迟的putObjectVolatile方法,并且不保证值的改变被其他线程立即看到。只有在field被volatile修饰并且期望被修改的时候使用才会生效。类似的方法有putOrderedInt和putOrderedLong。

(4)public native long staticFieldOffset(Field f);

返回给定的静态属性在它的类的存储分配中的位置(偏移地址)。

(5)public native long objectFieldOffset(Field f);

返回给定的非静态属性在它的类的存储分配中的位置(偏移地址)。

(6)public native Object staticFieldBase(Field f);

返回给定的静态属性的位置,配合staticFieldOffset方法使用。

3、操作数组

(1)public native int arrayBaseOffset(Class arrayClass);

返回数组类型的第一个元素的偏移地址(基础偏移地址)。

(2)public native int arrayIndexScale(Class arrayClass);

返回数组中元素与元素之间的偏移地址的增量。

这两个方法配合使用就可以定位到任何一个元素的地址。

4、内存管理

(1)public native int addressSize();

获取本地指针的大小(单位是byte),通常值为4或者8。常量ADDRESS_SIZE就是调用此方法。

(2)public native int pageSize();

获取本地内存的页数,此值为2的幂次方。

(3)public native long allocateMemory(long bytes);

分配一块新的本地内存,通过bytes指定内存块的大小(单位是byte),返回新开辟的内存的地址。

(4)public native long reallocateMemory(long address, long bytes);

通过指定的内存地址address重新调整本地内存块的大小,调整后的内存块大小通过bytes指定(单位为byte)。

(5)public native void setMemory(Object o, long offset, long bytes, byte value);

将给定内存块中的所有字节设置为固定值(通常是0)。

5、线程挂起和恢复

(1)public native void unpark(Object thread);

释放被park创建的在一个线程上的阻塞。由于其不安全性,因此必须保证线程是存活的。

(2)public native void park(boolean isAbsolute, long time);

阻塞当前线程,一直等道unpark方法被调用。

6、内存屏障

(1)public native void loadFence();

在该方法之前的所有读操作,一定在load屏障之前执行完成。

(2)public native void storeFence();

在该方法之前的所有写操作,一定在store屏障之前执行完成

(3)public native void fullFence();

在该方法之前的所有读写操作,一定在full屏障之前执行完成,这个内存屏障相当于上面两个(load屏障和store屏障)的合体功能。

7、CAS机制

public final native boolean compareAndSwapObject(   Object o, long offset, Object expected, Object x);public final native boolean compareAndSwapInt(   Object o, long offset,int expected, int x);public final native boolean compareAndSwapLong(   Object o, long offset, long expected,long x);

这个Unsafe类其实是贯穿到整个java并发包体系中的,不管是你看原子包还是lock包底部都有这样的一个类,我们需要记住的不是每一个方法,而是上面七类的标题。也就是具体有什么功能。

三、使用

说了这么久的源码在这里才介绍其使用,是因为官方并不推荐我们使用,也就是说我们无法直接new出来一个Unsafe类出来,那我们该如何使用呢?在很久之前我曾写过一篇介绍java反射机制的文章,没错就是这个反射机制,牛的不行。Unsafe就可以通过反射机制来获取。

public class UnsafeTest {   public static void main(String[] args) throws Exception {       //这里的theUnsafe就是我们源码中的那个theUnsafe       Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");       theUnsafe.setAccessible(true);       Unsafe unsafe = (Unsafe) theUnsafe.get(null);       //1、创建对象实例       Author author = (Author) unsafe.allocateInstance(Author.class);       //2、操作对象的属性       Field ageField = Author.class.getDeclaredField("age");       long fieldOffset = unsafe.objectFieldOffset(ageField);       //3、操作数组       String[] strings = new String[]{"1", "2", "3"};       long i = unsafe.arrayBaseOffset(String[].class);       //4、操作内存       long address = unsafe.allocateMemory(8L);           }}

感谢你能够认真阅读完这篇文章,希望小编分享的“java中Unsafe类怎么用”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网行业资讯频道,更多相关知识等着你来学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

java中Unsafe类怎么用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

java中Unsafe类怎么用

这篇文章主要介绍了java中Unsafe类怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Unsafe类使Java拥有了像C语言的指针一样操作内存空间的能力,同时也带来了
2023-06-28

Java中Unsafe类有什么用

小编给大家分享一下Java中Unsafe类有什么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、Unsafe类是啥?Java最初被设计为一种安全的受控环境。尽
2023-06-21

Java中Unsafe怎么用

这篇文章将为大家详细讲解有关Java中Unsafe怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Unsafe是什么首先我们说Unsafe类位于rt.jar里面sun.misc包下面,Unsafe翻译
2023-06-25

使用Java怎么实现一个CAS和Unsafe类

本篇文章给大家分享的是有关使用Java怎么实现一个CAS和Unsafe类,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。两者对比sychronized和volatile都解决了内
2023-06-06

Java中Unsafe如何使用

Java中Unsafe如何使用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Unsafe介绍Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安
2023-06-15

【基本功】Java魔法类:Unsafe应用解析

大家好,我是程序员鼓励师美美~《基本功》专栏又上新了:Java中的Unsafe类在提升运行效率、增强底层资源操作能力方面有很大的用处。但如果在开发过程中使用不当,就会出现各种“莫名其妙”的问题。本篇文章将会带领你重新认识它,绕过“开发雷区”
2023-06-02

Go语言中unsafe包怎么使用

本文小编为大家详细介绍“Go语言中unsafe包怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Go语言中unsafe包怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1. 什么是unsafe包un
2023-07-05

Golang中的unsafe包有什么用

今天小编给大家分享一下Golang中的unsafe包有什么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。unsafe 包提
2023-07-05

Java中Unsafe在安全领域的使用方法

本文小编为大家详细介绍“Java中Unsafe在安全领域的使用方法”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java中Unsafe在安全领域的使用方法”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。0 前言u
2023-06-29

Java中String类怎么用

这篇文章主要为大家展示了“Java中String类怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java中String类怎么用”这篇文章吧。大部分编程语言都能够处理字符串(String)。
2023-06-02

java中Vector类怎么用

这篇文章主要讲解了“java中Vector类怎么用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中Vector类怎么用”吧!public void add(intindex, Eel
2023-06-29

sun unsafe类功能及使用注意事项是什么

这篇文章跟大家分析一下“sun unsafe类功能及使用注意事项是什么”。内容详细易懂,对“sun unsafe类功能及使用注意事项是什么”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入
2023-06-28

java中ToStringBuilder类怎么使用

ToStringBuilder类是apache.commons.lang包中的一个工具类,用于生成Java对象的toString()方法。使用ToStringBuilder类可以方便地生成对象的字符串表示。下面是ToStringBuilde
2023-09-26

java中boolean类怎么使用

Boolean类是Java中的一个包装类,用于封装基本数据类型boolean的值。Boolean类提供了一些方法和常量来操作和表示boolean类型的值。1. 声明和初始化Boolean对象:```Boolean b1 = new Bool
2023-09-29

java中peekgraphic类怎么使用

在Java中,没有名为`PeekGraphic`的标准类。我怀疑您可能指的是`java.awt.image.BufferedImage`类,它用于处理图像数据。`BufferedImage`类提供了一系列方法来创建、操作和处理图像。以下是一
2023-08-24

Java中NumberFormat类怎么使用

Java中的NumberFormat类用于格式化数字,可以将数字格式化为特定的模式,例如货币、百分比和科学计数法等。下面是使用NumberFormat类的基本步骤:1. 导入NumberFormat类:```javaimport java.
2023-09-29

java中arrays类怎么使用

在Java中,Arrays类是一个工具类,提供了一些常用的操作数组的方法。可以通过静态方法调用这些方法。以下是一些Arrays类常用的方法及使用示例:1. toString方法:将数组转换为字符串输出。```javaint[] array
2023-08-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录