前几天我偶然发现了一个不安全的包装,它的功能让我感到惊讶。

当然,这个类是没有记录的,但是我想知道是否有一个很好的理由使用它。可能会出现哪些需要使用它的场景?如何在现实场景中使用它?

此外,如果您确实需要它,这难道不表明您的设计可能存在问题吗?

为什么Java包含这个类?


当前回答

基于对使用eclipse进行引用跟踪的Java 1.6.12库的简要分析,似乎Unsafe的每个有用功能都以有用的方式公开了。

CAS操作通过Atomic*类公开。 内存操作函数通过DirectByteBuffer公开 同步指令(park,unpark)通过AbstractQueuedSynchronizer公开,而AbstractQueuedSynchronizer又由Lock实现使用。

其他回答

有趣的是,我甚至从未听说过这个类(这可能是一件好事,真的)。

我想到的一件事是使用Unsafe#setMemory将包含敏感信息的缓冲区归零(密码、密钥等)。您甚至可以对“不可变”对象的字段执行此操作(然后,我再次假设普通的反射也可以在这里执行此操作)。但我不是安全专家,所以对此持保留态度。

它使用的一个例子是random方法,该方法调用不安全的方法来更改种子。

这个网站也有它的一些用途。

通过在一些代码搜索引擎中运行搜索,我得到了以下示例:

Java对象符号——使用它来进行更有效的数组处理,引用javadoc

类来获取对{@link Unsafe}对象的访问。{@link安全} 为了允许对数组进行有效的CAS操作,*是必需的。注意 {@link java.util.concurrent中的版本。原子},例如{@link java.util.concurrent.atomic。AtomicLongArray},需要额外的内存排序 这些保证在这些算法中通常是不需要的 在大多数处理器上都很昂贵。

SoyLatte - java 6 for osx javadoc excerpt

/** sun.misc的基类基于静态的不安全的FieldAccessors 字段。据观察,只有9种类型的 从反射代码的角度看字段:八个原语 类型和对象。使用不安全类而不是生成类 字节码节省内存和加载时间 动态生成的FieldAccessors。* /

SpikeSource

/* 通过线路发送的FinalFields ..如何解编和重新创建对象上 接收方?我们不想调用构造函数,因为它将为 最后一个字段。我们必须重新创建与发送端完全相同的最终字段。 太阳,杂项,不安全为我们做了这些。 * /

还有很多其他的例子,只要按上面的链接…

我们使用Unsafe实现了数组、HashMaps、TreeMaps等大型集合。为了避免/最小化碎片,我们使用dlmalloc over unsafe的概念实现内存分配器。这帮助我们获得了并发性方面的性能。

I was recently working on reimplementing the JVM and found that a surprising number of classes are implemented in terms of Unsafe. The class is mostly designed for the Java library implementers and contains features that are fundamentally unsafe but necessary for building fast primitives. For example, there are methods for getting and writing raw field offsets, using hardware-level synchronization, allocating and freeing memory, etc. It is not intended to be used by normal Java programmers; it's undocumented, implementation-specific, and inherently unsafe (hence the name!). Moreover, I think that the SecurityManager will disallow access to it in almost all cases.

简而言之,它的存在主要是为了允许库实现者访问底层机器,而不必在某些类(如AtomicInteger native)中声明每个方法。在常规Java编程中不需要使用或担心它,因为重点是使其余的库足够快,从而不需要这种访问。