-
Notifications
You must be signed in to change notification settings - Fork 56
Java serialization
Sayapin Alexander edited this page Aug 13, 2017
·
9 revisions
- http://javapapers.com/core-java/java-serialization/
- https://docs.oracle.com/javase/8/docs/platform/serialization/spec/protocol.html
- https://habrahabr.ru/post/60317/
- http://www.javaworld.com/article/2072752/the-java-serialization-algorithm-revealed.html
Целью изучения и этого раздела является создание библиотек для взаимодействия Java и PHP:
- Сериализация/десериализация: /wizardjedi/php-java-serialization
package test.serialize;
package test.serialize;
import java.io.*;
import java.util.HashMap;
class Main {
public static class Cls1 implements Serializable {
protected Long val = new Long(123);
}
public static class Cls2 extends Cls1 {
protected String val2 = "Test string";
}
public static void main(String[] args) throws Exception {
write("Boolean(true)",(oos)->oos.writeBoolean(true));
write("Boolean(false)",(oos)->oos.writeBoolean(false));
write("Byte(0x11)",(oos)->oos.writeByte(0x11));
write("Bytes(ab)",(oos)->oos.writeBytes("ab"));
write("Char(z)",(oos)->oos.writeChar('z'));
write("Chars(abc)",(oos)->oos.writeChars("abc"));
write("Int(1234)",(oos)->oos.writeInt(1234));
write("Long(1234)",(oos)->oos.writeLong(1234));
write("Short(1234)",(oos)->oos.writeShort(1234));
write("Object(a)",(oos)->oos.writeObject("a"));
write("Object(п)",(oos)->oos.writeObject("п"));
write("Object(new HashMap<>())",(oos)->oos.writeObject(new HashMap<>()));
write("Object(new Cls1)",(oos)->oos.writeObject(new Cls1()));
write("Object(new Cls2)",(oos)->oos.writeObject(new Cls2()));
}
public static void write(String title, Function<ObjectOutputStream> consumer) throws Exception {
System.out.println(title+":");
StringWriter s = new StringWriter();
ObjectOutputStream oos = new ObjectOutputStream(new HexOutputStream(s));
consumer.apply(oos);
oos.flush();
oos.close();
System.out.println(s.toString()+"\n");
}
public interface Function<T> {
void apply(T t) throws Exception;
}
/**
* @see com.sun.corba.se.impl.orbutil
* Got this class for hex dump with some changes.
*/
public static class HexOutputStream extends OutputStream
{
public static final int PADDING = 16;
protected char[] row = new char[PADDING];
static private final char hex[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
private StringWriter writer;
private long offset = 0;
/**
* Creates a new HexOutputStream.
* @param w The underlying StringWriter.
*/
public
HexOutputStream(StringWriter w) {
writer = w;
}
/**
* Writes a byte. Will block until the byte is actually
* written.
* param b The byte to write out.
* @exception java.io.IOException I/O error occurred.
*/
public synchronized void write(int b) throws IOException {
if (offset % PADDING == 0) {
for (int i=4*2;i>=0;i--) {
int tmpOffset = (int)(offset >> i*4);
writer.write(hex[((tmpOffset) & 0xF)]);
}
writer.write(": ");
}
writer.write(hex[((b >> 4) & 0xF)]);
writer.write(hex[((b >> 0) & 0xF)]);
offset++;
row[(int)((offset-1) % PADDING)] = (char)b;
if (offset % PADDING == 0) {
writer.write(" | ");
//for (int i=0;i<row.length;i++) {
writer.write(row);
//}
writer.write("\n");
} else {
writer.write(" ");
}
}
@Override
public void close() throws IOException {
//System.out.print(">>"+offset % PADDING);
if (offset % PADDING < PADDING) {
for (int i=(int)(offset % PADDING);i<PADDING;i++) {
writer.append(" ");
}
writer.write("| ");
writer.write(row, 0, (int)(offset % PADDING));
}
super.close();
}
public synchronized void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public synchronized void write(byte[] b, int off, int len)
throws IOException
{
for(int i=0; i < len; i++) {
write(b[off + i]);
}
}
}
}
Пример запуска
$ java -cp build/classes/ test.serialize.TestSerialize
Boolean(true):
000000000: ac ed 00 05 77 01 01 | ᆲ■ w
Boolean(false):
000000000: ac ed 00 05 77 01 00 | ᆲ■ w
Byte(0x11):
000000000: ac ed 00 05 77 01 11 | ᆲ■ w
Bytes(ab):
000000000: ac ed 00 05 77 02 61 62 | ᆲ■ wab
Char(z):
000000000: ac ed 00 05 77 02 00 7a | ᆲ■ w z
Chars(abc):
000000000: ac ed 00 05 77 06 00 61 00 62 00 63 | ᆲ■ w a b c
Int(1234):
000000000: ac ed 00 05 77 04 00 00 04 d2 | ᆲ■ w ᅭ
Long(1234):
000000000: ac ed 00 05 77 08 00 00 00 00 00 00 04 d2 | ᆲ■ ᅭ
Short(1234):
000000000: ac ed 00 05 77 02 04 d2 | ᆲ■ wᅭ
Object(a):
000000000: ac ed 00 05 74 00 01 61 | ᆲ■ t a
Object(п):
000000000: ac ed 00 05 74 00 02 d0 bf | ᆲ■ t
Object(new HashMap<>()):
000000000: ac ed 00 05 73 72 00 11 6a 61 76 61 2e 75 74 69 | ᆲ■ sr java.uti
000000010: 6c 2e 48 61 73 68 4d 61 70 05 07 da c1 c3 16 60 | l.HashMapᅳᅢ`
000000020: d1 03 00 02 46 00 0a 6c 6f 61 64 46 61 63 74 6f | F
loadFacto
000000030: 72 49 00 09 74 68 72 65 73 68 6f 6c 64 78 70 3f | rI thresholdxp?
000000040: 40 00 00 00 00 00 00 77 08 00 00 00 10 00 00 00 | @
000000050: 00 78 | x
Object(new Cls1):
000000000: ac ed 00 05 73 72 00 18 74 65 73 74 2e 73 65 72 | ᆲ■ sr test.ser
000000010: 69 61 6c 69 7a 65 2e 4d 61 69 6e 24 43 6c 73 31 | ialize.Main$Cls1
000000020: 4d 22 c3 b4 41 00 bf 41 02 00 01 4c 00 03 76 61 | M"ᅢᄡA A L va
000000030: 6c 74 00 10 4c 6a 61 76 61 2f 6c 61 6e 67 2f 4c | lt Ljava/lang/L
000000040: 6f 6e 67 3b 78 70 73 72 00 0e 6a 61 76 61 2e 6c | ong;xpsr java.l
000000050: 61 6e 67 2e 4c 6f 6e 67 3b 8b e4 90 cc 8f 23 df | ang.Long;ヒ¦ミᅩマ#
000000060: 02 00 01 4a 00 05 76 61 6c 75 65 78 72 00 10 6a | J valuexr j
000000070: 61 76 61 2e 6c 61 6e 67 2e 4e 75 6d 62 65 72 86 | ava.lang.Numberニ
000000080: ac 95 1d 0b 94 e0 8b 02 00 00 78 70 00 00 00 00 | ᆲユヤ¢ヒ xp
000000090: 00 00 00 7b | {
Object(new Cls2):
000000000: ac ed 00 05 73 72 00 18 74 65 73 74 2e 73 65 72 | ᆲ■ sr test.ser
000000010: 69 61 6c 69 7a 65 2e 4d 61 69 6e 24 43 6c 73 32 | ialize.Main$Cls2
000000020: 5b 34 53 26 2c d5 84 5a 02 00 01 4c 00 04 76 61 | [4S&,ᅰトZ L va
000000030: 6c 32 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f | l2t Ljava/lang/
000000040: 53 74 72 69 6e 67 3b 78 72 00 18 74 65 73 74 2e | String;xr test.
000000050: 73 65 72 69 61 6c 69 7a 65 2e 4d 61 69 6e 24 43 | serialize.Main$C
000000060: 6c 73 31 4d 22 c3 b4 41 00 bf 41 02 00 01 4c 00 | ls1M"ᅢᄡA A L
000000070: 03 76 61 6c 74 00 10 4c 6a 61 76 61 2f 6c 61 6e | valt Ljava/lan
000000080: 67 2f 4c 6f 6e 67 3b 78 70 73 72 00 0e 6a 61 76 | g/Long;xpsr jav
000000090: 61 2e 6c 61 6e 67 2e 4c 6f 6e 67 3b 8b e4 90 cc | a.lang.Long;ヒ¦ミᅩ
0000000a0: 8f 23 df 02 00 01 4a 00 05 76 61 6c 75 65 78 72 | マ# J valuexr
0000000b0: 00 10 6a 61 76 61 2e 6c 61 6e 67 2e 4e 75 6d 62 | java.lang.Numb
0000000c0: 65 72 86 ac 95 1d 0b 94 e0 8b 02 00 00 78 70 00 | erニᆲユヤ¢ヒ xp
0000000d0: 00 00 00 00 00 00 7b 74 00 0b 54 65 73 74 20 73 | {t Test s
0000000e0: 74 72 69 6e 67 | tring
Decode by hands
000000000: ac ed - magic
000000000: 00 05 - stream version
000000000: 7e - TC_ENUM
000000000: 72 - TC_CLASS_DESC
000000000: 00 1a - length = 26
000000000: 74 65 73 74 2e 73 65 72 | test.ser
000000010: 69 61 6c 69 7a 65 2e 4d 61 69 6e 24 4d 79 45 6e | ialize.Main$MyEn
000000020: 75 6d | um
000000020: 00 00 00 00 00 00 00 00 - serial version uid
000000020: 12 - Flags?
000000020: 00 00 - fields count
000000020: 78 - end block data for class annotation
000000020: 72 - super class class desc
000000020: 00 - start of length of class
000000030: 0e - length = 14
000000030: 6a 61 76 61 2e 6c 61 6e 67 2e 45 6e 75 6d |java.lang.Enum
000000030: 00 - start of serial version id
000000040: 00 00 00 00 00 00 00 - serial version id
000000040: 12 - flags
000000040: 00 00 - field count 0
000000040: 78 - end block data
000000040: 70 - TC_NULL
000000040: 74 - TC_STRING
000000040: 00 06 -- string length
000000040: 56 - name | V
000000050: 41 4c 55 45 32 | ALUE2