mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
Implement a rudimentary Java-compatible ObjectInputStream
The Java Language Specification documents the serialization protocol implemented by this change set: http://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html#10258 This change is intended to make it easier to use Avian VM as a drop-in replacement for the Oracle JVM when serializing objects. The previous serialization code is still available as avian.LegacyObjectInputStream. This commit only implements the non-object parts of the deserialization specification. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
parent
35ecf5025c
commit
4b8285e597
234
classpath/avian/LegacyObjectInputStream.java
Normal file
234
classpath/avian/LegacyObjectInputStream.java
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/* Copyright (c) 2008-2013, Avian Contributors
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software
|
||||||
|
for any purpose with or without fee is hereby granted, provided
|
||||||
|
that the above copyright notice and this permission notice appear
|
||||||
|
in all copies.
|
||||||
|
|
||||||
|
There is NO WARRANTY for this software. See license.txt for
|
||||||
|
details. */
|
||||||
|
|
||||||
|
package java.io;
|
||||||
|
|
||||||
|
import avian.VMClass;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
public class LegacyObjectInputStream extends InputStream {
|
||||||
|
private final InputStream in;
|
||||||
|
private final PushbackReader r;
|
||||||
|
|
||||||
|
public LegacyObjectInputStream(InputStream in) {
|
||||||
|
this.in = in;
|
||||||
|
this.r = new PushbackReader(new InputStreamReader(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
return in.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
|
return in.read(b, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object readObject() throws IOException, ClassNotFoundException {
|
||||||
|
return readObject(new HashMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean readBoolean() throws IOException {
|
||||||
|
read('z');
|
||||||
|
return readLongToken() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte readByte() throws IOException {
|
||||||
|
read('b');
|
||||||
|
return (byte) readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public char readChar() throws IOException {
|
||||||
|
read('c');
|
||||||
|
return (char) readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public short readShort() throws IOException {
|
||||||
|
read('s');
|
||||||
|
return (short) readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readInt() throws IOException {
|
||||||
|
read('i');
|
||||||
|
return (int) readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long readLong() throws IOException {
|
||||||
|
read('j');
|
||||||
|
return readLongToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float readFloat() throws IOException {
|
||||||
|
read('f');
|
||||||
|
return (float) readDoubleToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double readDouble() throws IOException {
|
||||||
|
read('d');
|
||||||
|
return readDoubleToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void defaultReadObject() throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void skipSpace() throws IOException {
|
||||||
|
int c;
|
||||||
|
while ((c = r.read()) != -1 && Character.isWhitespace((char) c));
|
||||||
|
if (c != -1) {
|
||||||
|
r.unread(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void read(char v) throws IOException {
|
||||||
|
skipSpace();
|
||||||
|
|
||||||
|
int c = r.read();
|
||||||
|
if (c != v) {
|
||||||
|
if (c == -1) {
|
||||||
|
throw new EOFException();
|
||||||
|
} else {
|
||||||
|
throw new StreamCorruptedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readStringToken() throws IOException {
|
||||||
|
skipSpace();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int c;
|
||||||
|
while ((c = r.read()) != -1 && ! Character.isWhitespace((char) c) && c != ')') {
|
||||||
|
sb.append((char) c);
|
||||||
|
}
|
||||||
|
if (c != -1) {
|
||||||
|
r.unread(c);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long readLongToken() throws IOException {
|
||||||
|
return Long.parseLong(readStringToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
private double readDoubleToken() throws IOException {
|
||||||
|
return Double.parseDouble(readStringToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object readObject(HashMap<Integer, Object> map)
|
||||||
|
throws IOException, ClassNotFoundException
|
||||||
|
{
|
||||||
|
skipSpace();
|
||||||
|
switch (r.read()) {
|
||||||
|
case 'a':
|
||||||
|
return deserializeArray(map);
|
||||||
|
case 'l':
|
||||||
|
return deserializeObject(map);
|
||||||
|
case 'n':
|
||||||
|
return null;
|
||||||
|
case -1:
|
||||||
|
throw new EOFException();
|
||||||
|
default:
|
||||||
|
throw new StreamCorruptedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object deserialize(HashMap<Integer, Object> map)
|
||||||
|
throws IOException, ClassNotFoundException
|
||||||
|
{
|
||||||
|
skipSpace();
|
||||||
|
switch (r.read()) {
|
||||||
|
case 'a':
|
||||||
|
return deserializeArray(map);
|
||||||
|
case 'l':
|
||||||
|
return deserializeObject(map);
|
||||||
|
case 'r':
|
||||||
|
return map.get((int) readLongToken());
|
||||||
|
case 'n':
|
||||||
|
return null;
|
||||||
|
case 'z':
|
||||||
|
return (readLongToken() != 0);
|
||||||
|
case 'b':
|
||||||
|
return (byte) readLongToken();
|
||||||
|
case 'c':
|
||||||
|
return (char) readLongToken();
|
||||||
|
case 's':
|
||||||
|
return (short) readLongToken();
|
||||||
|
case 'i':
|
||||||
|
return (int) readLongToken();
|
||||||
|
case 'j':
|
||||||
|
return readLongToken();
|
||||||
|
case 'f':
|
||||||
|
return (float) readDoubleToken();
|
||||||
|
case 'd':
|
||||||
|
return readDoubleToken();
|
||||||
|
case -1:
|
||||||
|
throw new EOFException();
|
||||||
|
default:
|
||||||
|
throw new StreamCorruptedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object deserializeArray(HashMap<Integer, Object> map)
|
||||||
|
throws IOException, ClassNotFoundException
|
||||||
|
{
|
||||||
|
read('(');
|
||||||
|
int id = (int) readLongToken();
|
||||||
|
Class c = Class.forName(readStringToken());
|
||||||
|
int length = (int) readLongToken();
|
||||||
|
Class t = c.getComponentType();
|
||||||
|
Object o = Array.newInstance(t, length);
|
||||||
|
|
||||||
|
map.put(id, o);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
Array.set(o, i, deserialize(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
read(')');
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native Object makeInstance(VMClass c);
|
||||||
|
|
||||||
|
private Object deserializeObject(HashMap<Integer, Object> map)
|
||||||
|
throws IOException, ClassNotFoundException
|
||||||
|
{
|
||||||
|
read('(');
|
||||||
|
int id = (int) readLongToken();
|
||||||
|
Class c = Class.forName(readStringToken());
|
||||||
|
Object o = makeInstance(c.vmClass);
|
||||||
|
|
||||||
|
map.put(id, o);
|
||||||
|
|
||||||
|
for (Field f: c.getAllFields()) {
|
||||||
|
int modifiers = f.getModifiers();
|
||||||
|
if ((modifiers & (Modifier.TRANSIENT | Modifier.STATIC)) == 0) {
|
||||||
|
try {
|
||||||
|
f.set(o, deserialize(map));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read(')');
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,29 @@
|
|||||||
|
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
|
import static java.io.ObjectOutputStream.STREAM_MAGIC;
|
||||||
|
import static java.io.ObjectOutputStream.STREAM_VERSION;
|
||||||
|
import static java.io.ObjectOutputStream.TC_NULL;
|
||||||
|
import static java.io.ObjectOutputStream.TC_REFERENCE;
|
||||||
|
import static java.io.ObjectOutputStream.TC_CLASSDESC;
|
||||||
|
import static java.io.ObjectOutputStream.TC_OBJECT;
|
||||||
|
import static java.io.ObjectOutputStream.TC_STRING;
|
||||||
|
import static java.io.ObjectOutputStream.TC_ARRAY;
|
||||||
|
import static java.io.ObjectOutputStream.TC_CLASS;
|
||||||
|
import static java.io.ObjectOutputStream.TC_BLOCKDATA;
|
||||||
|
import static java.io.ObjectOutputStream.TC_ENDBLOCKDATA;
|
||||||
|
import static java.io.ObjectOutputStream.TC_RESET;
|
||||||
|
import static java.io.ObjectOutputStream.TC_BLOCKDATALONG;
|
||||||
|
import static java.io.ObjectOutputStream.TC_EXCEPTION;
|
||||||
|
import static java.io.ObjectOutputStream.TC_LONGSTRING;
|
||||||
|
import static java.io.ObjectOutputStream.TC_PROXYCLASSDESC;
|
||||||
|
import static java.io.ObjectOutputStream.TC_ENUM;
|
||||||
|
import static java.io.ObjectOutputStream.SC_WRITE_METHOD;
|
||||||
|
import static java.io.ObjectOutputStream.SC_BLOCK_DATA;
|
||||||
|
import static java.io.ObjectOutputStream.SC_SERIALIZABLE;
|
||||||
|
import static java.io.ObjectOutputStream.SC_EXTERNALIZABLE;
|
||||||
|
import static java.io.ObjectOutputStream.SC_ENUM;
|
||||||
|
|
||||||
import avian.VMClass;
|
import avian.VMClass;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -17,218 +40,187 @@ import java.lang.reflect.Array;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
public class ObjectInputStream extends InputStream {
|
public class ObjectInputStream extends InputStream implements DataInput {
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
private final PushbackReader r;
|
|
||||||
|
|
||||||
public ObjectInputStream(InputStream in) {
|
public ObjectInputStream(InputStream in) throws IOException {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.r = new PushbackReader(new InputStreamReader(in));
|
short signature = (short)rawShort();
|
||||||
|
if (signature != STREAM_MAGIC) {
|
||||||
|
throw new IOException("Unrecognized signature: 0x"
|
||||||
|
+ Integer.toHexString(signature));
|
||||||
|
}
|
||||||
|
int version = rawShort();
|
||||||
|
if (version != STREAM_VERSION) {
|
||||||
|
throw new IOException("Unsupported version: " + version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
return in.read();
|
return in.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int rawByte() throws IOException {
|
||||||
|
int c = read();
|
||||||
|
if (c < 0) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rawShort() throws IOException {
|
||||||
|
return (rawByte() << 8) | rawByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rawInt() throws IOException {
|
||||||
|
return (rawShort() << 16) | rawShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long rawLong() throws IOException {
|
||||||
|
return ((rawInt() & 0xffffffffl) << 32) | rawInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String rawString() throws IOException {
|
||||||
|
int length = rawShort();
|
||||||
|
byte[] array = new byte[length];
|
||||||
|
readFully(array);
|
||||||
|
return new String(array);
|
||||||
|
}
|
||||||
|
|
||||||
public int read(byte[] b, int offset, int length) throws IOException {
|
public int read(byte[] b, int offset, int length) throws IOException {
|
||||||
return in.read(b, offset, length);
|
return in.read(b, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void readFully(byte[] b) throws IOException {
|
||||||
|
readFully(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readFully(byte[] b, int offset, int length) throws IOException {
|
||||||
|
while (length > 0) {
|
||||||
|
int count = read(b, offset, length);
|
||||||
|
if (count < 0) {
|
||||||
|
throw new EOFException("Reached EOF " + length + " bytes too early");
|
||||||
|
}
|
||||||
|
offset += count;
|
||||||
|
length -= count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readLine() throws IOException {
|
||||||
|
int c = read();
|
||||||
|
if (c < 0) {
|
||||||
|
return null;
|
||||||
|
} else if (c == '\n') {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (;;) {
|
||||||
|
builder.append((char)c);
|
||||||
|
c = read();
|
||||||
|
if (c < 0 || c == '\n') {
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object readObject() throws IOException, ClassNotFoundException {
|
public Object readObject() throws IOException, ClassNotFoundException {
|
||||||
return readObject(new HashMap());
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
private int remainingBlockData;
|
||||||
|
|
||||||
|
private int rawBlockDataByte() throws IOException {
|
||||||
|
while (remainingBlockData <= 0) {
|
||||||
|
int b = rawByte();
|
||||||
|
if (b == TC_BLOCKDATA) {
|
||||||
|
remainingBlockData = rawByte();
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException("Unknown token: 0x"
|
||||||
|
+ Integer.toHexString(b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--remainingBlockData;
|
||||||
|
return rawByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rawBlockDataShort() throws IOException {
|
||||||
|
return (rawBlockDataByte() << 8) | rawBlockDataByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rawBlockDataInt() throws IOException {
|
||||||
|
return (rawBlockDataShort() << 16) | rawBlockDataShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long rawBlockDataLong() throws IOException {
|
||||||
|
return ((rawBlockDataInt() & 0xffffffffl) << 32) | rawBlockDataInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readBoolean() throws IOException {
|
public boolean readBoolean() throws IOException {
|
||||||
read('z');
|
return rawBlockDataByte() != 0;
|
||||||
return readLongToken() != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte readByte() throws IOException {
|
public byte readByte() throws IOException {
|
||||||
read('b');
|
return (byte)rawBlockDataByte();
|
||||||
return (byte) readLongToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public char readChar() throws IOException {
|
public char readChar() throws IOException {
|
||||||
read('c');
|
return (char)rawBlockDataShort();
|
||||||
return (char) readLongToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public short readShort() throws IOException {
|
public short readShort() throws IOException {
|
||||||
read('s');
|
return (short)rawBlockDataShort();
|
||||||
return (short) readLongToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readInt() throws IOException {
|
public int readInt() throws IOException {
|
||||||
read('i');
|
return rawBlockDataInt();
|
||||||
return (int) readLongToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long readLong() throws IOException {
|
public long readLong() throws IOException {
|
||||||
read('j');
|
return rawBlockDataLong();
|
||||||
return readLongToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float readFloat() throws IOException {
|
public float readFloat() throws IOException {
|
||||||
read('f');
|
return Float.intBitsToFloat(rawBlockDataInt());
|
||||||
return (float) readDoubleToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double readDouble() throws IOException {
|
public double readDouble() throws IOException {
|
||||||
read('d');
|
return Double.longBitsToDouble(rawBlockDataLong());
|
||||||
return readDoubleToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void defaultReadObject() throws IOException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void skipSpace() throws IOException {
|
public int readUnsignedByte() throws IOException {
|
||||||
int c;
|
return rawBlockDataByte();
|
||||||
while ((c = r.read()) != -1 && Character.isWhitespace((char) c));
|
}
|
||||||
if (c != -1) {
|
|
||||||
r.unread(c);
|
public int readUnsignedShort() throws IOException {
|
||||||
|
return rawBlockDataShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readUTF() throws IOException {
|
||||||
|
int length = rawBlockDataShort();
|
||||||
|
if (remainingBlockData < length) {
|
||||||
|
throw new IOException("Short block data: "
|
||||||
|
+ remainingBlockData + " < " + length);
|
||||||
}
|
}
|
||||||
|
byte[] bytes = new byte[length];
|
||||||
|
readFully(bytes);
|
||||||
|
remainingBlockData -= length;
|
||||||
|
return new String(bytes, "UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void read(char v) throws IOException {
|
public int skipBytes(int count) throws IOException {
|
||||||
skipSpace();
|
int i = 0;
|
||||||
|
while (i < count) {
|
||||||
int c = r.read();
|
if (read() < 0) {
|
||||||
if (c != v) {
|
return i;
|
||||||
if (c == -1) {
|
|
||||||
throw new EOFException();
|
|
||||||
} else {
|
|
||||||
throw new StreamCorruptedException();
|
|
||||||
}
|
}
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readStringToken() throws IOException {
|
|
||||||
skipSpace();
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
int c;
|
|
||||||
while ((c = r.read()) != -1 && ! Character.isWhitespace((char) c) && c != ')') {
|
|
||||||
sb.append((char) c);
|
|
||||||
}
|
|
||||||
if (c != -1) {
|
|
||||||
r.unread(c);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private long readLongToken() throws IOException {
|
|
||||||
return Long.parseLong(readStringToken());
|
|
||||||
}
|
|
||||||
|
|
||||||
private double readDoubleToken() throws IOException {
|
|
||||||
return Double.parseDouble(readStringToken());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object readObject(HashMap<Integer, Object> map)
|
|
||||||
throws IOException, ClassNotFoundException
|
|
||||||
{
|
|
||||||
skipSpace();
|
|
||||||
switch (r.read()) {
|
|
||||||
case 'a':
|
|
||||||
return deserializeArray(map);
|
|
||||||
case 'l':
|
|
||||||
return deserializeObject(map);
|
|
||||||
case 'n':
|
|
||||||
return null;
|
|
||||||
case -1:
|
|
||||||
throw new EOFException();
|
|
||||||
default:
|
|
||||||
throw new StreamCorruptedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object deserialize(HashMap<Integer, Object> map)
|
|
||||||
throws IOException, ClassNotFoundException
|
|
||||||
{
|
|
||||||
skipSpace();
|
|
||||||
switch (r.read()) {
|
|
||||||
case 'a':
|
|
||||||
return deserializeArray(map);
|
|
||||||
case 'l':
|
|
||||||
return deserializeObject(map);
|
|
||||||
case 'r':
|
|
||||||
return map.get((int) readLongToken());
|
|
||||||
case 'n':
|
|
||||||
return null;
|
|
||||||
case 'z':
|
|
||||||
return (readLongToken() != 0);
|
|
||||||
case 'b':
|
|
||||||
return (byte) readLongToken();
|
|
||||||
case 'c':
|
|
||||||
return (char) readLongToken();
|
|
||||||
case 's':
|
|
||||||
return (short) readLongToken();
|
|
||||||
case 'i':
|
|
||||||
return (int) readLongToken();
|
|
||||||
case 'j':
|
|
||||||
return readLongToken();
|
|
||||||
case 'f':
|
|
||||||
return (float) readDoubleToken();
|
|
||||||
case 'd':
|
|
||||||
return readDoubleToken();
|
|
||||||
case -1:
|
|
||||||
throw new EOFException();
|
|
||||||
default:
|
|
||||||
throw new StreamCorruptedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object deserializeArray(HashMap<Integer, Object> map)
|
|
||||||
throws IOException, ClassNotFoundException
|
|
||||||
{
|
|
||||||
read('(');
|
|
||||||
int id = (int) readLongToken();
|
|
||||||
Class c = Class.forName(readStringToken());
|
|
||||||
int length = (int) readLongToken();
|
|
||||||
Class t = c.getComponentType();
|
|
||||||
Object o = Array.newInstance(t, length);
|
|
||||||
|
|
||||||
map.put(id, o);
|
|
||||||
|
|
||||||
for (int i = 0; i < length; ++i) {
|
|
||||||
Array.set(o, i, deserialize(map));
|
|
||||||
}
|
|
||||||
|
|
||||||
read(')');
|
|
||||||
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static native Object makeInstance(VMClass c);
|
private static native Object makeInstance(VMClass c);
|
||||||
|
|
||||||
private Object deserializeObject(HashMap<Integer, Object> map)
|
|
||||||
throws IOException, ClassNotFoundException
|
|
||||||
{
|
|
||||||
read('(');
|
|
||||||
int id = (int) readLongToken();
|
|
||||||
Class c = Class.forName(readStringToken());
|
|
||||||
Object o = makeInstance(c.vmClass);
|
|
||||||
|
|
||||||
map.put(id, o);
|
|
||||||
|
|
||||||
for (Field f: c.getAllFields()) {
|
|
||||||
int modifiers = f.getModifiers();
|
|
||||||
if ((modifiers & (Modifier.TRANSIENT | Modifier.STATIC)) == 0) {
|
|
||||||
try {
|
|
||||||
f.set(o, deserialize(map));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read(')');
|
|
||||||
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user