2015-04-02 4 views
1

Есть два аналогичных методов в Java ObjectInputStream:Когда будет использоваться ObjectInputStream.readUshared() vs .readObject()?

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() против .readObject()

+0

Никогда не использовал его. Одно использование было бы как проверка соответствия протокола, чтобы гарантировать, что отправитель использовал 'writeUnshared().' Если он не является описанным исключением, это приведет. – EJP

ответ

0

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

А.6 Ограждение Неподеленная десериализованное объектов

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

В копировальном подходе, суб-объекты Десериализованные из потока следует рассматривать как «ненадежный ввод»: вновь создаваемые объекты, инициализирован, чтобы иметь такое же значение, как Десериализованный подобъектам, должны быть заменен на под-объекты методом readObject. Например, предположим, что объект имеет частный байтовое поле массива, 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(); 
} 

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

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

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