Когда можно использовать ObjectInputStream.readUshared () против .readObject ()?

1

В Java ObjectInputStream есть два похожих метода:

readUnshared()

а также

readObject()

В документации указано:

public Object readUnshared() throws IOException, ClassNotFoundException

Считывает объект "unshared" из ObjectInputStream. Этот метод идентичен readObject, за исключением того, что он предотвращает последующие вызовы readObject и readUnshared от возврата дополнительных ссылок на десериализованный экземпляр, полученный с помощью этого вызова. В частности:

Если readUnshared вызывается для десериализации обратной ссылки (представления потока объекта, который был ранее записан в поток), будет выведено исключение ObjectStreamException.

Если readUnshared возвращается успешно, то любые последующие попытки десериализации обратных ссылок на дескриптор потока, десериализованные readUnshared, вызовут исключение ObjectStreamException.

Дезаминирование объекта с помощью readUnshared делает недействительным дескриптор потока, связанный с возвращенным объектом. Обратите внимание, что это само по себе не всегда гарантирует, что ссылка, возвращаемая readUnshared, уникальна; десериализованный объект может определять метод readResolve, который возвращает объект, видимый другим сторонам, или readUnshared может возвращать объект класса или константу перечисления, доступную в другом месте потока или через внешние средства. Если десериализованный объект определяет метод readResolve, и вызов этого метода возвращает массив, тогда readUnshared возвращает неглубокий клон этого массива; это гарантирует, что возвращаемый объект массива уникален и не может быть получен во второй раз из вызова readObject или readUnshared в ObjectInputStream, даже если манипулировать базовым потоком данных.

Подклассы ObjectInputStream, которые переопределяют этот метод, могут быть созданы только в контекстах безопасности, обладающих "enableSubclassImplementation" SerializablePermission; любая попытка создать такой подкласс без этого разрешения вызовет исключение SecurityException.

Но мне было интересно, если бы кто-то использовал для этого реальную жизнь, используя .readUnshared() vs .readObject()

  • 0
    Никогда не использовал это. Одним из них может быть проверка writeUnshared(). протокола, чтобы убедиться, что отправитель использовал writeUnshared(). Если он не исключение, описанное приведет.
Теги:
java-7
objectinputstream
objectoutputstream

1 ответ

0

Я считаю, что это могут быть особые случаи, связанные с безопасностью (?). Как этот (отсюда).

A.6 Защита неразделенных десериализованных объектов

Если класс имеет какие-либо частные или пакетные поля ссылки на объекты частного объекта, а класс зависит от того, что эти ссылки на объекты недоступны вне класса (или пакета), то либо объекты, на которые ссылаются, должны быть скопированы как часть процесса десериализации, иначе методы ObjectOutputStream.writeUnshared и ObjectInputStream.readUnshared (введенные в версии 1.4 JavaTM 2 SDK, Standard Edition) должны использоваться для обеспечения уникальных ссылок на внутренние объекты.

В подходе копирования подэлементы, десериализованные из потока, должны рассматриваться как "ненадежный вход": вновь созданные объекты, инициализированные с тем же значением, что и десериализованные под-объекты, должны быть заменены под-объектами с помощью readObject метод. Например, предположим, что объект имеет поле private byte array, b, которое должно оставаться закрытым:

 private void readObject(ObjectInputStream s)
    throws IOException, ClassNotFoundException
{
    s.defaultReadObject();

    b = (byte[])b.clone();

    if (<invariants are not satisfied>)
        throw new java.io.StreamCorruptedException();
}

Эта проблема особенно важна при рассмотрении сериализации неизменяемых объектов, содержащих внутренние (обязательно частные) ссылки на изменяемые под-объекты. Если не предпринимаются специальные меры для копирования подэлементов во время десериализации объекта-контейнера, то вредоносная сторона с доступом на запись к потоку сериализации может нарушать неизменность объекта-контейнера путем подделки ссылок на его изменяемые под-объекты и использования этих ссылок для изменения внутреннего состояния объекта-контейнера. Таким образом, в этом случае настоятельно необходимо, чтобы класс неизменяемых контейнеров предоставлял метод десериализации, специфичный для класса, который делает частные копии каждого объекта изменяемого компонента, который он десериализует. Обратите внимание, что для сохранения неизменяемости нет необходимости копировать объекты неизменяемых компонентов.

Также важно отметить, что вызов клона не всегда может быть правильным способом для защиты от копирования объекта. Если метод клонирования не может рассчитываться для создания независимой копии (а не для "кражи" ссылки на копию), для создания копии следует использовать альтернативное средство. Альтернативный способ копирования всегда должен использоваться, если класс под-объекта не является окончательным, так как метод clone или методы-помощники, которые он вызывает, могут быть переопределены подклассами.

Начиная с версии 1.4 JavaTM 2 SDK, Standard Edition, уникальные ссылки на десериализованные объекты также могут быть обеспечены с использованием методов ObjectOutputStream.writeUnshared и ObjectInputStream.readUnshared, что позволяет избежать осложнений, затрат на производительность и издержек памяти для защитного копирования.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню