java有unsafe类吗_Java的Unsafe类:“当然也有没有它的方法!”

java有unsafe类吗

JAXenter:社交媒体上正在讨论Java 9可能在没有sun.misc.Unsafe的情况下发布 首先: sun.misc.Unsafe背后是什么?

Uwe Schindler: Unsafe是Oracle JDK / OpenJDK平台的私有内部类。 许多公共Java API在后台使用它来实现操作,否则这些操作仅在本机C或汇编代码中可用。 它主要用于以下任务:

  • 原子比较和交换操作:Java字节码没有可本地执行的指令,因此来自java.util.concurrent包的实现(例如AtomicInteger,LongAdder或ConcurrentHashMap)在后台使用了Unsafe。
  • 易失性数组访问:对此也没有相应的Java字节码–您只能将整个数组声明为易失性,而不能声明其元素。
  • 直接访问堆外内存:Unsafe提供了malloc()之类的东西-从C编程语言中可以得知。 另外,它提供了通过其绝对地址访问分配的内存(在主Java堆之外)的方法。 这类似于C中的指针。此功能主要由Java NIO API中的直接缓冲区使用,并提供对内存映射文件的访问。
  • 有关对象实例内部结构的一些有用的常量。 这些常量通常是调用上述方法之一所必需的,但是它们对于在运行时估计Java堆上需要多少内存对象实例也很有用。

为什么应删除sun.misc.Unsafe

Unsafe的问题很容易解释:此类中的方法可用于通过直接指针访问Java堆内部和外部的内存。 因为没有检查,所以它们可以用于使JVM(SIGSEGV)崩溃或将平台的汇编代码注入JVM! 这通常是“不安全的”(正如该类别的名称所暗示的)。 Java代码应使用JDK提供的“官方” API:AtomicInteger,ConcurrentHashMap,ByteBuffer等。

还请参见: sun.misc.Unsafe苦难告诉我们什么

正式地,JDK限制了对sun.misc.Unsafe的访问,因为静态工厂方法getUnsafe()对调用者敏感:只能从JRE的类内部(由系统类加载器提供)调用,而不能从应用程序代码中调用。 但是,聪明的开发人员找到了一种通过Java反射来获取Unsafe实例的方法(如果Java SecurityManager不能阻止这种情况,则读取Unsafe的私有字段来保存单例实例)。

这就是Java 9对其施加限制的地方:由于新的模块概念, sun.misc.Unsafe从“ java.base”中删除,并被推送到内部模块中。 应用程序代码无法从这些内部模块访问类,甚至无法实例化它们。 实际上, sun.misc.Unsafe不再存在于JDK之外,并且被其新的模块化概念完全隔离。 因此,Class.forName()将引发ClassNotFoundException。 这确实阻止了应用程序代码的任何访问!

删除sun.misc.Unsafe对Apache Lucene和Solr意味着什么?

这不会对Apache Lucene产生影响,因为在我们的代码准则中我们禁止使用sun.misc.Unsafe 。 我们是一个库,许多项目都在使用该库,并且我们不能损害用户程序的安全性。 此外,依靠未公开的 API(例如sun.misc.Unsafe)使我们的代码对平台内部API的更改敏感。 如果看一下Apache Lucene的源代码,过去使用过Unsafe的许多程序员可能会明白,如果没有它,当然还有一种方法!

Apache Solr最终可能会遇到问题,因为有许多第三方库,我们不知道它们是否使用Unsafe。 其中之一最近被更换了。

批评者担心,许多主流应用程序在删除sun.misc.Unsafe之后将停止工作。 是吗

实际上,这是正确的说法! 有许多库,例如Netty,它们在内部使用Unsafe(使用前面所述的反射黑客)。 在很多情况下,甚至都没有记录! 一些项目还使用特殊的库来代替Java更高版本(javax软件包)中出现的功能。 一个示例是LongAdder,它只是Java 8的java.util.concurrent类的一部分。 这些项目应更新为需要Java 8,并删除过时的外部库。

您对重新实现sun.misc.Unsafe部分并将其作为公共API添加到Java规范的建议有何看法?

实际上, sun.misc.Unsafe的某些部分并不是真正的“不安全”。 例如,如果所有常量或比较和交换原语由公共API正确封装,则可以非常安全地使用它们。 但是,实际上应该避免直接访问绝对内存地址(例如“ C代码”),因为这将完全破坏Java平台的整体安全性。 正如您在Apache Lucene的ByteBufferIndexInput的代码中看到的那样,可以使用ByteBuffer.allocateDirect()并以安全的方式使用公共API实现堆外内存访问,但是通过边界检查可以节省少量运行时开销。 但是,Hotspot VM的优化最近消除了许多此类问题! 一个新的安全的API可以替代ByteBuffer(具有最终界限和64位访问权限),从而进一步改善这一点。

因此,这些库的开发人员应考虑这一点,并可能为其产品提供不需要安全的新更新。 我认为,这应该可以在Java 9发行之前进行管理。但是在开发过程中肯定会存在一个小的“空白”,这可能会出现问题。 因此,负责Java 9的OpenJDK开发人员提出了一种“命令行开关”作为一种变通办法,这使得sun.misc.Unsafe对于旧代码再次可见。

翻译自: https://jaxenter.com/javas-unsafe-class-there-is-certainly-also-a-way-without-it-119084.html

java有unsafe类吗

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值