Skip to content

Instantly share code, notes, and snippets.

@wangweij
Last active November 10, 2017 09:01
Show Gist options
  • Save wangweij/2c5a87fdab22a578bc8743d96d8d33bf to your computer and use it in GitHub Desktop.
Save wangweij/2c5a87fdab22a578bc8743d96d8d33bf to your computer and use it in GitHub Desktop.
Apply ois-dump.patch to ObjectInputStream.java. If created with a PrintStream as the 2nd argument, reading will generate a dump into that PrintStream. SerialASM.java can read this dump and assemble it into a binary blob or a Java program (if -c specified).
// List.of(1, true, 0.75, "string")
STREAM_MAGIC
s 5
TC_OBJECT
TC_CLASSDESC
"java.util.CollSer"
l 6309168927139932177
3
s 1
'I'
"tag"
TC_ENDBLOCKDATA
TC_NULL
// handle 0 assigned to non proxy desc java.util.CollSer
oct 00000001
TC_BLOCKDATA
4
// refill 4
i 5
TC_OBJECT
TC_CLASSDESC
"java.lang.Integer"
l 1360826667806852920
SC_SERIALIZABLE
s 1
'I'
"value"
TC_ENDBLOCKDATA
TC_CLASSDESC
"java.lang.Number"
l -8742448824652078965
SC_SERIALIZABLE
s 0
TC_ENDBLOCKDATA
TC_NULL
// handle 3 assigned to non proxy desc java.lang.Number
// handle 2 assigned to non proxy desc java.lang.Integer
oct 00000001
// handle 4 assigned to object class java.lang.Integer
TC_OBJECT
TC_CLASSDESC
"java.lang.Boolean"
l -3665804199014368530
SC_SERIALIZABLE
s 1
'Z'
"value"
TC_ENDBLOCKDATA
TC_NULL
// handle 5 assigned to non proxy desc java.lang.Boolean
oct 01
// handle 6 assigned to object class java.lang.Boolean
TC_OBJECT
TC_CLASSDESC
"java.lang.Double"
l -9172774392245257468
SC_SERIALIZABLE
s 1
'D'
"value"
TC_ENDBLOCKDATA
TC_REFERENCE
h 3
// handle 7 assigned to non proxy desc java.lang.Double
oct 3FE8000000000000
// handle 8 assigned to object class java.lang.Double
TC_STRING
"string"
// handle 9 assigned to str string
TC_REFERENCE
h 9
TC_ENDBLOCKDATA
// handle 1 assigned to object class java.util.CollSer
diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java
@@ -29,6 +29,7 @@
import java.lang.System.Logger;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Array;
+import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.security.AccessControlContext;
@@ -243,6 +244,8 @@
"double", double.class,
"void", void.class);
+ private static final char[] hchars = "0123456789ABCDEF".toCharArray();
+
private static class Caches {
/** cache of subclass security audit results */
static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
@@ -333,9 +336,13 @@
* @see ObjectOutputStream#ObjectOutputStream(OutputStream)
*/
public ObjectInputStream(InputStream in) throws IOException {
+ this(in, null);
+ }
+
+ public ObjectInputStream(InputStream in, PrintStream dump) throws IOException {
verifySubclass();
- bin = new BlockDataInputStream(in);
- handles = new HandleTable(10);
+ bin = new BlockDataInputStream(in, dump);
+ handles = new HandleTable(10, dump);
vlist = new ValidationList();
serialFilter = ObjectInputFilter.Config.getSerialFilter();
enableOverride = false;
@@ -1693,7 +1700,7 @@
if (bin.readByte() != TC_REFERENCE) {
throw new InternalError();
}
- passHandle = bin.readInt() - baseWireHandle;
+ passHandle = bin.readHandle();
if (passHandle < 0 || passHandle >= handles.size()) {
throw new StreamCorruptedException(
String.format("invalid handle value: %08X", passHandle +
@@ -1734,6 +1741,7 @@
handles.markException(passHandle, resolveEx);
}
+ handles.describe(passHandle, "class " + desc.getName());
handles.finish(passHandle);
return cl;
}
@@ -1840,6 +1848,7 @@
}
handles.finish(descHandle);
+ handles.describe(descHandle, "proxy desc " + desc.getName());
passHandle = descHandle;
return desc;
}
@@ -1897,6 +1906,7 @@
}
handles.finish(descHandle);
+ handles.describe(descHandle, "non proxy desc " + desc.getName());
passHandle = descHandle;
return desc;
@@ -1923,6 +1933,7 @@
String.format("invalid type code: %02X", tc));
}
passHandle = handles.assign(unshared ? unsharedMarker : str);
+ handles.describe(passHandle, "str " + str);
handles.finish(passHandle);
return str;
}
@@ -1987,6 +1998,7 @@
}
handles.finish(arrayHandle);
+ handles.describe(arrayHandle, "array of " + ccl);
passHandle = arrayHandle;
return array;
}
@@ -2030,6 +2042,7 @@
}
handles.finish(enumHandle);
+ handles.describe(enumHandle, "enum " + result);
passHandle = enumHandle;
return result;
}
@@ -2078,6 +2091,7 @@
readSerialData(obj, desc);
}
+ handles.describe(passHandle, "object " + obj.getClass());
handles.finish(passHandle);
if (obj != null &&
@@ -2831,6 +2845,8 @@
private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
/** char buffer for fast string reads */
private final char[] cbuf = new char[CHAR_BUF_SIZE];
+ /** dump */
+ private final PrintStream dump;
/** block data mode */
private boolean blkmode = false;
@@ -2852,9 +2868,13 @@
* Creates new BlockDataInputStream on top of given underlying stream.
* Block data mode is turned off by default.
*/
- BlockDataInputStream(InputStream in) {
+ BlockDataInputStream(InputStream in, PrintStream dump) {
this.in = new PeekInputStream(in);
+ this.dump = dump;
din = new DataInputStream(this);
+// if (dump != null) {
+// dump.println("// Start stream");
+// }
}
/**
@@ -2865,6 +2885,9 @@
* block data is still present in the stream.
*/
boolean setBlockDataMode(boolean newmode) throws IOException {
+// if (dump != null) {
+// dump.println("// blockmode " + newmode);
+// }
if (blkmode == newmode) {
return blkmode;
}
@@ -2893,6 +2916,9 @@
* mode, throws an IllegalStateException.
*/
void skipBlockData() throws IOException {
+// if (dump != null) {
+// dump.println("// skipBlockData");
+// }
if (!blkmode) {
throw new IllegalStateException("not in block data mode");
}
@@ -2932,6 +2958,10 @@
return HEADER_BLOCKED;
}
in.readFully(hbuf, 0, 2);
+ if (dump != null) {
+ dump.println("TC_BLOCKDATA");
+ dump.println(hbuf[1] & 0xFF);
+ }
return hbuf[1] & 0xFF;
case TC_BLOCKDATALONG:
@@ -2940,6 +2970,10 @@
}
in.readFully(hbuf, 0, 5);
int len = Bits.getInt(hbuf, 1);
+ if (dump != null) {
+ dump.println("TC_BLOCKDATALONG");
+ dump.println("i " + len);
+ }
if (len < 0) {
throw new StreamCorruptedException(
"illegal block data header length: " +
@@ -2954,6 +2988,9 @@
* reads may span data blocks separated by a TC_RESET.
*/
case TC_RESET:
+ if (dump != null) {
+ dump.println("TC_RESET");
+ }
in.read();
handleReset();
break;
@@ -2987,6 +3024,9 @@
if (unread > 0) {
int n =
in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
+ if (dump != null) {
+ dump.println("// refill " + n);
+ }
if (n >= 0) {
end = n;
unread -= n;
@@ -3065,6 +3105,7 @@
*/
public int read() throws IOException {
+ // no dump. called by others.
if (blkmode) {
if (pos == end) {
refill();
@@ -3076,10 +3117,16 @@
}
public int read(byte[] b, int off, int len) throws IOException {
+ if (dump != null) {
+ dump.println(">> read");
+ }
return read(b, off, len, false);
}
public long skip(long len) throws IOException {
+ if (dump != null) {
+ dump.println(">> skip");
+ }
long remain = len;
while (remain > 0) {
if (blkmode) {
@@ -3193,6 +3240,7 @@
public void readFully(byte[] b, int off, int len, boolean copy)
throws IOException
{
+ int oldOff = off;
while (len > 0) {
int n = read(b, off, len, copy);
if (n < 0) {
@@ -3201,9 +3249,20 @@
off += n;
len -= n;
}
+ if (dump != null && off != oldOff) {
+ StringBuilder sb = new StringBuilder("oct ");
+ for (int i = oldOff; i < off; i++) {
+ sb.append(hchars[(b[i]>>4)&0xf]);
+ sb.append(hchars[b[i]&0xf]);
+ }
+ dump.println(sb.toString());
+ }
}
public int skipBytes(int n) throws IOException {
+ if (dump != null) {
+ dump.println(">> skipBytes");
+ }
return din.skipBytes(n);
}
@@ -3212,6 +3271,9 @@
if (v < 0) {
throw new EOFException();
}
+ if (dump != null) {
+ dump.println(v != 0);
+ }
return (v != 0);
}
@@ -3220,6 +3282,31 @@
if (v < 0) {
throw new EOFException();
}
+ if (dump != null) {
+ boolean found = false;
+ try {
+ for (Field f : ObjectStreamConstants.class.getFields()) {
+ if (f.getType() == Byte.TYPE && f.getByte(null) == v) {
+ String n = f.getName();
+ if (n.equals("TC_BASE")) {
+ n = "TC_NULL";
+ }
+ dump.println(n);
+ found = true;
+ break;
+ }
+ }
+ } catch (Exception e) {
+ // ignored
+ }
+ if (!found) {
+ if (v > ' ' && v <= '~') {
+ dump.println("'" + (char)v + "'");
+ } else {
+ dump.println(v);
+ }
+ }
+ }
return (byte) v;
}
@@ -3228,6 +3315,9 @@
if (v < 0) {
throw new EOFException();
}
+ if (dump != null) {
+ dump.println(v);
+ }
return v;
}
@@ -3240,22 +3330,40 @@
}
char v = Bits.getChar(buf, pos);
pos += 2;
+ if (dump != null) {
+ dump.println("c " + (int)v);
+ }
return v;
}
public short readShort() throws IOException {
+ short v;
if (!blkmode) {
pos = 0;
in.readFully(buf, 0, 2);
+ v = Bits.getShort(buf, pos);
+ pos += 2;
} else if (end - pos < 2) {
- return din.readShort();
+ v = din.readShort();
+ } else {
+ v = Bits.getShort(buf, pos);
+ pos += 2;
}
- short v = Bits.getShort(buf, pos);
- pos += 2;
+ if (dump != null) {
+ if (v == STREAM_MAGIC) {
+ dump.println("STREAM_MAGIC");
+ } else {
+ dump.println("s " + v);
+ }
+ }
return v;
}
public int readUnsignedShort() throws IOException {
+ return readUnsignedShortInternal(false);
+ }
+
+ private int readUnsignedShortInternal(boolean silent) throws IOException {
if (!blkmode) {
pos = 0;
in.readFully(buf, 0, 2);
@@ -3264,10 +3372,29 @@
}
int v = Bits.getShort(buf, pos) & 0xFFFF;
pos += 2;
+ if (!silent && dump != null) {
+ dump.println("s " + v);
+ }
+ return v;
+ }
+
+ public int readHandle() throws IOException {
+ int v = readIntInternal() - baseWireHandle;
+ if (dump != null) {
+ dump.println("h " + v);
+ }
return v;
}
public int readInt() throws IOException {
+ int v = readIntInternal();
+ if (dump != null) {
+ dump.println("i " + v);
+ }
+ return v;
+ }
+
+ private int readIntInternal() throws IOException {
if (!blkmode) {
pos = 0;
in.readFully(buf, 0, 4);
@@ -3288,10 +3415,17 @@
}
float v = Bits.getFloat(buf, pos);
pos += 4;
+ if (dump != null) {
+ dump.println("f " + v);
+ }
return v;
}
public long readLong() throws IOException {
+ return readLongInternal(false);
+ }
+
+ public long readLongInternal(boolean silent) throws IOException {
if (!blkmode) {
pos = 0;
in.readFully(buf, 0, 8);
@@ -3300,6 +3434,9 @@
}
long v = Bits.getLong(buf, pos);
pos += 8;
+ if (!silent && dump != null) {
+ dump.println("l " + v);
+ }
return v;
}
@@ -3312,11 +3449,14 @@
}
double v = Bits.getDouble(buf, pos);
pos += 8;
+ if (dump != null) {
+ dump.println("d " + v);
+ }
return v;
}
public String readUTF() throws IOException {
- return readUTFBody(readUnsignedShort());
+ return readUTFBody(readUnsignedShortInternal(true));
}
@SuppressWarnings("deprecation")
@@ -3333,6 +3473,9 @@
*/
void readBooleans(boolean[] v, int off, int len) throws IOException {
+ if (dump != null) {
+ dump.println("// readBooleans");
+ }
int stop, endoff = off + len;
while (off < endoff) {
if (!blkmode) {
@@ -3341,19 +3484,30 @@
stop = off + span;
pos = 0;
} else if (end - pos < 1) {
- v[off++] = din.readBoolean();
+ boolean b = din.readBoolean();
+ if (dump != null) {
+ dump.println(b);
+ }
+ v[off++] = b;
continue;
} else {
stop = Math.min(endoff, off + end - pos);
}
while (off < stop) {
- v[off++] = Bits.getBoolean(buf, pos++);
+ boolean b = Bits.getBoolean(buf, pos++);
+ if (dump != null) {
+ dump.println(b);
+ }
+ v[off++] = b;
}
}
}
void readChars(char[] v, int off, int len) throws IOException {
+ if (dump != null) {
+ dump.println("// readChars");
+ }
int stop, endoff = off + len;
while (off < endoff) {
if (!blkmode) {
@@ -3362,20 +3516,31 @@
stop = off + span;
pos = 0;
} else if (end - pos < 2) {
- v[off++] = din.readChar();
+ char c = din.readChar();
+ if (dump != null) {
+ dump.println("c " + (int)c);
+ }
+ v[off++] = c;
continue;
} else {
stop = Math.min(endoff, off + ((end - pos) >> 1));
}
while (off < stop) {
- v[off++] = Bits.getChar(buf, pos);
+ char c = Bits.getChar(buf, pos);
+ if (dump != null) {
+ dump.println("c " + (int)c);
+ }
+ v[off++] = c;
pos += 2;
}
}
}
void readShorts(short[] v, int off, int len) throws IOException {
+ if (dump != null) {
+ dump.println("// readShorts");
+ }
int stop, endoff = off + len;
while (off < endoff) {
if (!blkmode) {
@@ -3384,20 +3549,31 @@
stop = off + span;
pos = 0;
} else if (end - pos < 2) {
- v[off++] = din.readShort();
+ short s = din.readShort();
+ if (dump != null) {
+ dump.println("s " + s);
+ }
+ v[off++] = s;
continue;
} else {
stop = Math.min(endoff, off + ((end - pos) >> 1));
}
while (off < stop) {
- v[off++] = Bits.getShort(buf, pos);
+ short s = Bits.getShort(buf, pos);
+ if (dump != null) {
+ dump.println("s " + s);
+ }
+ v[off++] = s;
pos += 2;
}
}
}
void readInts(int[] v, int off, int len) throws IOException {
+ if (dump != null) {
+ dump.println("// readInts");
+ }
int stop, endoff = off + len;
while (off < endoff) {
if (!blkmode) {
@@ -3406,20 +3582,31 @@
stop = off + span;
pos = 0;
} else if (end - pos < 4) {
- v[off++] = din.readInt();
+ int i = din.readInt();
+ if (dump != null) {
+ dump.println("i " + i);
+ }
+ v[off++] = i;
continue;
} else {
stop = Math.min(endoff, off + ((end - pos) >> 2));
}
while (off < stop) {
- v[off++] = Bits.getInt(buf, pos);
+ int i = Bits.getInt(buf, pos);
+ if (dump != null) {
+ dump.println("i " + i);
+ }
+ v[off++] = i;
pos += 4;
}
}
}
void readFloats(float[] v, int off, int len) throws IOException {
+ if (dump != null) {
+ dump.println("// readFloats");
+ }
int span, endoff = off + len;
while (off < endoff) {
if (!blkmode) {
@@ -3427,19 +3614,31 @@
in.readFully(buf, 0, span << 2);
pos = 0;
} else if (end - pos < 4) {
- v[off++] = din.readFloat();
+ float f = din.readFloat();
+ if (dump != null) {
+ dump.println("f " + f);
+ }
+ v[off++] = f;
continue;
} else {
span = Math.min(endoff - off, ((end - pos) >> 2));
}
bytesToFloats(buf, pos, v, off, span);
+ if (dump != null) {
+ for (int i = 0; i < span; i++) {
+ dump.println("f " + v[off + i]);
+ }
+ }
off += span;
pos += span << 2;
}
}
void readLongs(long[] v, int off, int len) throws IOException {
+ if (dump != null) {
+ dump.println("// readLongs");
+ }
int stop, endoff = off + len;
while (off < endoff) {
if (!blkmode) {
@@ -3448,20 +3647,31 @@
stop = off + span;
pos = 0;
} else if (end - pos < 8) {
- v[off++] = din.readLong();
+ long l = din.readLong();
+ if (dump != null) {
+ dump.println("l " + l);
+ }
+ v[off++] = l;
continue;
} else {
stop = Math.min(endoff, off + ((end - pos) >> 3));
}
while (off < stop) {
- v[off++] = Bits.getLong(buf, pos);
+ long l = Bits.getLong(buf, pos);
+ if (dump != null) {
+ dump.println("l " + l);
+ }
+ v[off++] = l;
pos += 8;
}
}
}
void readDoubles(double[] v, int off, int len) throws IOException {
+ if (dump != null) {
+ dump.println("// readDoubles");
+ }
int span, endoff = off + len;
while (off < endoff) {
if (!blkmode) {
@@ -3469,13 +3679,22 @@
in.readFully(buf, 0, span << 3);
pos = 0;
} else if (end - pos < 8) {
- v[off++] = din.readDouble();
+ double d = din.readDouble();
+ if (dump != null) {
+ dump.println("d " + d);
+ }
+ v[off++] = d;
continue;
} else {
span = Math.min(endoff - off, ((end - pos) >> 3));
}
bytesToDoubles(buf, pos, v, off, span);
+ if (dump != null) {
+ for (int i = 0; i < span; i++) {
+ dump.println("d " + v[off + i]);
+ }
+ }
off += span;
pos += span << 3;
}
@@ -3487,7 +3706,7 @@
* (instead of the standard 2 bytes) to convey the UTF encoding length.
*/
String readLongUTF() throws IOException {
- return readUTFBody(readLong());
+ return readUTFBody(readLongInternal(true));
}
/**
@@ -3529,7 +3748,11 @@
}
}
- return sbuf.toString();
+ String s = sbuf.toString();
+ if (dump != null) {
+ dump.println("\"" + s + "\"");
+ }
+ return s;
}
/**
@@ -3723,13 +3946,17 @@
/** number of handles in table */
int size = 0;
+ /** dump */
+ final PrintStream dump;
+
/**
* Creates handle table with the given initial capacity.
*/
- HandleTable(int initialCapacity) {
+ HandleTable(int initialCapacity, PrintStream d) {
status = new byte[initialCapacity];
entries = new Object[initialCapacity];
deps = new HandleList[initialCapacity];
+ dump = d;
}
/**
@@ -3747,6 +3974,12 @@
return size++;
}
+ void describe(int n, String label) {
+ if (dump != null) {
+ dump.printf("// handle %d assigned to %s\n", n, label);
+ }
+ }
+
/**
* Registers a dependency (in exception status) of one handle on
* another. The dependent handle must be "open" (i.e., assigned, but
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.ObjectStreamClass;
import java.io.ObjectStreamConstants;
import java.lang.reflect.Field;
// This class assembles a serialization description into a byte blob.
// "//" comment can appear anywhere (hopefully not in a string);
// A line can be "string" or 'A' (byte);
// or a number as "type number", type can be 1st char of char, short, int,
// long, float, or double, number can be hex, long can end with 'l';
// or "oct hex" for a binary blob;
// or "svuid" means serialVersionUID of the string above;
// or "h handle" where handle is a number;
// or a ObjectStreamConstants constant;
// or "true", or "false";
// or a byte.
//
// Attention: if you want to use "h number", all "nh" must be provided,
// This tool does not support auto handle counting (yet).
public class SerialASM {
static void codi(String f, String v) {
StringBuilder sb = new StringBuilder(" dos.");
sb.append(f).append('(');
if (f.equals("writeUTF")) {
sb.append('"');
}
sb.append(v);
if (f.equals("writeLong") && (!v.endsWith("l") && !v.endsWith("L"))) {
sb.append('L');
}
if (f.equals("writeUTF")) {
sb.append('"');
}
sb.append(");\n");
System.out.print(sb.toString());
}
public static void main(String[] args) throws Exception {
boolean code = args.length == 1 && args[0].equals("-c");
if (code) {
System.out.println("import java.io.*;\n"
+ "\n"
+ "public class App implements ObjectStreamConstants {\n"
+ "\n"
+ " static byte[] hex(String in) {\n"
+ " int len = in.length()/2;\n"
+ " byte[] out = new byte[len];\n"
+ " for (int i=0; i<len; i++) {\n"
+ " out[i] = (byte)Integer.parseInt(in.substring(i*2, i*2+2), 16);\n"
+ " }\n"
+ " return out;\n"
+ " }\n"
+ "\n"
+ " public static void main(String[] args) throws Exception {\n"
+ " ByteArrayOutputStream baos = new ByteArrayOutputStream();\n"
+ " DataOutputStream dos = new DataOutputStream(baos);\n");
}
try (DataOutputStream dos = code ? null : new DataOutputStream(System.out);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
String lastString = null;
while (true) {
String s = br.readLine();
if (s == null) {
break;
}
int pos = s.indexOf("//");
if (pos >= 0) {
s = s.substring(0, pos);
}
s = s.trim();
if (s.isEmpty()) {
continue;
}
char h = s.charAt(0);
if (h == '\'') {
if (code) {
codi("writeByte", "" + (int)s.charAt(1));
} else {
dos.writeByte(s.charAt(1));
}
} else if (h == '"') {
lastString = s.substring(1, s.length() - 1);
if (code) {
codi("writeUTF", lastString);
} else {
dos.writeUTF(lastString);
}
} else {
String[] pair = s.split(" ", 2);
String k = pair[0];
String v = pair.length == 2 ? pair[1] : pair[0];
int radix = 10;
String oldv = v;
if (v.startsWith("0x") || v.startsWith("0X")) {
v = v.substring(2);
radix = 16;
}
switch (k) {
case "c":
if (code) {
codi("writeChar", oldv);
} else {
dos.writeChar(Short.parseShort(v, radix));
}
break;
case "s":
if (code) {
codi("writeShort", oldv);
} else {
dos.writeShort(Short.parseShort(v, radix));
}
break;
case "i":
if (code) {
codi("writeInt", oldv);
} else {
dos.writeInt(Integer.parseInt(v, radix));
}
break;
case "h":
if (code) {
codi("writeInt", "ObjectStreamConstants.baseWireHandle + " + oldv);
} else {
dos.writeInt(ObjectStreamConstants.baseWireHandle
+ Integer.parseInt(v, radix));
}
break;
case "l":
if (v.endsWith("l") || v.endsWith("L")) {
v = v.substring(0, v.length() - 1);
}
if (code) {
codi("writeLong", oldv);
} else {
dos.writeLong(Long.parseLong(v, radix));
}
break;
case "f":
if (code) {
codi("writeFloat", v);
} else {
dos.writeFloat(Float.parseFloat(v));
}
break;
case "d":
if (code) {
codi("writeDouble", oldv);
} else {
dos.writeDouble(Double.parseDouble(v));
}
break;
case "oct":
if (code) {
codi("write", "hex(\"" + v + "\")");
} else {
dos.write(xeh(v));
}
break;
case "true":
case "false":
if (code) {
codi("writeBoolean", v);
} else {
dos.writeBoolean(v.equals("true"));
}
break;
case "svuid":
Class<?> cl = Class.forName(lastString, false, null);
ObjectStreamClass desc = ObjectStreamClass.lookup(cl);
if (desc != null) {
if (code) {
codi("writeLong", "" + desc.getSerialVersionUID());
} else {
dos.writeLong(desc.getSerialVersionUID());
}
} else {
throw new Exception("svuid for " + lastString);
}
break;
default:
if (pair.length == 2) {
throw new Exception("Unknown " + s);
}
if (Character.isDigit(h)) {
if (code) {
codi("writeByte", oldv);
} else {
dos.writeByte(Byte.parseByte(v, radix));
}
} else {
Field f = ObjectStreamConstants.class.getField(s);
if (f.getType() == Byte.TYPE) {
if (code) {
codi("writeByte", s);
} else {
dos.writeByte(f.getByte(null));
}
} else if (f.getType() == Short.TYPE) {
if (code) {
codi("writeShort", s);
} else {
dos.writeShort(f.getShort(null));
}
} else {
throw new Exception("Const? " + s);
}
}
}
}
}
}
if (code) {
System.out.println("\n"
+ " System.out.write(baos.toByteArray());\n"
+ " }\n"
+ "}\n");
System.out.flush();
}
}
static byte[] xeh(String in) {
int len = in.length()/2;
byte[] out = new byte[len];
for (int i=0; i<len; i++) {
out[i] = (byte)Integer.parseInt(in.substring(i*2, i*2+2), 16);
}
return out;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment