iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >sun unsafe类功能及使用注意事项是什么
  • 884
分享到

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

2023-06-28 23:06:47 884人浏览 安东尼
摘要

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

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

Unsafe简介

Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。

但由于Unsafe类使Java语言拥有了类似C语言指针一样操作内存空间的能力,这无疑也增加了程序发生相关指针问题的风险。

在程序中过度、不正确使用Unsafe类会使得程序出错的概率变大,使得Java这种安全的语言变得不再“安全”,因此对Unsafe的使用一定要慎重。

获取Unsafe实例

private static sun.misc.Unsafe getUnsafe() {        try {            return AccessController.doPrivileged(new PrivilegedExceptionAction<Unsafe>() {                @Override                public sun.misc.Unsafe run() throws Exception {                    Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;                    for (Field f : k.getDeclaredFields()) {                        f.setAccessible(true);                        Object x = f.get(null);                        if (k.isInstance(x)) {                            return k.cast(x);                        }                    }                    // The sun.misc.Unsafe field does not exist.                    throw new Error("unsafe is null");                }            });        } catch (Throwable e) {            throw new Error("get unsafe failed", e);        }    }

Unsafe功能列表

  • allocateMemory/freeMemory,分配、释放堆外内存DirectMemory(和c/cpp中的malloc一样)

  • CAS操作

  • copyMemory

  • defineClass(without security checks)

  • get/put address 使用堆外内存地址进行数据的读写操作

  • get/put volatile 使用堆外内存地址进行数据的读写操作 - volatile版本

  • loadFence/storeFence/fullFence 禁止指令重排序

  • park/unpark 阻塞/解除阻塞线程

Unsafe的数组操作

unsafe中,有两个关于数组的方法:

public native int arrayBaseOffset(Class<?> arrayClass);public native int arrayIndexScale(Class<?> arrayClass);

base offset含义

首先,在Java中,数组也是对象

In the Java programming language, arrays are objects (&sect;4.3.1), are dynamically created, and may be assigned to variables of type Object (&sect;4.3.2). All methods of class Object may be invoked on an array.
https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html

那么既然是对象,就会有object header,占用一部分空间,那么理解数组的base offset也就不难了

比如下面的一段JOL输出,实际上对象的属性数据是从OFFSET 16的位置开始的,0-12的空间被header所占用

HotSpot 64-bit VM, COOPS, 8-byte alignmentlambda.Book object internals: OFFSET  SIZE           TYPE DESCRIPTION                               VALUE      0    12                (object header)                           N/A     12     4            int Book.sales                                N/A     16     4         String Book.title                                N/A     20     4      LocalDate Book.publishTime                          N/A     24     4         String Book.author                               N/A     28     4   List<String> Book.tags                                 N/AInstance size: 32 bytesSpace losses: 0 bytes internal + 0 bytes external = 0 bytes total

那么如果要访问对象的属性数据,需要基于基地址(base address)进行偏移,基地址+基础偏移(base offset)+属性偏移(field offset)才是数据的内存地址(逻辑),那么title属性的内存地址实际上就是:

book(instance).title field address = book object base address + base offset + title field offset

数组在Java里可以视为一种特殊的对象,无论什么类型的数组,他们在内存中都会有一分基础偏移的空间,和object header类似

经过测试,64位的JVM数组类型的基础偏移都是16(测试结果在不同JVM下可能会有所区别)
原始类型的基础偏移都是12(测试结果在不同JVM下可能会有所区别)
可以使用JOL工具查看原始类型包装类的offset,比如int就看Integer的,虽然jdk没有提供函数,但是通过JOL也是可以获取的,jvm类型和对其方式匹配即可

index scale含义

就是指数组中每个元素所占用的空间大小,比如int[] scale就是4,long[] scale就是8,object[] scale就是4(指针大小)

有了这个offset,就可以对数组进行copyMemory操作了

public native void copyMemory(Object srcBase, long srcOffset,                                  Object destBase, long destOffset,                                  long bytes);

array copy to direct memory

在使用copyMemory操作时,需要传入对象及对象的base offset,对于数组来说,offset就是上面介绍的offset,比如现在将一个数组中的数据拷贝至DirectBuffer

byte[] byte = new byte[4096];unsafe.copyMemory(byte,ARRAY_BYTE_BASE_OFFSET,null,directAddr,4096);

之所以使用unsafe而不是ByteBuffer的方法来操作DirectBuffer,是因为ByteBuffer不够灵活。

比如我想把一个byte[]拷贝至DirectBuffer的某个位置中,就没有相应的方法;只能先设置position,然后再put(byte[], int, int),非常麻烦,而且并发访问时position(long)和put也是个非原子性操作

但是用unsafe来操作的话就很轻松了,直接copyMemory,直接指定address + offset就行

unsafe.copyMemory(byte,ARRAY_BYTE_BASE_OFFSET,null,directAddr,4096);

copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes)

  • srcBase 原数据对象,可以是对象、数组(对象),也可以是Null(为Null时必须指定offset,offset就是address)

  • srcOffset 原数据对象的base offset,如果srcBase为空则此项为address

  • destBase 目标数据对象,规则同src

  • destOffset 目标数据对象的base offset,规则同src

  • bytes 要拷贝的数据大小(字节单位)

通过copyMemory方法,可以做各种拷贝操作:

对象(一般是数组)拷贝到指定堆外内存地址

long l = unsafe.allocateMemory(1);data2[0] = 5;//目标是memory address,destBase为null,destOffset为addressunsafe.copyMemory(data2,16,null,l,1);

将对象拷贝到对象

byte[] data1 = new byte[1];data1[0] = 9;byte[] data2 = new byte[1];unsafe.copyMemory(data1,16,data2,16,1);

将堆外内存地址的数据拷贝到堆内(一般是数组)

byte[] data2 = new byte[1];long l = unsafe.allocateMemory(1);unsafe.putByte(l, (byte) 2);//源数据是memory address,srcBase为null,srcOffset为addressunsafe.copyMemory(null,l,data2,16,1);

堆外内存地址互相拷贝

long l = unsafe.allocateMemory(1);long l2 = unsafe.allocateMemory(1);unsafe.putByte(l, (byte) 2);//源数据是memory address,srcBase为null,srcOffset为address//目标是memory address,destBase为null,destOffset为addressunsafe.copyMemory(null,l,null,l2,1);

Benchmark

sun.misc.Unsafe#putInt(java.lang.Object, long, int) & object field manual set

禁用JIT结果:

BenchmarkModeCntScoreErrorUnits
ObjectFieldSetBenchmark.manualSetthrpt28646455.472 ops/ns
ObjectFieldSetBenchmark.unsafeSetthrpt27901066.170 ops/ns

启用JIT结果:

BenchmarkModeCntScoreErrorUnits
ObjectFieldSetBenchmark.manualSetthrpt2477232013.545 ops/ns
ObjectFieldSetBenchmark.unsafeSetthrpt2499135982.962 ops/ns

结论,几乎没区别

什么时候用Unsafe

一般使用DirectBuffer时,需要配合Unsafe来使用,因为DirectBuffer的内存是分配在JVM Heap之外的,属于C Heap,所以需要用直接操作内存地址(逻辑),和C里malloc之后的操作方式一样

关于sun unsafe类功能及使用注意事项是什么就分享到这里啦,希望上述内容能够让大家有所提升。如果想要学习更多知识,请大家多多留意小编的更新。谢谢大家关注一下编程网网站!

--结束END--

本文标题: sun unsafe类功能及使用注意事项是什么

本文链接: https://www.lsjlt.com/news/321450.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • sun unsafe类功能及使用注意事项是什么
    这篇文章跟大家分析一下“sun unsafe类功能及使用注意事项是什么”。内容详细易懂,对“sun unsafe类功能及使用注意事项是什么”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。...
    99+
    2023-06-28
  • sun unsafe类功能及使用注意事项详解
    目录Unsafe简介获取Unsafe实例Unsafe功能列表Unsafe的数组操作base offset含义index scale含义array copy to direct mem...
    99+
    2024-04-02
  • 使用golang-unsafe包的注意事项及说明
    目录总结(详细的内容可以往下看)详细内容总结基于golang 15.5 总结(详细的内容可以往下看) 1.不能使用unsafe包里的ArbitraryType类型 2.Pointer...
    99+
    2023-02-10
    golang-unsafe包 golang unsafe 使用golang-unsafe包
  • PyGraphviz安装使用及注意事项是什么
    本篇内容主要讲解“PyGraphviz安装使用及注意事项是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PyGraphviz安装使用及注意事项是什么”吧!1. 工具说明PyGraphviz ...
    99+
    2023-07-05
  • localStorage的用法及使用注意事项是什么
    这篇文章主要讲解了“localStorage的用法及使用注意事项是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“localStorage的用法及使用注意事项是什么”吧!localStor...
    99+
    2023-06-29
  • Assert.assertEquals的使用方法及注意事项是什么
    这篇文章主要介绍了Assert.assertEquals的使用方法及注意事项是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Assert.assertEquals的使用方法及注意事项是什么文章都会有所收获,...
    99+
    2023-06-30
  • ajaxSuccess使用注意事项是什么
    本文小编为大家详细介绍“ajaxSuccess使用注意事项是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“ajaxSuccess使用注意事项是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,...
    99+
    2024-04-02
  • 使用.removeProp的注意事项是什么
    本篇内容主要讲解“使用.removeProp的注意事项是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“使用.removeProp的注意事项是什么”吧!  ...
    99+
    2024-04-02
  • 使用.prop的注意事项是什么
    这篇文章主要介绍“使用.prop的注意事项是什么”,在日常操作中,相信很多人在使用.prop的注意事项是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”使用.prop的注意...
    99+
    2024-04-02
  • jQuery Ajax使用心得及注意事项分别是什么
    jQuery Ajax使用心得及注意事项分别是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 IE7及以...
    99+
    2024-04-02
  • React中style的使用方法及注意事项是什么
    这篇“React中style的使用方法及注意事项是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“React中style的...
    99+
    2023-07-05
  • 使用Oracle Nologging+Append注意事项是什么
    本篇内容介绍了“使用Oracle Nologging+Append注意事项是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细...
    99+
    2024-04-02
  • Java多线程Thread类的使用及注意事项
    目录Thread类的基本用法线程指标中断线程1.手动设置标志位2.使用Thread中内置的一个标志位来判定线程等待进程状态线程安全问题synchronized用法1.直接修饰普通的方...
    99+
    2024-04-02
  • Python中深浅拷贝的使用及注意事项是什么
    这篇文章主要讲解了“Python中深浅拷贝的使用及注意事项是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python中深浅拷贝的使用及注意事项是什么”吧!一、Python深浅拷贝概念在...
    99+
    2023-07-05
  • PyGraphviz安装使用及注意事项
    目录1. 工具说明2. linux安装3. windows安装3.1 安装 python3.2 安装 Graphviz3.3 安装 PyGraphviz3.4 PyGraphviz ...
    99+
    2023-02-22
    PyGraphviz 安装使用 PyGraphviz 安装 python PyGraphviz PyGraphviz 使用
  • return语句使用的注意事项是什么
    本篇内容主要讲解“return语句使用的注意事项是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“return语句使用的注意事项是什么”吧!   ...
    99+
    2024-04-02
  • .height()的注意事项是什么
    这篇文章将为大家详细讲解有关.height()的注意事项是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。   .height()   描述: 获取匹配元素集合中的...
    99+
    2024-04-02
  • Js中parseInt的使用及注意事项
    目录start回顾一下map学习一下 parseInt总结:总结start 先看一个题目['1','2','3'].map(parse...
    99+
    2023-01-03
    js parseInt js parseint 精度 js parseint 小数
  • cmd使用javac和java及注意事项
    一、简述: cmd中,执行java命令与javac命令的区别: javac:是编译命令,将java源文件编译成.class字节码文件。 例如:javac hello.java 将...
    99+
    2024-04-02
  • Java项目Guava包 HashMultimap使用及注意事项
    目录1. 数据模型介绍2. 简单使用介绍2.1 容器创建2.2 添加元素2.3 移除元素2.4 替换元素2.5 获取元素及遍历2.6 输出所有的key2.7 输出所有的value3....
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作