Java如何以及为什么使用Unsafe?

总览

sun.misc.Unsafe至少在Java 1.4(2004)中就已经存在于Java中。 在Java 9中,不安全将与许多其他供内部使用的类一起隐藏。 以提高JVM的可维护性。 尽管仍不确定究竟将取代Unsafe到底是什么,但我怀疑将取代Unsafe不仅仅是一件事,但它提出了一个问题,为什么要使用它?

执行Java语言不允许的但仍然有用的操作。

Java不允许使用低级语言可用的许多技巧。 对于大多数开发人员而言,这是一件好事,不仅可以使您免于自己,而且还可以使您从同事中免除。 这也使导入开放源代码更加容易,因为您知道它们可以造成的损害是有限的。 或至少可以限制您意外执行的操作。 如果您尽力而为,仍然可能造成伤害。

但是您为什么还要尝试,您可能会感到奇怪? 在不安全的情况下构建库时,很多(但不是全部)方法很有用,并且在某些情况下,如果不使用JNI,则没有其他方法可以做同样的事情,这更加危险,并且您将失去“一次编译,在任何地方运行”的权限。 ”

对象反序列化

使用框架反序列化或构建对象时,您要假设要重新构成以前存在的对象。 您期望您将使用反射来调用类的setter,或者更可能直接设置内部字段,甚至最终字段。 问题是您想创建一个对象的实例,但是您实际上并不需要构造函数,因为这可能只会使事情变得更加困难并产生副作用。

public class A implements Serializable {private final int num;public A(int num) {System.out.println("Hello Mum");this.num = num;}public int getNum() {return num;}
}

在此类中,您应该能够重建和设置final字段,但是如果您必须调用构造函数,并且它可能完成与反序列化无关的事情。 由于这些原因,许多库使用Unsafe来创建实例而不调用构造函数。

Unsafe unsafe = getUnsafe();
Class aClass = A.class;
A a = (A) unsafe.allocateInstance(aClass);

不需要时,调用allocateInstance可以避免调用适当的构造函数。

线程安全访问直接内存

Unsafe的另一个用途是对堆外内存的线程安全访问。 ByteBuffer使您可以安全地访问堆外或直接内存,但是它没有任何线程安全操作。 如果要在进程之间共享数据,这特别有用。

import sun.misc.Unsafe;
import sun.nio.ch.DirectBuffer;import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;public class PingPongMapMain {public static void main(String... args) throws IOException {boolean odd;switch (args.length < 1 ? "usage" : args[0].toLowerCase()) {case "odd":odd = true;break;case "even":odd = false;break;default:System.err.println("Usage: java PingPongMain [odd|even]");return;        }int runs = 10000000;long start = 0;System.out.println("Waiting for the other odd/even");File counters = new File(System.getProperty("java.io.tmpdir"), "counters.deleteme");        counters.deleteOnExit();try (FileChannel fc = new RandomAccessFile(counters, "rw").getChannel()) {MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);long address = ((DirectBuffer) mbb).address();for (int i = -1; i < runs; i++) {for (; ; ) {long value = UNSAFE.getLongVolatile(null, address);boolean isOdd = (value & 1) != 0;if (isOdd != odd)// wait for the other side.continue;// make the change atomic, just in case there is more than one odd/even processif (UNSAFE.compareAndSwapLong(null, address, value, value + 1))break;}if (i == 0) {System.out.println("Started");start = System.nanoTime();}}}System.out.printf("... Finished, average ping/pong took %,d ns%n",(System.nanoTime() - start) / runs);}static final Unsafe UNSAFE;static {try {Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);UNSAFE = (Unsafe) theUnsafe.get(null);} catch (Exception e) {throw new AssertionError(e);}}
}

当您在两个程序中运行此程序时,一个程序带有奇数 ,另一个程序带有偶数 。 您可以看到每个进程都通过持久共享内存来更改数据。

在每个程序中,它会将相同的磁盘高速缓存映射到进程中。 内存中实际上只有一个副本。 这意味着可以共享内存,前提是您使用线程安全操作,例如volatile和CAS操作。

i7-3970X的输出为

等待另一个奇/偶
已开始
…完成后,平均ping / pong花费了83 ns

这是两个进程之间的83 ns往返时间。 当您考虑使用System V IPC大约需要2500 ns,并且IPC易变而不是持续存在时,这很快。

使用不安全适合工作吗?

我不建议您直接使用不安全。 它比自然的Java开发需要更多的测试。 因此,我建议您使用已经过使用测试的库。 如果您想自己使用Unsafe,建议您在独立的库中测试它的用法。 这限制了在应用程序中使用“不安全”的方式,并为您提供了一个更安全,不安全的方式。

结论

有趣的是Java中存在Unsafe,您可能想在家中玩它。 它有一些工作应用程序,尤其是在编写低级库时,但是总的来说,最好使用经过测试的Unsafe库,而不是直接使用它。

翻译自: https://www.javacodegeeks.com/2014/12/how-and-why-is-unsafe-used-in-java.html

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

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

相关文章

Angularjs基础(三)

AngularJS ng-model 指令     ng-model 指令用于绑定应用程序数据到HTML 控制器&#xff08;input,select,textarea&#xff09;的值ng-model指令     ng-model指令可以将输入域的值与AngularJS 创建的变量绑定。       实例&#xff1a;         <di…

ASP.NET MVC的生命周期与网址路由

网址路由&#xff08;Routing&#xff09;在ASP.NET MVC中有两个主要用途&#xff0c;一个用途是匹配通过浏览器传来的HTTP请求&#xff0c;另一个用途则是将适当的网址返回浏览器。 首先我们来看下第一个用途&#xff0c;也就是匹配通过浏览器传来的HTTP请求。 客户端对ASP.NE…

ecshop分页类assign_pager分析和扩展

ecshop分页类assign_pager分析和扩展,我们前面的文章中介绍过ecshop ajax分页&#xff0c;他的基础都是简单单一的分页。如果我们要在ecshop分页里面传入自己的参数&#xff0c;你就必须对ecshop的assign_pager分页函数进行系统的认识和分析。 首先我们看category.php的ecshop分…

NEC css规范

CSS规范 - 分类方法 SS文件的分类和引用顺序 通常&#xff0c;一个项目我们只引用一个CSS&#xff0c;但是对于较大的项目&#xff0c;我们需要把CSS文件进行分类。 我们按照CSS的性质和用途&#xff0c;将CSS文件分成“公共型样式”、“特殊型样式”、“皮肤型样式”&#…

JDK 8中的流驱动的集合功能

这篇文章介绍了JDK 8的应用–引入了带有集合的 流 &#xff0c;以更简洁地完成通常需要的与集合相关的功能。 在此过程中&#xff0c;将演示并简要说明使用Java Streams的几个关键方面。 请注意&#xff0c;尽管JDK 8 Streams通过并行化支持提供了潜在的性能优势&#xff0c;但…

知识汇集

Oracle中锁介绍&#xff1a;http://space.itpub.net/26961876/viewspace-731300转载于:https://www.cnblogs.com/yaohonv/archive/2012/08/18/tech-col.html

jquery mobile 移动web(5)

有序列表   <div data-role"content">     <ol data-role"listview" data-theme"g">       <li><a href"#"> List 1</a></li>       <li><a href"#"> L…

cjmx:JConsole的命令行版本

当监视正在运行的Java应用程序时&#xff0c;JConsole是一个很好的工具。 但是&#xff0c;当无法使用JConsole直接连接到JVM&#xff08;例如&#xff0c;由于网络限制&#xff09;并且无法进行SSH隧道传输时&#xff0c;那么拥有命令行版本的JConsole会很棒。 jcmx是JConsol…

Android中SQLiteDatabase操作【附源码】

像我们做的很多应用程序及网站一样&#xff0c;基本都是对数据库进行增删改查来实现相应的功能。那么Android开发也一样&#xff0c;不过由于在移动客户端应用&#xff0c;所以不会像sql server、mysql那么复杂&#xff0c;Android应用程序支持本地数据库&#xff0c;SQLiteDat…

移动设备HTML5页面布局

在HTML5标准添加的新元素中&#xff0c;用于常见页面结 构的包括header footer footer nav aside aside article section hgroup 。 下面简单介绍一下这个元素&#xff1a; 1.header header>元素定义文档的页面组合&#xff0c;通 常是一些引导和导航信息&#xff0c;标签…

Hazelcast入门指南第5部分

这是我撰写的有关Hazelcast的一系列文章的延续。 我强烈建议您阅读其他内容&#xff1a; 第1 部分 &#xff0c; 第2 部分 &#xff0c; 第3 部分和第4部分 。 让人一见倾心的东西&#xff1f; 这篇文章中将没有Hazelcast专用代码。 让我重复一遍。 这篇文章中将没有Hazelcast…

【BEV感知算法概述——下一代自动驾驶感知算法】

文章目录 BEV感知算法概念BEV感知算法数据集介绍BEV感知算法分类BEV感知算法的优劣小结 BEV感知算法概念 Bird’s-Eye-View&#xff0c;鸟瞰图&#xff08;俯视图&#xff09;。BEV感知算法存在许多的优势。 首先&#xff0c;BEV视图存在遮挡小的优点&#xff0c;由于视觉的透…

jquery鼠标事件

click()   为点击事件绑定一个事件处理函数&#xff0c;或者触发元素点击事件。   .click( handler(eventObject) )     handler(eventObject)       每次事件触发时候执行的函数。   .click([eventData],handler(eventObject))     eventData      …

[LaunchPad] 超声波测试,数码管显示

1 #include "io430g2553.h"2 3 unsigned char Disp_Tab[] {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //段码控制 4 unsigned char dispbit[8]{0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F}; //位选控制 5 6 unsigned char LedOut[4];7 8 …

Spring的依赖注入陷阱

Spring框架中有三种注入变量&#xff1a; 基于二传手的注射 基于构造函数的注入 基于现场的注入 这些机制中的每一种都有优点和缺点&#xff0c;并且不仅只有一种正确的方法。 例如现场注入&#xff1a; Autowired private FooBean fooBean;在生产代码中使用它通常不是最好…

jquery 操作css 选择器

.addClass()   为每个匹配的元素添加指定的样式类名   .addClass(className)     className 为每个匹配元素所有增加的一个或多个样式名   .addClass(function(index,currentClass))     函数返回一个或者多个用空格隔开&#xff0c; index 表示参数匹配中的索引…

vim设置

一、基本编辑功能1、复制、剪切和粘贴复制特定的某一段&#xff1a;把光标移到要复制的文本的头部&#xff0c;按下“v”&#xff0c;往后移动光标&#xff0c;光标所过之处的字符>都会高亮&#xff0c;移到欲复制文本的尾部后&#xff0c;按下“y”&#xff0c;高亮文本全部…

jquery表单属性筛选元素

$(":button") 选择所有按钮元素类型为按钮的元素。 等于$(input[type"button"]) $(":checkbox") 选择所有类型为复选框的元素。 等于$(input[type"checkbox"]) $(":checked") 选择所有勾选的元素。 $( "input:checked&…

Hamcrest Matchers的高级创建

介绍 上一次 &#xff0c;我讨论了Hamcrest Matcher是什么&#xff0c;如何使用以及如何制作。 在本文中&#xff0c;我将解释创建Hamcrest Matchers的更多高级步骤。 首先&#xff0c;我将分享如何使您的匹配器更易于类型安全&#xff0c;然后介绍无状态匹配器的一些技术&…

嵌入式成长轨迹37 【Zigbee项目】【CC2430基础实验】【自动闪烁】

最为简单的代码&#xff0c;只用到一个寄存器P1DIR。因为点亮的led灯&#xff08;p1.0和p1.1&#xff09;的管脚是p1的&#xff0c;要输出就得将这两个管脚设置为输出管脚。该寄存器用0~8对应1.0~1.8管脚。 1 //main.c2 #include <ioCC2430.h>3 4 #define uint unsigned …