unsafe java_Java如何以及为什么使用Unsafe?

unsafe java

总览

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

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

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

但是您为什么还要尝试,您可能会感到奇怪? 当在Unsafe中构建库时,很多(但不是全部)方法很有用,并且在某些情况下,如果不使用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

unsafe java

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

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

相关文章

python决策树算法_决策树算法及python实现

决策树算法是机器学习中的经典算法 1.决策树(decision tree) 决策树是一种树形结构&#xff0c;其中每个内部节点表示一个属性上的测试&#xff0c;每个分支代表一个测试输出&#xff0c;每个叶节点代表一种类别。 假设小明去看电影&#xff0c;影响看电影的外部因素有 时间 电…

mysql 远程服务器返回错误404_远程服务器返回异常: (404) 未找到

代码如下&#xff0c;res 赋不了值&#xff0c;为什么&#xff1f;private HttpWebResponse GetData(string url, string agent null, string prod_id null, string oauth_consumerKey "C16207CBF5444A5BB2499189D1E526D5", string oauth_consumerSecret "8…

长见识:你真的知道C语言里extern quot;Cquot; 的作用吗?

经常在C语言的头文件中看到下面的代码&#xff1a;#ifdef __cplusplus extern "C" { #endif// all of your legacy C code here#ifdef __cplusplus } #endif这通常用于C 和C混合编程的时候&#xff0c;为了防止C 的编译器在编译C文件的时候出现错误&#xff1b;众所周…

python自动批量发邮件脚本_Python实现自动发送邮件功能

简单邮件传输协议(SMTP)是一种协议&#xff0c;用于在邮件服务器之间发送电子邮件和路由电子邮件。Python提供smtplib模块&#xff0c;该模块定义了一个SMTP客户端会话对象&#xff0c;可用于使用SMTP或ESMTP侦听器守护程序向任何互联网机器发送邮件。 SMTP通讯的基本流程可以概…

aem 渲染_AEM中的单元测试(大声思考)

aem 渲染如果要在AEM中进行单元测试&#xff0c;这不是任何建议&#xff0c;而是各种思想的总结和一些可供选择的选项。 一段时间之前&#xff0c;我已经为客户进行了一些研究&#xff0c;这篇文章在很大程度上受到了这项工作的影响&#xff0c;但是很多上下文相关的东西已经被…

C语言中#if,#if defined ,#ifdef,extern的用法描述

1、#if 和#ifdef当asd_eee表达式存在而且&#xff0c;值为ture的时候接续向下执行例如#define TARGET_LITTLE_ENDINA 1 #define TARGET_BIG_ENDINA 0 #ifdef TARGET_LITTLE_ENDINA call little endina function #else call big endina function #endif上面的今天写的代码&…

java 排序性能_Java8排序–性能陷阱

java 排序性能Java 8带来了lambda的所有优点&#xff0c;使我们能够使用声明式样式进行编程。 但这真的免费吗&#xff1f; 我们是否应该担心必须为新的编程功能付出的代价&#xff1f; 这是一个我们可能要担心的例子。 考虑对这个简单类的实例进行排序&#xff1a; private…

delphi报列表索引越界怎么处理_图解Elasticsearch索引机制,此篇带你领悟新世界...

前言随着Elastic的上市&#xff0c;ELK不仅在互联网大公司得到长足的发展&#xff0c;而且在各个中小公司都得到非常广泛的应用&#xff0c;甚至连"婚庆网站"都开始使用Elasticsearch了。随之而来的是 Elasticsearch 相关部署、框架、性能优化的文章早已铺天盖地。因…

为什么C语言函数不能返回数组,却可以返回结构体

C语言函数为什么不能返回数组&#xff1f;在C语言程序开发中&#xff0c;我们不可以编写下面这样的代码&#xff1a;char f(void[8]{ char ret;// ...fill... return ret; }int main(int argc, char ** argv) {char obj_a[10];obj_a f(); }不可以编写这样的代码这其实就是不能…

oracle迁移mysql_从自建Oracle迁移至RDS MySQL

#本示例以名称为dtstest的数据库账号为例介绍授权命令&#xff0c;需要对PDB和CDB同时授权#PDB授权示例&#xff1a;create user dtstest IDENTIFIED BY rdsdt_dtsacct;grant create session to dtstest;grant connect to dtstest;grant resource to dtstest;grant select on a…

2015年传智播客java_2015年Java 8强势开始

2015年传智播客javaJDK 8从2015年开始&#xff0c;其博客文章和文章的受欢迎程度将激增。 这与本月将 Java 自动升级到JDK 8恰好吻合。 在这篇文章中&#xff0c;我列出并简要描述了2015年已经发布的许多有关JDK 8的文章和帖子。 JDK 8 Streams在最近的帖子中理所当然地受欢迎…

python文件运行哪一个_如何使一个python文件运行另一个?

本问题已经有最佳答案&#xff0c;请猛点这里访问。 如何创建一个python文件来运行另一个&#xff1f; 例如&#xff0c;我有两个.py文件。我想运行一个文件&#xff0c;然后让它运行另一个.py文件。 docs.python.org / / modules.html教程 所以我execfile()模块通常是更好的。…

C语言printf()函数具体解释和安全隐患

程序员都知道&#xff0c;也都会使用printf函数&#xff0c;但你知道它也有“安全隐患”吗&#xff1f;下面就来举例我说说&#xff1a;嵌入式专栏1问题描述打印输出的数据并不是理论值&#xff0c;如下图&#xff08;右边&#xff09;&#xff1a;嵌入式专栏2进一步描述问题请…

brew search mysql_brew mysql

1、homebrew安装/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"2、命令使用安装软件&#xff1a;brew install 软件名&#xff0c;例&#xff1a;brew install wget搜索软件&#xff1a;brew search 软件名&a…

spring 请求转码_Spring请求级备忘录

spring 请求转码介绍 备注化是一种方法级别的缓存技术&#xff0c;用于加快连续调用的速度。 这篇文章将演示如何仅使用Spring AOP实现任何数据源的请求级可重复读取。 Spring缓存 Spring提供了非常有用的缓存抽象 &#xff0c;允许您将应用程序逻辑与缓存实现细节分离。 Sp…

java map 如何根据key获得对象_ThreadLocal:Java中的影分身

关于ThreadLocal&#xff0c;你有哪些疑问&#xff1f;ThreadLocal是用来解决什么问题的&#xff1f;如何使用ThreadLocal&#xff1f;ThreadLocal的实现原理是什么&#xff1f;可否举几个实际项目中使用ThreadLocal的案例&#xff1f;基础知识ThreadLocal是线程局部变量&#…

【C语言】你可能对 sizeof() 有点误解。。。

各位&#xff0c;今天还是按照惯例给大家分享一个C语言容易出现的小错误&#xff0c;这也是跟sizeof有关的&#xff0c;问题虽小&#xff0c;却可管中窥豹&#xff0c;话不多说&#xff0c;代码先行&#xff1a;#include int main() { int i; i 8; printf("%d\…

mysql cluster 设置单向复制_mysql单向主从配置

1.环境要求操作系统&#xff1a;centOS6.5或以上Mysql版本&#xff1a;mysql5.5主机配置&#xff1a;4核CPU、4G内存2.主从复制的方式mysql5.6开始主从复制有两种方式&#xff1a;基于日志(binlog)、基于GTID(全局十事务标示符)&#xff0c;下面主要介绍基于日志(binlog)的复制…

java处理注释_如何处理Java注释

java处理注释Java 8的一项很酷的新功能是对lambda表达式的支持。 Lambda表达式在很大程度上依赖于FunctionalInterface 注释 。 在本文中&#xff0c;我们将介绍注释以及如何处理它们&#xff0c;以便您可以实现自己的出色功能。 注解 Java 5中添加了注释 。Java语言附带了一…

nginx tcp转发_Nginx学习(九):负载均衡服务

介绍对于请求而言&#xff0c;负载均衡能很好的均摊请求&#xff0c;提高服务端吞吐率和整体性能&#xff0c;多个服务节点部署的方式&#xff0c;也提高了容灾和服务高可用。一、负载均衡分类负载均衡分为&#xff1a;GSLB和SLB。1. GDLB全局负载均衡&#xff0c;往往按照国家…