Насколько опасно использование sun.misc.Unsafe на самом деле?

Мне интересно, насколько опасно использование sun.misc.Unsafe. Я хочу создать прокси-объект объекта, где я перехватываю вызов метода каждый (но один для Object.finalize для соображений производительности). Для этой цели я выполнил поиск по слову litle и придумал следующий фрагмент кода:

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 рекламируется как запись один раз, запускайте всю мою реальность, поскольку разработчик выглядит как Write Once, запускается один раз в управляемой среде выполнения клиента
  • sun.misc.Unsafe считается частью публичного API в Java 9
  • Многие виртуальные машины, отличные от Oracle, также предлагают sun.misc.Unsafe, поскольку, я думаю, есть довольно некоторые библиотеки уже используют его. Это также приводит к тому, что класс вряд ли исчезнет.
  • Я никогда не буду запускать приложение на Android, поэтому для меня это не важно.
  • Сколько людей фактически используют виртуальные машины без Oracle?

Мне все еще интересно: есть ли другие причины, почему я не должен использовать sun.misc.Unsafe, о котором я не думал? Если вы зададите эти вопросы, люди скорее ответят на неопределенное, потому что это небезопасно, но я действительно не чувствую, что это помимо (очень маловероятной) возможности того, что этот метод однажды исчезнет из Oracle VM.

Мне действительно нужно создать объект без вызова конструктора для преодоления системы типа Java. Я не рассматриваю sun.misc.Unsafe для причин производительности.

Дополнительная информация: Я использую ReflectionFactory в примере для удобства, который делегирует Unsafe. Я знаю о библиотеках, таких как objenesis, но, глядя на код, я узнал, что они в основном делают что-то подобное, но проверяют другие способы использования Java версии, которые не будут работать для меня в любом случае, поэтому я думаю, что писать четыре строки стоит сохранить зависимость.

Ответ 1

Существуют три существенные проблемы (IMO):

  • Методы в классе Unsafe имеют возможность нарушать безопасность во время выполнения и делать другие вещи, которые могут привести к жесткому сбою JVM.

  • Практически все, что вы делаете, используя Unsafe, теоретически может зависеть от внутренних деталей JVM; то есть детали того, как JVM делает вещи и представляет вещи. Они могут быть зависимыми от платформы и могут меняться от одной версии Java к следующей.

  • Используемые вами методы... или даже имя самого класса... могут отличаться от разных версий, платформ и поставщиков.

ИМО, это приводит к сильным причинам не делать этого... но это вопрос мнения.

Теперь, если Unsafe становится стандартизированным/частью стандартного Java API (например, в Java 9), тогда некоторые из вышеперечисленных проблем будут спорными. Но я думаю, что риск серьезных сбоев, если вы допустили ошибку, всегда останется.

Ответ 2

Во время одной сессии JavaOne 2013 Марк Рейнхольд (архитектор JDK) задал вопрос: "Насколько безопасно использовать класс Unsafe?". Он ответил с каким-то удивительным ответом: "Я считаю, что он должен стать стабильным API. Конечно, правильно защищен с проверками безопасности и т.д."

Итак, похоже, что может быть что-то вроде java.util.Unsafe для JDK9. Между тем использование существующего класса относительно безопасно (так же безопасно, как и делать что-то небезопасное).