src/share/classes/java/io/ObjectInputStream.java
Print this page
@@ -37,11 +37,10 @@
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicBoolean;
import static java.io.ObjectStreamClass.processQueue;
import sun.reflect.misc.ReflectUtil;
/**
* An ObjectInputStream deserializes primitive data and objects previously
@@ -532,11 +531,11 @@
{
SerialCallbackContext ctx = curContext;
if (ctx == null) {
throw new NotActiveException("not in call to readObject");
}
- Object curObj = ctx.getObj();
+ ctx.checkAndSetUsed();
ObjectStreamClass curDesc = ctx.getDesc();
bin.setBlockDataMode(false);
GetFieldImpl getField = new GetFieldImpl(curDesc);
getField.readFields();
bin.setBlockDataMode(true);
@@ -1595,11 +1594,11 @@
ObjectStreamClass desc = new ObjectStreamClass();
int descHandle = handles.assign(unshared ? unsharedMarker : desc);
passHandle = NULL_HANDLE;
- ObjectStreamClass readDesc = null;
+ ObjectStreamClass readDesc;
try {
readDesc = readClassDescriptor();
} catch (ClassNotFoundException ex) {
throw (IOException) new InvalidClassException(
"failed to read class descriptor").initCause(ex);
@@ -1974,21 +1973,25 @@
if (cl != null && obj != null && !cl.isInstance(obj)) {
throw new ClassCastException();
}
int primDataSize = desc.getPrimDataSize();
+ if (primDataSize > 0) {
if (primVals == null || primVals.length < primDataSize) {
primVals = new byte[primDataSize];
}
bin.readFully(primVals, 0, primDataSize, false);
if (obj != null) {
desc.setPrimFieldValues(obj, primVals);
}
+ }
+ int numObjFields = desc.getNumObjFields();
+ if (numObjFields > 0) {
int objHandle = passHandle;
ObjectStreamField[] fields = desc.getFields(false);
- Object[] objVals = new Object[desc.getNumObjFields()];
+ Object[] objVals = new Object[numObjFields];
int numPrimFields = fields.length - objVals.length;
for (int i = 0; i < objVals.length; i++) {
ObjectStreamField f = fields[numPrimFields + i];
objVals[i] = readObject0(f.isUnshared());
if (f.getField() != null) {
@@ -1998,10 +2001,11 @@
if (obj != null) {
desc.setObjFieldValues(obj, objVals);
}
passHandle = objHandle;
}
+ }
/**
* Reads in and returns IOException that caused serialization to abort.
* All stream state is discarded prior to reading in fatal exception. Sets
* passHandle to fatal exception's handle.
@@ -2375,12 +2379,16 @@
/** buffer for reading general/block data */
private final byte[] buf = new byte[MAX_BLOCK_SIZE];
/** buffer for reading block data headers */
private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
- /** char buffer for fast string reads */
+ /** char buffer for fast string reads - used by {@link #readUTFSpan(long)} */
private final char[] cbuf = new char[CHAR_BUF_SIZE];
+ /** shared string builder for less object allocations - used by
+ * {@link #readUTFBody(long)}, {@link #readUTFChar(long)} and
+ * {@link #readUTFSpan(long)} */
+ private final StringBuilder sbuf = new StringBuilder(CHAR_BUF_SIZE);
/** block data mode */
private boolean blkmode = false;
// block data state fields; values meaningful only when blkmode true
@@ -3042,23 +3050,23 @@
* Reads in the "body" (i.e., the UTF representation minus the 2-byte
* or 8-byte length header) of a UTF encoding, which occupies the next
* utflen bytes.
*/
private String readUTFBody(long utflen) throws IOException {
- StringBuilder sbuf = new StringBuilder();
if (!blkmode) {
end = pos = 0;
}
+ sbuf.setLength(0);
while (utflen > 0) {
int avail = end - pos;
if (avail >= 3 || (long) avail == utflen) {
- utflen -= readUTFSpan(sbuf, utflen);
+ utflen -= readUTFSpan(utflen);
} else {
if (blkmode) {
// near block boundary, read one byte at a time
- utflen -= readUTFChar(sbuf, utflen);
+ utflen -= readUTFChar(utflen);
} else {
// shift and refill buffer manually
if (avail > 0) {
System.arraycopy(buf, pos, buf, 0, avail);
}
@@ -3074,13 +3082,13 @@
/**
* Reads span of UTF-encoded characters out of internal buffer
* (starting at offset pos and ending at or before offset end),
* consuming no more than utflen bytes. Appends read characters to
- * sbuf. Returns the number of bytes consumed.
+ * {@link #sbuf}. Returns the number of bytes consumed.
*/
- private long readUTFSpan(StringBuilder sbuf, long utflen)
+ private long readUTFSpan(long utflen)
throws IOException
{
int cpos = 0;
int start = pos;
int avail = Math.min(end - pos, CHAR_BUF_SIZE);
@@ -3148,16 +3156,16 @@
return pos - start;
}
/**
* Reads in single UTF-encoded character one byte at a time, appends
- * the character to sbuf, and returns the number of bytes consumed.
+ * the character to {@link #sbuf}, and returns the number of bytes consumed.
* This method is used when reading in UTF strings written in block
* data mode to handle UTF-encoded characters which (potentially)
* straddle block-data boundaries.
*/
- private int readUTFChar(StringBuilder sbuf, long utflen)
+ private int readUTFChar(long utflen)
throws IOException
{
int b1, b2, b3;
b1 = readByte() & 0xFF;
switch (b1 >> 4) {