前几天我遇到了sun.misc.Unsafe包裹,并对它能做什么感到惊讶.
当然,这门课没有证件,但我想知道是否有充分的理由使用它.您可能需要使用哪些场景?它如何在现实场景中使用?
此外,如果您确实需要它,那是否表明您的设计可能出现问题?
为什么Java甚至包括这个类?
zud*_*kod 159
例子
VM"内在化".即无锁散列表中使用的CAS(比较和交换)例如:sun.misc.Unsafe.compareAndSwapInt它可以将真正的JNI调用转换为包含CAS特殊指令的本机代码
在这里阅读更多关于CAS的信息http://en.wikipedia.org/wiki/Compare-and-swap
主机VM的sun.misc.Unsafe功能性可以被用于分配未初始化的对象,然后解释该构造函数调用的任何其他方法调用.
人们可以追踪本地address.It可以使用java.lang.Unsafe类检索对象的内存地址中的数据,并在其领域直接通过不安全的get/put方法操作!
编译JVM的时间优化.高性能VM使用"魔术",需要低级操作.例如:http://en.wikipedia.org/wiki/Jikes_RVM
分配内存,sun.misc.Unsafe.allocateMemory例如: - 当调用ByteBuffer.allocateDirect时,DirectByteBuffer构造函数在内部调用它
跟踪调用堆栈并使用sun.misc.Unsafe实例化的值进行重放,这对于检测非常有用
sun.misc.Unsafe.arrayBaseOffset和arrayIndexScale可用于开发arraylets,这是一种有效地将大型数组拆分为较小对象的技术,以限制在大型对象上扫描,更新或移动操作的实时成本
http://robaustin.wikidot.com/how-to-write-to-direct-memory-locations-in-java
更多关于这里的参考 - http://bytescrolls.blogspot.com/2011/04/interesting-uses-of-sunmiscunsafe.html
Asa*_*saf 31
只是在某些代码搜索引擎中运行搜索,我得到以下示例:
用于访问{@link Unsafe}对象的简单类.{@link Unsafe}*是允许对阵列进行高效CAS操作所必需的.请注意,{@link java.util.concurrent.atomic}中的版本,例如{@link java.util.concurrent.atomic.AtomicLongArray},需要额外的内存排序保证,这些保证通常在这些算法中不需要并且也很昂贵在大多数处理器上
/**用于静态字段的基于sun.misc.Unsafe的FieldAccessors的基类.观察结果是,从反射代码的角度来看,只有九种类型的字段:八种基本类型和对象.使用类Unsafe而不是生成的字节码可以为动态生成的FieldAccessor节省内存和加载时间.*/
/*通过网络发送的FinalFields ..如何在接收端解组并重新创建对象?我们不想调用构造函数,因为它会为最终字段建立值.我们必须重新创建最终字段,就像发送方一样.sun.misc.Unsafe为我们这样做.*/
还有很多其他的例子,只需按照上面的链接...
Mik*_*els 24
有意思,我从来没有听说过这个课程(这可能是一件好事,真的).
跳到脑海的一件事是使用Unsafe#setMemory将包含敏感信息的缓冲区归零(密码,密钥......).你甚至可以对"不可变"对象的字段执行此操作(然后我再次假设普通的旧反射也可以在这里做到这一点).我不是安全专家,所以不管怎么说.
Tim*_*der 22
基于对使用eclipse进行参考跟踪的Java 1.6.12库的非常简短的分析,似乎每个有用的功能Unsafe都以有用的方式公开.
CAS操作通过Atomic*类公开.内存操作函数通过DirectByteBuffer公开同步指令(park,unpark)通过AbstractQueuedSynchronizer公开,而AbstractQueuedSynchronizer又由Lock实现使用.
Ral*_*lph 21
Unsafe.throwException - 允许抛出已检查的异常而不声明它们.
在处理反射或AOP的某些情况下,这很有用.
假设您为用户定义的接口构建通用代理.并且用户可以通过在接口中声明异常来指定特殊情况下的实现抛出哪个异常.然后,这是我所知道的唯一方法,即在接口的动态实现中引发已检查的异常.
import org.junit.Test;
/** need to allow forbidden references! */ import sun.misc.Unsafe;
/**
* Demonstrate how to throw an undeclared checked exception.
* This is a hack, because it uses the forbidden Class {@link sun.misc.Unsafe}.
*/
public class ExceptionTest {
/**
* A checked exception.
*/
public static class MyException extends Exception {
private static final long serialVersionUID = 5960664994726581924L;
}
/**
* Throw the Exception.
*/
@SuppressWarnings("restriction")
public static void throwUndeclared() {
getUnsafe().throwException(new MyException());
}
/**
* Return an instance of {@link sun.misc.Unsafe}.
* @return THE instance
*/
@SuppressWarnings("restriction")
private static Unsafe getUnsafe() {
try {
Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
singleoneInstanceField.setAccessible(true);
return (Unsafe) singleoneInstanceField.get(null);
} catch (IllegalArgumentException e) {
throw createExceptionForObtainingUnsafe(e);
} catch (SecurityException e) {
throw createExceptionForObtainingUnsafe(e);
} catch (NoSuchFieldException e) {
throw createExceptionForObtainingUnsafe(e);
} catch (IllegalAccessException e) {
throw createExceptionForObtainingUnsafe(e);
}
}
private static RuntimeException createExceptionForObtainingUnsafe(final Throwable cause) {
return new RuntimeException("error while obtaining sun.misc.Unsafe", cause);
}
/**
* scenario: test that an CheckedException {@link MyException} can be thrown
* from an method that not declare it.
*/
@Test(expected = MyException.class)
public void testUnsingUnsaveToThrowCheckedException() {
throwUndeclared();
}
}
Run Code Online (Sandbox Code Playgroud)
我最近正在重新实现JVM,发现在方面实现了惊人数量的类Unsafe。该类主要是为Java库实现者设计的,并且包含从本质上讲是不安全的但对于构建快速基元是必需的功能。例如,存在一些获取和写入原始字段偏移量,使用硬件级同步,分配和释放内存等的方法。普通Java程序员不打算使用它。它是无证的,特定于实现的,并且本质上是不安全的(因此得名!)。而且,我认为SecurityManager在几乎所有情况下,该方法都将禁止使用它。
简而言之,主要是允许库实现者访问底层计算机,而不必在某些类(例如AtomicIntegernative)中声明每个方法。您不需要在常规Java编程中使用或担心它,因为重点是使其余库足够快,以至于您不需要这种访问。
使用它可以有效地访问和分配大量内存,例如在您自己的体素引擎中!(即Minecraft风格的游戏.)
根据我的经验,JVM通常无法消除您真正需要的边界检查.例如,如果您正在迭代一个大型数组,但实际的内存访问隐藏在循环中的非虚拟*方法调用下,则JVM仍然可以对每个数组访问执行边界检查,而不是之前的一次循环.因此,为了获得潜在的大性能提升,您可以通过使用sun.misc.Unsafe直接访问内存的方法来消除循环内部的JVM边界检查,确保在正确的位置自行进行任何边界检查.(你是要去边界检查在一定程度上,对吧?)
*由非虚,我指的是JVM不应该动态地解决无论你的具体方法是,因为你已经正确地保证类/方法/实例是一些静态/最终/有什么你的组合.
对于我自己开发的体素引擎,这在块生成和序列化过程中产生了显着的性能提升(我在一起读取/写入整个阵列的地方).结果可能会有所不同,但如果缺少边界消除是你的问题,那么这将解决它.
这有一些潜在的主要问题:具体来说,当您提供访问内存的能力而无需对接口的客户端进行边界检查时,他们可能会滥用它.(不要忘记,黑客也可以是你的界面的客户端...特别是在用Java编写的体素引擎的情况下.)因此,你应该设计你的界面,使得内存访问不会被滥用,或者你应该非常小心,以验证用户数据,则可以不断,之前曾经与你的危险接口打成一片.考虑到黑客可以通过未经检查的内存访问进行的灾难性事情,最好采用这两种方法.
我自己没有使用过它,但我想如果你有一个变量只是偶尔被多个线程读取(所以你真的不想让它变得易失)你可以putObjectVolatile在主线程中写入它时使用readObjectVolatile当从其他线程进行罕见的读取时。
| 归档时间: |
|
| 查看次数: |
56598 次 |
| 最近记录: |