Можно ли обойти проверку канонического конструктора записи во время десериализации или отражения в Java?JAVA

Программисты JAVA общаются здесь
Anonymous
Можно ли обойти проверку канонического конструктора записи во время десериализации или отражения в Java?

Сообщение Anonymous »

Записи Java реализуют инварианты через их канонический конструктор:

Код: Выделить всё

public record User(String name) {
public User {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("Invalid name");
}
}
}
Обычное создание экземпляров и отражение (

Код: Выделить всё

Constructor::newInstance
) оба вызывают этот конструктор.
Я также рассмотрел, как работает десериализация Java (например, конструкторы не вызываются для сериализуемых классов, и вызывается только первый несериализуемый конструктор суперкласса), но эти объяснения предполагают стандартный поток десериализации и не уточняют, можно ли полностью обойти вызов конструктора.
Чтобы изучить это дальше, я попробовал использовать Небезопасно:

Код: Выделить всё

Unsafe unsafe = ...; // obtained via reflection
User user = (User) unsafe.allocateInstance(User.class);
System.out.println(user.name());
Насколько я понимаю, allocateInstance не вызывает конструкторы.
Мои вопросы:
  • Действителен ли этот код для записей или JVM предотвращает выделение экземпляров записей таким образом?
  • Если это работает, эффективно ли он обходит канонический конструктор и нарушает инварианты записей, определенные спецификации языка Java?
  • Опираются ли общие платформы сериализации (например, Jackson, сериализация Java) на аналогичные низкоуровневые механизмы или они обязаны вызывать канонический конструктор для записей?

Вернуться в «JAVA»