前几天我偶然发现了一个不安全的包装,它的功能让我感到惊讶。
当然,这个类是没有记录的,但是我想知道是否有一个很好的理由使用它。可能会出现哪些需要使用它的场景?如何在现实场景中使用它?
此外,如果您确实需要它,这难道不表明您的设计可能存在问题吗?
为什么Java包含这个类?
前几天我偶然发现了一个不安全的包装,它的功能让我感到惊讶。
当然,这个类是没有记录的,但是我想知道是否有一个很好的理由使用它。可能会出现哪些需要使用它的场景?如何在现实场景中使用它?
此外,如果您确实需要它,这难道不表明您的设计可能存在问题吗?
为什么Java包含这个类?
当前回答
有趣的是,我甚至从未听说过这个类(这可能是一件好事,真的)。
我想到的一件事是使用Unsafe#setMemory将包含敏感信息的缓冲区归零(密码、密钥等)。您甚至可以对“不可变”对象的字段执行此操作(然后,我再次假设普通的反射也可以在这里执行此操作)。但我不是安全专家,所以对此持保留态度。
其他回答
通过在一些代码搜索引擎中运行搜索,我得到了以下示例:
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 ..如何解编和重新创建对象上 接收方?我们不想调用构造函数,因为它将为 最后一个字段。我们必须重新创建与发送端完全相同的最终字段。 太阳,杂项,不安全为我们做了这些。 * /
还有很多其他的例子,只要按上面的链接…
不安全的。允许抛出检查异常而不声明它们。
这在处理反射或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();
}
}
not safe.park()和not safe.unpark()用于构建自定义并发控制结构和协作调度机制。
为了有效地复制内存(至少对于短块,复制速度比System.arraycopy()快);由Java LZF和Snappy编解码器使用。它们使用'getLong'和'putLong',这比逐字节复制要快;在复制16/32/64字节块时尤其有效。
使用它来有效地访问和分配大量的内存,例如在您自己的体素引擎中!(例如《我的世界》风格的游戏。)
In my experience, the JVM is often unable to eliminate bounds-checking in place you truly need it. For example, if you're iterating over a large array, but the actual memory access is tucked underneath a non-virtual* method call in the loop, the JVM may still perform a bounds check with each array access, rather than once just before the loop. Thus, for potentially large performance gains, you can eliminate JVM bounds-checking inside the loop via a method which employs sun.misc.Unsafe to access the memory directly, making sure to do any bounds-checking yourself at the correct places. (You are gonna bounds check at some level, right?) *by non-virtual, I mean the JVM shouldn't have to dynamically resolve whatever your particular method is, because you've correctly guaranteed that class/method/instance are some combination of static/final/what-have-you.
对于我自己开发的体素引擎来说,这在块生成和序列化期间(在我同时读取/写入整个数组的低位置)带来了显著的性能提升。结果可能会有所不同,但如果缺乏界限消除是您的问题,那么这将解决它。
There are some potentially major problems with this: specifically, when you provide the ability to access memory without bounds-checking to clients of your interface, they will probably abuse it. (Don't forget that hackers can also be clients of your interface... especially in the case of a voxel engine written in Java.) Thus, you should either design your interface in a way such that memory access cannot be abused, or you should be extremely careful to validate user-data before it can ever, ever mingle with your dangerous interface. Considering the catastrophic things a hacker can do with unchecked memory access, it's probably best to take both approaches.