实际使用sun.misc.Unsafe有多安全?

时间:2013-12-10 12:20:39

标签: java java-api

我想知道不安全实际上是如何使用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

我的考虑是:

  • 尽管Java被宣传为一次写入,但无处不在我的现实,因为开发人员看起来像是一次写入,在可控制的客户的运行时环境中运行一次
  • sun.misc.Unsafeconsidered to become part of the public API in Java 9
  • 许多非Oracle虚拟机也提供sun.misc.Unsafe,因为 - 我猜 - 有quite some libraries already use it。这也使得该课程不太可能消失
  • 我永远不会在Android上运行该应用程序,所以这对我来说无关紧要。
  • 有多少人实际上正在使用非Oracle VM?

我仍然想知道:还有其他原因我不应该使用sun.misc.Unsafe我没想到的吗?如果你谷歌这个问题,人们宁愿回答一个未指定的,因为它不安全但我真的不觉得除了(非常不可能)该方法有一天会从Oracle VM中消失的可能性。

我实际上需要创建一个对象而不需要调用构造函数来克服Java的类型系统。我不是在考虑performance reasons的{{1}}。

其他信息:为方便起见,我在示例中使用ReflectionFactory,最终委托给Unsafe。我知道像objenesis这样的库,但是查看我发现的代码,他们基本上做了类似的事情,但是在使用Java版本时检查其他方法,这对我来说无论如何也是如此,所以我想写四行是值得保存的依赖性。

2 个答案:

答案 0 :(得分:7)

有三个重要(IMO)问题:

  • Unsafe类中的方法能够违反运行时类型的安全性,并执行其他可能导致JVM崩溃的事情。

    < / LI>
  • 实际上,使用Unsafe做的任何事情在理论上都可能依赖于JVM的内部细节;即JVM如何处理和表示事物的细节。这些可能与平台有关,可能会从一个版本的Java更改为下一个版本。

  • 您正在使用的方法......甚至是类名本身......在不同版本,平台和供应商之间可能不一样。

国际海事组织,这些有充分理由不这样做......但这是一个意见问题。

现在,如果Unsafe成为标准化/标准Java API的一部分(例如在Java 9中),那么上述一些问题就没有实际意义了。但我认为,如果你犯了错误,硬崩溃的风险将永远存在。

答案 1 :(得分:4)

在一次JavaOne 2013会议期间,Mark Reinhold(JDK架构师)提出了一个问题:“使用Unsafe类有多安全?”。他的回答有点令人惊讶:“我相信它应该成为一个稳定的API。当然可以保护安全检查......”

所以看起来像JDK9可能有类似java.util.Unsafe的东西。同时使用现有的类是相对安全的(如做不安全的事情一样安全)。