我想知道不安全实际上是如何使用sun.misc.Unsafe
。我想创建一个对象的代理,我在其中拦截每个方法调用(但为了性能考虑而将Object.finalize
调用到class MyClass {
private final String value;
MyClass() {
this.value = "called";
}
public void print() {
System.out.println(value);
}
}
@org.junit.Test
public void testConstructorTrespassing() throws Exception {
@SuppressWarnings("unchecked")
Constructor<MyClass> constructor = ReflectionFactory.getReflectionFactory()
.newConstructorForSerialization(MyClass.class, Object.class.getConstructor());
constructor.setAccessible(true);
assertNull(constructor.newInstance().print());
}
。为此,我用谷歌搜索了一下,并提出了以下代码片段:
sun.misc.Unsafe
我的考虑是:
sun.misc.Unsafe
是considered to become part of the public API in Java 9 sun.misc.Unsafe
,因为 - 我猜 - 有quite some libraries already use it。这也使得该课程不太可能消失我仍然想知道:还有其他原因我不应该使用sun.misc.Unsafe
我没想到的吗?如果你谷歌这个问题,人们宁愿回答一个未指定的,因为它不安全但我真的不觉得除了(非常不可能)该方法有一天会从Oracle VM中消失的可能性。
我实际上需要创建一个对象而不需要调用构造函数来克服Java的类型系统。我不是在考虑performance reasons的{{1}}。
其他信息:为方便起见,我在示例中使用ReflectionFactory
,最终委托给Unsafe
。我知道像objenesis这样的库,但是查看我发现的代码,他们基本上做了类似的事情,但是在使用Java版本时检查其他方法,这对我来说无论如何也是如此,所以我想写四行是值得保存的依赖性。
答案 0 :(得分:7)
有三个重要(IMO)问题:
Unsafe
类中的方法能够违反运行时类型的安全性,并执行其他可能导致JVM崩溃的事情。
实际上,使用Unsafe做的任何事情在理论上都可能依赖于JVM的内部细节;即JVM如何处理和表示事物的细节。这些可能与平台有关,可能会从一个版本的Java更改为下一个版本。
您正在使用的方法......甚至是类名本身......在不同版本,平台和供应商之间可能不一样。
国际海事组织,这些有充分理由不这样做......但这是一个意见问题。
现在,如果Unsafe
成为标准化/标准Java API的一部分(例如在Java 9中),那么上述一些问题就没有实际意义了。但我认为,如果你犯了错误,硬崩溃的风险将永远存在。
答案 1 :(得分:4)
在一次JavaOne 2013会议期间,Mark Reinhold(JDK架构师)提出了一个问题:“使用Unsafe类有多安全?”。他的回答有点令人惊讶:“我相信它应该成为一个稳定的API。当然可以保护安全检查......”
所以看起来像JDK9可能有类似java.util.Unsafe的东西。同时使用现有的类是相对安全的(如做不安全的事情一样安全)。