使用sun.misc.Unsafe有多危险?

16
我想知道使用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());
}

我的看法是:

  • 尽管Java被宣传为“一次编写,到处运行”,但是我作为开发人员的实际情况更像是“一次编写,在可控的客户端运行时环境中运行一次”
  • sun.misc.Unsafe 被认为将成为Java 9公共API的一部分
  • 许多非Oracle虚拟机也提供sun.misc.Unsafe我猜这是因为有很多库已经在使用它。这也使这个类不太可能消失。
  • 我永远不会在Android上运行该应用程序,所以这对我没有关系。
  • 实际上有多少人使用非Oracle虚拟机呢?
我仍在思考:是否有其他原因,我不应该使用sun.misc.Unsafe?如果你在谷歌上搜索这个问题,人们会回答一个不明确的因为它不安全,但我并不真的觉得除了这个方法(非常不可能)有一天会从Oracle VM中消失之外还有别的原因。
我实际上需要创建一个对象而不调用构造函数来克服Java的类型系统。出于性能原因,我不考虑使用sun.misc.Unsafe

附加信息: 我在示例中使用 ReflectionFactory 仅为方便起见,它最终委托给 Unsafe。我知道像 objenesis 这样的库,但看了代码后我发现它们基本上做了类似的事情,但在使用 Java 版本时会检查其他方法,这对我来说也不起作用,所以我想编写四行代码值得节省一个依赖项。


注意:如果它在Java 9中成为公共API,那么它绝对不会在com.sun包中。 - Jesper
请记住,在您没有足够权限的系统上,您将无法使用Unsafe。 - Hot Licks
两者都是正确的。然而,你所需要的所有权限就是通过反射读取私有字段的权利。这对于许多库来说是一个非常普遍的要求。 - Rafael Winterhalter
2个回答

7
有三个重要的问题(在我看来):
- Unsafe类中的方法具有违反运行时类型安全性的能力,还可能导致JVM“硬崩溃”等其他问题。 - 使用Unsafe几乎可以做任何事情,但理论上可能依赖于JVM内部细节,即JVM如何执行操作和表示事物的细节。这些可能与平台相关,并且可能会从一个Java版本到另一个版本发生变化。 - 不同版本、平台和供应商之间使用的方法甚至类名称本身都可能不同。
在我看来,这些原因足以说明不应该使用它......但这是一个观点问题。
如果Unsafe成为标准/标准Java API的一部分(例如在Java 9中),那么上述某些问题将无关紧要。但我认为,如果犯了错误,导致JVM崩溃的风险仍然存在。

4

在JavaOne 2013的一个会议上,JDK架构师Mark Reinhold被问到一个问题:“使用Unsafe类有多安全?”他给出了令人惊讶的答案:“我相信它应该成为稳定的API。当然要经过适当的安全检查等保护措施…”

因此,看起来JDK9可能会有类似java.util.Unsafe的东西。与此同时,使用现有的类是相对安全的(尽管做不安全的事情总是有风险的)。


这不仅仅是一个谣言:http://openjdk.5641.n7.nabble.com/Turn-sun-misc-Unsafe-into-a-public-API-td158365.html - Rafael Winterhalter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接