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

Raf*_*ter 16 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());
}
Run Code Online (Sandbox Code Playgroud)

我的考虑是:

  • 尽管Java被宣传为Write一次,但在任何地方都可以运行,因为开发人员看起来就像写一次,在可控制的客户的运行时环境中运行一次
  • sun.misc.Unsafe认为是Java 9中公共API的一部分
  • sun.misc.Unsafe从那时起,许多非Oracle虚拟机也会提供- 我猜 - 有很多库已经使用它了.这也使得这个班级不太可能消失
  • 我永远不会在Android上运行该应用程序,所以这对我来说无关紧要.
  • 有多少人实际上正在使用非Oracle VM?

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

我实际上需要创建一个对象而不需要调用构造函数来克服Java的类型系统.我不考虑sun.misc.Unsafe性能的原因.

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

Ste*_*n C 7

有三个重要(IMO)问题:

  • Unsafe该类中的方法具有违反运行时类型安全性的能力,并且可以执行其他可能导致JVM"硬崩溃"的事情.

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

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

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

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