Spec-Zone .ru
спецификации, руководства, описания, API
|
СОДЕРЖАНИЕ | ПРЕДЫДУЩИЙ | NEXT | Спецификация Сериализации Объекта Java версия 6.0 |
ГЛАВА 6 |
Темы:
Потоковый формат удовлетворяет следующие цели проекта:
Объект class представляется следующим:
ObjectStreamClass
объект для Класса, который не является динамическим прокси class, представляется следующим:
writeObject
метод, и сериализуем ли class, externalizable, или перечислимый типLjava/lang/Object;
") как определено в Спецификации виртуальной машины Java.annotateClass
методObjectStreamClass
из его супертипа (нуль, если суперкласс не сериализуем), ObjectStreamClass
объект для динамического прокси class представляется следующим:
getInterfaces
метод на объекте Класса.annotateProxyClass
метод.java.lang.reflect.Proxy
.String
объекты состоят из информации о длине, сопровождаемой содержанием строки, закодированной в измененном UTF-8. Измененное кодирование UTF-8 является тем же самым как использующийся в виртуальной машине Java и в java.io.DataInput
и DataOutput
интерфейсы; это отличается от стандартного UTF-8 в представлении дополнительных символов и нулевого символа. Форма информации о длине зависит от длины строки в измененном кодировании UTF-8. Если измененное кодирование UTF-8 данного String
меньше чем 65536 байтов в длине, длина пишется как 2 байта, представляющие 16-разрядное целое число без знака. Запускаясь с Java 2 платформы, Standard Edition, v1.3, если длина строки в измененном кодировании UTF-8 составляет 65536 байтов или больше, длина пишется в 8 байтах, представляющих подписанное 64-разрядное целое число. typecode предшествование String
в сериализации поток указывает, какой формат использовался, чтобы записать String
.
Массивы представляются следующим:
ObjectStreamClass
объект.Перечислимые константы представляются следующим:
Новые объекты в потоке представляются следующим:
writeObject
/readObject
методы, могут быть дополнительные объекты и/или блочные записи данных типов примитивов, записанных writeObject
метод, сопровождаемый endBlockData
код.Все примитивные данные, записанные классами, буферизуются и обертываются в блочные записи данных, независимо если данные пишутся потоку в пределах a writeObject
метод или записанный непосредственно потоку снаружи a writeObject
метод. Эти данные могут только быть считаны соответствием readObject
методы или быть считанным непосредственно из потока. Объекты, записанные writeObject
метод, оконечный любая предыдущая блочная запись данных и, пишется или как регулярные объекты или как нулевые или обратные ссылки, как соответствующий. Блочные записи данных позволяют восстановлению после ошибки отбрасывать любые дополнительные данные. Когда вызвано изнутри class, поток может отбросить любые данные или объекты до endBlockData
.
ObjectOutputStream.useProtocolVersion
берет в качестве параметра версию протокола, чтобы использовать, чтобы записать поток сериализации.
Потоковые Версии Протокола следующие:
ObjectStreamConstants.PROTOCOL_VERSION_1
: Указывает на начальный потоковый формат.
ObjectStreamConstants.PROTOCOL_VERSION_2
: Указывает на новый внешний формат данных. Примитивные данные пишутся в блочном режиме данных и завершаются с TC_ENDBLOCKDATA.
Блочные границы данных были стандартизированы. Примитивные данные, записанные в блочном режиме данных, нормализуются, чтобы не превысить 1024-байтовые блоки. Преимущество этого изменения должно было сжать спецификацию сериализированного формата данных в потоке. Это изменение является полностью обратным и прямо совместимым.
PROTOCOL_VERSION_2
. JDK 1.1 значения по умолчанию к записи PROTOCOL_VERSION_1
.
JDK 1.1.7 и больше может считать обе версии.
Выпуски до JDK 1.1.7 могут только читать PROTOCOL_VERSION_1
.
Таблица ниже содержит грамматику для потокового формата. Нетерминальные символы показывают курсивом. Терминальные символы в фиксированном шрифте width. Определения нетерминалов сопровождаются ":". Определение сопровождается одной или более альтернативами, каждым на отдельной строке. Следующая таблица описывает нотацию:
Отметьте, что символ (utf) используется, чтобы назвать строку записанной, используя 2-байтовую информацию о длине, и (долго-utf) используется, чтобы назвать строку записанной, используя 8-байтовую информацию о длине. Для получения дополнительной информации обратитесь к Разделу 6.2, "Потоковые Элементы".
Сериализованный поток представляется любым потоком, удовлетворяющим потоковое правило.
stream: magic version contents
contents: content contents content
content: object blockdata
object: newObject newClass newArray newString newEnum newClassDesc prevObject nullReference exception TC_RESET
newClass: TC_CLASS classDesc newHandle
classDesc: newClassDesc nullReference (ClassDesc)prevObject // an object required to be of type // ClassDesc
superClassDesc: classDesc
newClassDesc: TC_CLASSDESC className serialVersionUID newHandle classDescInfo TC_PROXYCLASSDESC newHandle proxyClassDescInfo
classDescInfo: classDescFlags fields classAnnotation superClassDesc
className: (utf)
serialVersionUID: (long)
classDescFlags: (byte) // Defined in Terminal Symbols and // Constants
proxyClassDescInfo: (int)<count> proxyInterfaceName[count] classAnnotation superClassDesc
proxyInterfaceName:
(utf)
fields: (short)<count> fieldDesc[count]
fieldDesc: primitiveDesc objectDesc
primitiveDesc: prim_typecode fieldName
objectDesc: obj_typecode fieldName className1
fieldName: (utf)
className1: (String)object // String containing the field's type, // in field descriptor format
classAnnotation: endBlockData contents endBlockData // contents written by annotateClass
prim_typecode: `B' // byte `C' // char `D' // double `F' // float `I' // integer `J' // long `S' // short `Z' // boolean
obj_typecode: `[` // array `L' // object
newArray: TC_ARRAY classDesc newHandle (int)<size> values[size]
newObject: TC_OBJECT classDesc newHandle classdata[] // data for each class
classdata: nowrclass // SC_SERIALIZABLE & classDescFlag && // !(SC_WRITE_METHOD & classDescFlags) wrclass objectAnnotation // SC_SERIALIZABLE & classDescFlag && // SC_WRITE_METHOD & classDescFlags externalContents // SC_EXTERNALIZABLE & classDescFlag && // !(SC_BLOCKDATA & classDescFlags objectAnnotation // SC_EXTERNALIZABLE & classDescFlag&& // SC_BLOCKDATA & classDescFlags
nowrclass: values // fields in order of class descriptor
wrclass: nowrclass
objectAnnotation: endBlockData contents endBlockData // contents written by writeObject // or writeExternal PROTOCOL_VERSION_2.
blockdata: blockdatashort blockdatalong
blockdatashort: TC_BLOCKDATA (unsigned byte)<size> (byte)[size]
blockdatalong: TC_BLOCKDATALONG (int)<size> (byte)[size]
endBlockData : TC_ENDBLOCKDATA
externalContent: // Only parseable by readExternal ( bytes) // primitive data object
externalContents: // externalContent written by externalContent // writeExternal in PROTOCOL_VERSION_1. externalContents externalContent
newString: TC_STRING newHandle (utf) TC_LONGSTRING newHandle (long-utf)
newEnum: TC_ENUM classDesc newHandle enumConstantName
enumConstantName: (String)object
prevObject TC_REFERENCE (int)handle
nullReference TC_NULL
exception: TC_EXCEPTION reset (Throwable)object reset
magic: STREAM_MAGIC
version STREAM_VERSION
values: // The size and types are described by the // classDesc for the current object
newHandle: // The next number in sequence is assigned // to the object being serialized or deserialized
reset: // The set of known objects is discarded // so the objects of the exception do not // overlap with the previously sent objects // or with objects that may be sent after // the exception
java.io.ObjectStreamConstants
определите терминальные и постоянные величины, ожидаемые в потоке.
final static short STREAM_MAGIC = (short)0xaced; final static short STREAM_VERSION = 5; final static byte TC_NULL = (byte)0x70; final static byte TC_REFERENCE = (byte)0x71; final static byte TC_CLASSDESC = (byte)0x72; final static byte TC_OBJECT = (byte)0x73; final static byte TC_STRING = (byte)0x74; final static byte TC_ARRAY = (byte)0x75; final static byte TC_CLASS = (byte)0x76; final static byte TC_BLOCKDATA = (byte)0x77; final static byte TC_ENDBLOCKDATA = (byte)0x78; final static byte TC_RESET = (byte)0x79; final static byte TC_BLOCKDATALONG = (byte)0x7A; final static byte TC_EXCEPTION = (byte)0x7B; final static byte TC_LONGSTRING = (byte) 0x7C; final static byte TC_PROXYCLASSDESC = (byte) 0x7D; final static byte TC_ENUM = (byte) 0x7E; final static int baseWireHandle = 0x7E0000;Байт флага classDescFlags может включать значения
final static byte SC_WRITE_METHOD = 0x01; //if SC_SERIALIZABLE final static byte SC_BLOCK_DATA = 0x08; //if SC_EXTERNALIZABLE final static byte SC_SERIALIZABLE = 0x02; final static byte SC_EXTERNALIZABLE = 0x04; final static byte SC_ENUM = 0x10;SC_WRITE_METHOD флага устанавливается, если у Сериализуемого class, пишущий поток был a
writeObject
метод, который, возможно, записал дополнительные данные в поток. В этом случае маркер TC_ENDBLOCKDATA, как всегда ожидают, завершит данные для того class. Флаг SC_BLOCKDATA устанавливается если Externalizable
class пишется в потоковое использование STREAM_PROTOCOL_2
. По умолчанию это - протокол, используемый, чтобы записать Externalizable
объекты в поток в JDK 1.2. JDK 1.1 записи STREAM_PROTOCOL_1.
SC_SERIALIZABLE флага устанавливается, если class, который записал расширенный поток java.io.Serializable
но нет java.io.Externalizable
, class, читая поток должен также расшириться java.io.Serializable
и механизм сериализации значения по умолчанию должен использоваться.
SC_EXTERNALIZABLE флага устанавливается, если class, который записал расширенный поток java.io.Externalizable
, class, читая данные должен также расшириться Externalizable
и данные будут считаны, используя writeExternal
и readExternal
методы.
SC_ENUM флага устанавливается, если class, который записал поток, был перечислимым типом. Соответствующий class получателя должен также быть перечислимым типом. Данные для констант перечислимого типа будут записаны и считаны как описано в Разделе 1.12, "Сериализация Перечислимых Констант".
class List implements java.io.Serializable { int value; List next; public static void main(String[] args) { try { List list1 = new List(); List list2 = new List(); list1.value = 17; list1.next = list2; list2.value = 19; list2.next = null; ByteArrayOutputStream o = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(o); out.writeObject(list1); out.writeObject(list2); out.flush(); ... } catch (Exception ex) { ex.printStackTrace(); } } }Получающийся поток содержит:
00: ac ed 00 05 73 72 00 04 4c 69 73 74 69 c8 8a 15 >....sr..Listi...<
10: 40 16 ae 68 02 00 02 49 00 05 76 61 6c 75 65 4c >Z......I..valueL<
20: 00 04 6e 65 78 74 74 00 06 4c 4c 69 73 74 3b 78 >..nextt..LList;x<
30: 70 00 00 00 11 73 71 00 7e 00 00 00 00 00 13 70 >p....sq.~......p<
40: 71 00 7e 00 03 >q.~..<