1 Star 0 Fork 81

Alex Gao/openjdk-1.8.0

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
fast-serializer-jdk8.patch 30.58 KB
一键复制 编辑 原始数据 按行查看 历史
eapen 提交于 2022-02-10 17:08 . I4T6FD: upgrade to 8u322-06(ga)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
commit 3ece3b6a87e4bf61a1f786c12d796012becce313
Date: Thu May 28 10:30:20 2020 +0800
Add FastSerializer
Summary:<core-libs>: Add FastSerializer
LLT: jtreg
Bug url: NA
diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp
index cdb72c0d5..d50041635 100644
--- a/hotspot/src/share/vm/prims/unsafe.cpp
+++ b/hotspot/src/share/vm/prims/unsafe.cpp
@@ -1361,6 +1361,10 @@ UNSAFE_ENTRY(void, Unsafe_PrefetchWrite(JNIEnv* env, jclass ignored, jobject obj
Prefetch::write(addr, (intx)offset);
UNSAFE_END
+UNSAFE_ENTRY(jboolean, Unsafe_GetUseFastSerializer(JNIEnv *env, jobject unsafe)) {
+ return UseFastSerializer;
+}
+UNSAFE_END
/// JVM_RegisterUnsafeMethods
@@ -1447,7 +1451,8 @@ static JNINativeMethod methods_140[] = {
{CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)},
{CC "monitorEnter", CC "(" OBJ ")V", FN_PTR(Unsafe_MonitorEnter)},
{CC "monitorExit", CC "(" OBJ ")V", FN_PTR(Unsafe_MonitorExit)},
- {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)}
+ {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)},
+ {CC "getUseFastSerializer", CC "()Z", FN_PTR(Unsafe_GetUseFastSerializer)}
};
// These are the methods prior to the JSR 166 changes in 1.5.0
@@ -1493,8 +1498,8 @@ static JNINativeMethod methods_141[] = {
{CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)},
{CC "monitorEnter", CC "(" OBJ ")V", FN_PTR(Unsafe_MonitorEnter)},
{CC "monitorExit", CC "(" OBJ ")V", FN_PTR(Unsafe_MonitorExit)},
- {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)}
-
+ {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)},
+ {CC "getUseFastSerializer", CC "()Z", FN_PTR(Unsafe_GetUseFastSerializer)}
};
// These are the methods prior to the JSR 166 changes in 1.6.0
@@ -1548,7 +1553,8 @@ static JNINativeMethod methods_15[] = {
{CC "compareAndSwapInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
{CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)},
{CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)},
- {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)}
+ {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)},
+ {CC "getUseFastSerializer", CC "()Z", FN_PTR(Unsafe_GetUseFastSerializer)}
};
@@ -1606,7 +1612,8 @@ static JNINativeMethod methods_16[] = {
{CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)},
{CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
{CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)},
- {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)}
+ {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)},
+ {CC "getUseFastSerializer", CC "()Z", FN_PTR(Unsafe_GetUseFastSerializer)}
};
// These are the methods for 1.8.0
@@ -1662,7 +1669,8 @@ static JNINativeMethod methods_18[] = {
{CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)},
{CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
{CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)},
- {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)}
+ {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)},
+ {CC "getUseFastSerializer", CC "()Z", FN_PTR(Unsafe_GetUseFastSerializer)}
};
JNINativeMethod loadavg_method[] = {
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index 2e6ff26ed..0a6ebfae1 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -553,6 +553,10 @@ class CommandLineFlags {
"Enable normal processing of flags relating to experimental " \
"features") \
\
+ experimental(bool, UseFastSerializer, false, \
+ "Cache-based serialization.It is extremely fast, but it can only" \
+ "be effective in certain scenarios.") \
+ \
product(bool, JavaMonitorsInStackTrace, true, \
"Print information about Java monitor locks when the stacks are" \
"dumped") \
diff --git a/jdk/src/share/classes/java/io/ObjectInputStream.java b/jdk/src/share/classes/java/io/ObjectInputStream.java
index 5d30f2a01..b67f01719 100644
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java
+++ b/jdk/src/share/classes/java/io/ObjectInputStream.java
@@ -52,6 +52,7 @@ import sun.misc.JavaOISAccess;
import sun.util.logging.PlatformLogger;
import sun.security.action.GetBooleanAction;
import sun.security.action.GetIntegerAction;
+import sun.misc.Unsafe;
/**
* An ObjectInputStream deserializes primitive data and objects previously
@@ -284,6 +285,22 @@ public class ObjectInputStream
traceLogger = (filterLog != null &&
filterLog.isLoggable(PlatformLogger.Level.FINER)) ? filterLog : null;
}
+
+ /*
+ * Logger for FastSerializer.
+ * Setup the FastSerializer logger if it is set to FINE
+ * (Assuming it will not change).
+ */
+ private static final PlatformLogger fastSerLogger;
+ static {
+ if (printFastSerializer) {
+ PlatformLogger fastSerLog = PlatformLogger.getLogger("fastSerializer");
+ fastSerLogger = (fastSerLog != null &&
+ fastSerLog.isLoggable(PlatformLogger.Level.FINE)) ? fastSerLog : null;
+ } else {
+ fastSerLogger = null;
+ }
+ }
}
/** filter stream for handling block data conversion */
@@ -312,6 +329,9 @@ public class ObjectInputStream
/** if true, invoke resolveObject() */
private boolean enableResolve;
+ /** Used to get the commandline option: useFastSerializer */
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
/**
* Context during upcalls to class-defined readObject methods; holds
* object currently being deserialized and descriptor for current class.
@@ -325,6 +345,38 @@ public class ObjectInputStream
*/
private ObjectInputFilter serialFilter;
+ /**
+ * value of "useFastSerializer" property
+ */
+ private static final boolean defaultFastSerializer = UNSAFE.getUseFastSerializer();
+
+ /**
+ * true or false for open FastSerilizer
+ * May be changed in readStreamHeader
+ */
+ private boolean useFastSerializer = defaultFastSerializer;
+
+ /**
+ * Value of "fastSerializerEscapeMode" property. It can be turned on
+ * when useFastSerializer is true.
+ */
+ private static final boolean fastSerializerEscapeMode = java.security.AccessController.doPrivileged(
+ new sun.security.action.GetBooleanAction(
+ "fastSerializerEscapeMode")).booleanValue();
+
+ /**
+ * value of "printFastSerializer" property,
+ * as true or false for printing FastSerializer logs.
+ */
+ private static final boolean printFastSerializer = java.security.AccessController.doPrivileged(
+ new sun.security.action.GetBooleanAction(
+ "printFastSerializer")).booleanValue();
+
+ /**
+ * Magic number that is written to the stream header when using fastserilizer.
+ */
+ private static final short STREAM_MAGIC_FAST = (short)0xdeca;
+
/**
* Creates an ObjectInputStream that reads from the specified InputStream.
* A serialization stream header is read from the stream and verified.
@@ -396,6 +443,9 @@ public class ObjectInputStream
* transitively so that a complete equivalent graph of objects is
* reconstructed by readObject.
*
+ * The difference between fastSerialzation and default serialization is the
+ * descriptor serialization. The data serialization is same with each other.
+ *
* <p>The root object is completely restored when all of its fields and the
* objects it references are completely restored. At this point the object
* validation callbacks are executed in order based on their registered
@@ -670,11 +720,20 @@ public class ObjectInputStream
vlist.register(obj, prio);
}
+ /**
+ * Cache the class meta during serialization.
+ * Only used in FastSerilizer.
+ */
+ protected static ConcurrentHashMap<String,Class<?>> nameToClass = new ConcurrentHashMap<>();
+
/**
* Load the local class equivalent of the specified stream class
* description. Subclasses may implement this method to allow classes to
* be fetched from an alternate source.
*
+ * When fastSerializer is turned on, fields of desc will be null except
+ * name. When resolveClass is override, this may cause null pointer exception.
+ *
* <p>The corresponding method in <code>ObjectOutputStream</code> is
* <code>annotateClass</code>. This method will be invoked only once for
* each unique class in the stream. This method can be implemented by
@@ -715,16 +774,27 @@ public class ObjectInputStream
throws IOException, ClassNotFoundException
{
String name = desc.getName();
+ Class<?> cl = null;
+
+ if (useFastSerializer) {
+ cl = nameToClass.get(name);
+ if (cl != null) {
+ return cl;
+ }
+ }
try {
- return Class.forName(name, false, latestUserDefinedLoader());
+ cl = Class.forName(name, false, latestUserDefinedLoader());
} catch (ClassNotFoundException ex) {
- Class<?> cl = primClasses.get(name);
- if (cl != null) {
- return cl;
- } else {
+ cl = primClasses.get(name);
+ if (cl == null) {
throw ex;
}
}
+ if (useFastSerializer) {
+ nameToClass.put(name, cl);
+ }
+
+ return cl;
}
/**
@@ -894,9 +964,34 @@ public class ObjectInputStream
{
short s0 = bin.readShort();
short s1 = bin.readShort();
- if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
- throw new StreamCorruptedException(
- String.format("invalid stream header: %04X%04X", s0, s1));
+ if (useFastSerializer) {
+ if (s0 != STREAM_MAGIC_FAST || s1 != STREAM_VERSION) {
+
+ if (s0 != STREAM_MAGIC) {
+ throw new StreamCorruptedException(
+ String.format("invalid stream header: %04X%04X, and FastSerializer is activated", s0, s1));
+ }
+
+ if (!fastSerializerEscapeMode) {
+ throw new StreamCorruptedException(
+ String.format("invalid stream header: %04X%04X.Fast serialization does not support " +
+ "original serialized files", s0, s1));
+ }
+
+ // Escape to default serialization
+ useFastSerializer = false;
+ if (Logging.fastSerLogger != null) {
+ Logging.fastSerLogger.fine("[Deserialize]: Escape and disable FastSerializer");
+ }
+ }
+ } else if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
+ if (s0 == STREAM_MAGIC_FAST && s1 == STREAM_VERSION) {
+ throw new StreamCorruptedException(
+ String.format("invalid stream header: %04X%04X, and it is a FastSerializer stream", s0, s1));
+ } else {
+ throw new StreamCorruptedException(
+ String.format("invalid stream header: %04X%04X", s0, s1));
+ }
}
}
@@ -910,6 +1005,11 @@ public class ObjectInputStream
* this method reads class descriptors according to the format defined in
* the Object Serialization specification.
*
+ * In fastSerialize mode, the descriptor is obtained by lookup method. And
+ * the resolveClass method is called here to get the classmeta. Since the
+ * descriptor is obtained by lookup, the descriptor is same as localdesc.
+ * So we cann't distinguish the receiver desc and local desc.
+ *
* @return the class descriptor read
* @throws IOException If an I/O error has occurred.
* @throws ClassNotFoundException If the Class of a serialized object used
@@ -920,6 +1020,27 @@ public class ObjectInputStream
protected ObjectStreamClass readClassDescriptor()
throws IOException, ClassNotFoundException
{
+ // fastSerializer
+ if (useFastSerializer) {
+ String name = readUTF();
+ Class<?> cl = null;
+ ObjectStreamClass desc = new ObjectStreamClass(name);
+ try {
+ // In order to match this method, we add an annotateClass method in
+ // writeClassDescriptor.
+ cl = resolveClass(desc);
+ } catch (ClassNotFoundException ex) {
+ // resolveClass is just used to obtain Class which required by lookup method
+ // and it will be called again later, so we don't throw ClassNotFoundException here.
+ return desc;
+ }
+ if (cl != null) {
+ desc = ObjectStreamClass.lookup(cl, true);
+ }
+ return desc;
+ }
+
+ // Default deserialization. If the Class cannot be found, throw ClassNotFoundException.
ObjectStreamClass desc = new ObjectStreamClass();
desc.readNonProxy(this);
return desc;
@@ -1996,41 +2090,64 @@ private ObjectStreamClass readNonProxyDesc(boolean unshared)
skipCustomData();
- try {
- totalObjectRefs++;
- depth++;
- desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
-
- if (cl != null) {
- // Check that serial filtering has been done on the local class descriptor's superclass,
- // in case it does not appear in the stream.
-
- // Find the next super descriptor that has a local class descriptor.
- // Descriptors for which there is no local class are ignored.
- ObjectStreamClass superLocal = null;
- for (ObjectStreamClass sDesc = desc.getSuperDesc(); sDesc != null; sDesc = sDesc.getSuperDesc()) {
- if ((superLocal = sDesc.getLocalDesc()) != null) {
- break;
- }
- }
-
- // Scan local descriptor superclasses for a match with the local descriptor of the super found above.
- // For each super descriptor before the match, invoke the serial filter on the class.
- // The filter is invoked for each class that has not already been filtered
- // but would be filtered if the instance had been serialized by this Java runtime.
- for (ObjectStreamClass lDesc = desc.getLocalDesc().getSuperDesc();
- lDesc != null && lDesc != superLocal;
- lDesc = lDesc.getSuperDesc()) {
- filterCheck(lDesc.forClass(), -1);
- }
- }
- } finally {
- depth--;
+ totalObjectRefs++;
+ depth++;
+
+ if (useFastSerializer) {
+ desc.initNonProxyFast(readDesc, resolveEx);
+ ObjectStreamClass superDesc = desc.getSuperDesc();
+ long originDepth = depth - 1;
+ // Since desc is obtained from the lookup method, we will lose the depth and
+ // totalObjectRefs of superDesc. So we add a loop here to compute the depth
+ // and objectRef of superDesc.
+ while (superDesc != null && superDesc.forClass() != null) {
+ filterCheck(superDesc.forClass(), -1);
+ superDesc = superDesc.getSuperDesc();
+ totalObjectRefs++;
+ depth++;
+ }
+ depth = originDepth;
+ } else {
+ try {
+ desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
+
+ if (cl != null) {
+ // Check that serial filtering has been done on the local class descriptor's superclass,
+ // in case it does not appear in the stream.
+
+ // Find the next super descriptor that has a local class descriptor.
+ // Descriptors for which there is no local class are ignored.
+ ObjectStreamClass superLocal = null;
+ for (ObjectStreamClass sDesc = desc.getSuperDesc(); sDesc != null; sDesc = sDesc.getSuperDesc()) {
+ if ((superLocal = sDesc.getLocalDesc()) != null) {
+ break;
+ }
+ }
+
+ // Scan local descriptor superclasses for a match with the local descriptor of the super found above.
+ // For each super descriptor before the match, invoke the serial filter on the class.
+ // The filter is invoked for each class that has not already been filtered
+ // but would be filtered if the instance had been serialized by this Java runtime.
+ for (ObjectStreamClass lDesc = desc.getLocalDesc().getSuperDesc();
+ lDesc != null && lDesc != superLocal;
+ lDesc = lDesc.getSuperDesc()) {
+ filterCheck(lDesc.forClass(), -1);
+ }
+ }
+ } finally {
+ depth--;
+ }
}
handles.finish(descHandle);
passHandle = descHandle;
+ if (Logging.fastSerLogger != null) {
+ Logging.fastSerLogger.fine(
+ "[Deserialize] useFastSerializer:{0}, Class name:{1}, SerialVersionUID:{2}, flags:{3}",
+ useFastSerializer, desc.getName(), desc.getSerialVersionUID(), desc.getFlags(this));
+ }
+
return desc;
}
@@ -2334,21 +2478,25 @@ public class ObjectInputStream
desc.setPrimFieldValues(obj, primVals);
}
- int objHandle = passHandle;
- ObjectStreamField[] fields = desc.getFields(false);
- Object[] objVals = new Object[desc.getNumObjFields()];
- int numPrimFields = fields.length - objVals.length;
- for (int i = 0; i < objVals.length; i++) {
- ObjectStreamField f = fields[numPrimFields + i];
- objVals[i] = readObject0(Object.class, f.isUnshared());
- if (f.getField() != null) {
- handles.markDependency(objHandle, passHandle);
+ Object[] objVals = null;
+ int numObjFields = desc.getNumObjFields();
+ if (numObjFields > 0) {
+ int objHandle = passHandle;
+ ObjectStreamField[] fields = desc.getFields(false);
+ 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(Object.class, f.isUnshared());
+ if (f.getField() != null) {
+ handles.markDependency(objHandle, passHandle);
+ }
}
+ if (obj != null) {
+ desc.setObjFieldValues(obj, objVals);
+ }
+ passHandle = objHandle;
}
- if (obj != null) {
- desc.setObjFieldValues(obj, objVals);
- }
- passHandle = objHandle;
}
/**
diff --git a/jdk/src/share/classes/java/io/ObjectOutputStream.java b/jdk/src/share/classes/java/io/ObjectOutputStream.java
index 6d29e3a1f..3890efc3e 100644
--- a/jdk/src/share/classes/java/io/ObjectOutputStream.java
+++ b/jdk/src/share/classes/java/io/ObjectOutputStream.java
@@ -37,6 +37,8 @@ import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue;
import java.io.SerialCallbackContext;
import sun.reflect.misc.ReflectUtil;
+import sun.misc.Unsafe;
+import sun.util.logging.PlatformLogger;
/**
* An ObjectOutputStream writes primitive data types and graphs of Java objects
@@ -173,6 +175,24 @@ public class ObjectOutputStream
new ReferenceQueue<>();
}
+ private static class Logging {
+ /*
+ * Logger for FastSerializer.
+ * Setup the FastSerializer logger if it is set to FINE.
+ * (Assuming it will not change).
+ */
+ static final PlatformLogger fastSerLogger;
+ static {
+ if (printFastSerializer) {
+ PlatformLogger fastSerLog = PlatformLogger.getLogger("fastSerializer");
+ fastSerLogger = (fastSerLog != null &&
+ fastSerLog.isLoggable(PlatformLogger.Level.FINE)) ? fastSerLog : null;
+ } else {
+ fastSerLogger = null;
+ }
+ }
+ }
+
/** filter stream for handling block data conversion */
private final BlockDataOutputStream bout;
/** obj -> wire handle map */
@@ -214,6 +234,27 @@ public class ObjectOutputStream
new sun.security.action.GetBooleanAction(
"sun.io.serialization.extendedDebugInfo")).booleanValue();
+ /**
+ * Magic number that is written to the stream header when using fastserilizer.
+ */
+ private static final short STREAM_MAGIC_FAST = (short)0xdeca;
+
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
+ /**
+ * Value of "UseFastSerializer" property. The fastSerializer is turned
+ * on when it is true.
+ */
+ private static final boolean useFastSerializer = UNSAFE.getUseFastSerializer();
+
+ /**
+ * value of "printFastSerializer" property,
+ * as true or false for printing FastSerializer logs.
+ */
+ private static final boolean printFastSerializer = java.security.AccessController.doPrivileged(
+ new sun.security.action.GetBooleanAction(
+ "printFastSerializer")).booleanValue();
+
/**
* Creates an ObjectOutputStream that writes to the specified OutputStream.
* This constructor writes the serialization stream header to the
@@ -327,6 +363,9 @@ public class ObjectOutputStream
* object are written transitively so that a complete equivalent graph of
* objects can be reconstructed by an ObjectInputStream.
*
+ * The difference between fastSerialzation and default serialization is the
+ * descriptor serialization. The data serialization is same with each other.
+ *
* <p>Exceptions are thrown for problems with the OutputStream and for
* classes that should not be serialized. All exceptions are fatal to the
* OutputStream, which is left in an indeterminate state, and it is up to
@@ -633,7 +672,11 @@ public class ObjectOutputStream
* stream
*/
protected void writeStreamHeader() throws IOException {
- bout.writeShort(STREAM_MAGIC);
+ if (useFastSerializer) {
+ bout.writeShort(STREAM_MAGIC_FAST);
+ } else {
+ bout.writeShort(STREAM_MAGIC);
+ }
bout.writeShort(STREAM_VERSION);
}
@@ -648,6 +691,9 @@ public class ObjectOutputStream
* By default, this method writes class descriptors according to the format
* defined in the Object Serialization specification.
*
+ * In fastSerializer mode, we will only write the classname to the stream.
+ * The annotateClass is used to match the resolveClass in readClassDescriptor.
+ *
* <p>Note that this method will only be called if the ObjectOutputStream
* is not using the old serialization stream format (set by calling
* ObjectOutputStream's <code>useProtocolVersion</code> method). If this
@@ -665,7 +711,14 @@ public class ObjectOutputStream
protected void writeClassDescriptor(ObjectStreamClass desc)
throws IOException
{
- desc.writeNonProxy(this);
+ if (useFastSerializer) {
+ writeUTF(desc.getName());
+ // The annotateClass is used to match the resolveClass called in
+ // readClassDescriptor.
+ annotateClass(desc.forClass());
+ } else {
+ desc.writeNonProxy(this);
+ }
}
/**
@@ -1275,9 +1328,21 @@ public class ObjectOutputStream
bout.writeByte(TC_CLASSDESC);
handles.assign(unshared ? null : desc);
+ if (Logging.fastSerLogger != null) {
+ Logging.fastSerLogger.fine(
+ "[Serialize] useFastSerializer:{0}, Class name:{1}, SerialVersionUID:{2}, flags:{3}, protocol:{4}",
+ useFastSerializer, desc.getName(), desc.getSerialVersionUID(), desc.getFlags(this), protocol);
+ }
+
if (protocol == PROTOCOL_VERSION_1) {
// do not invoke class descriptor write hook with old protocol
- desc.writeNonProxy(this);
+ if (useFastSerializer) {
+ // only write name and annotate class when using FastSerializer
+ writeUTF(desc.getName());
+ annotateClass(desc.forClass());
+ } else {
+ desc.writeNonProxy(this);
+ }
} else {
writeClassDescriptor(desc);
}
@@ -1291,7 +1356,9 @@ public class ObjectOutputStream
bout.setBlockDataMode(false);
bout.writeByte(TC_ENDBLOCKDATA);
- writeClassDesc(desc.getSuperDesc(), false);
+ if (!useFastSerializer) {
+ writeClassDesc(desc.getSuperDesc(), false);
+ }
}
/**
diff --git a/jdk/src/share/classes/java/io/ObjectStreamClass.java b/jdk/src/share/classes/java/io/ObjectStreamClass.java
index 64453b25a..fce3c3475 100644
--- a/jdk/src/share/classes/java/io/ObjectStreamClass.java
+++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java
@@ -280,6 +280,40 @@ public class ObjectStreamClass implements Serializable {
return suid.longValue();
}
+ /**
+ * Return the flags for this class described by this descriptor. The flags
+ * means a set of bit masks for ObjectStreamClass, which indicate the status
+ * of SC_WRITE_METHOD, SC_SERIALIZABLE, SC_EXTERNALIZABLE, SC_BLOCK_DATA and
+ * SC_ENUM.
+ *
+ * @param serialStream ObjectOutputStream or ObjectInputStream
+ *
+ * @return the flags for this class described by this descriptor
+ */
+ byte getFlags(Object serialStream) {
+ byte flags = 0;
+ if (externalizable) {
+ flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
+ if (serialStream instanceof ObjectOutputStream) {
+ int protocol = ((ObjectOutputStream)serialStream).getProtocolVersion();
+ if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {
+ flags |= ObjectStreamConstants.SC_BLOCK_DATA;
+ }
+ } else if (serialStream instanceof ObjectInputStream) {
+ flags |= ObjectStreamConstants.SC_BLOCK_DATA;
+ }
+ } else if (serializable) {
+ flags |= ObjectStreamConstants.SC_SERIALIZABLE;
+ }
+ if (hasWriteObjectData) {
+ flags |= ObjectStreamConstants.SC_WRITE_METHOD;
+ }
+ if (isEnum) {
+ flags |= ObjectStreamConstants.SC_ENUM;
+ }
+ return flags;
+ }
+
/**
* Return the class in the local VM that this version is mapped to. Null
* is returned if there is no corresponding local class.
@@ -570,6 +604,15 @@ public class ObjectStreamClass implements Serializable {
ObjectStreamClass() {
}
+ /**
+ * Create a blank class descriptor with name. It is only used
+ * in fastSerialize path.
+ * @param name class name
+ */
+ ObjectStreamClass(String name) {
+ this.name = name;
+ }
+
/**
* Creates a PermissionDomain that grants no permission.
*/
@@ -756,6 +799,44 @@ public class ObjectStreamClass implements Serializable {
initialized = true;
}
+ /**
+ * Initializes class descriptor representing a non-proxy class.
+ * Used in fast serialization mode.
+ */
+ void initNonProxyFast(ObjectStreamClass model,
+ ClassNotFoundException resolveEx)
+ {
+ this.cl = model.cl;
+ this.resolveEx = resolveEx;
+ this.superDesc = model.superDesc;
+ name = model.name;
+ this.suid = model.suid;
+ isProxy = false;
+ isEnum = model.isEnum;
+ serializable = model.serializable;
+ externalizable = model.externalizable;
+ hasBlockExternalData = model.hasBlockExternalData;
+ hasWriteObjectData = model.hasWriteObjectData;
+ fields = model.fields;
+ primDataSize = model.primDataSize;
+ numObjFields = model.numObjFields;
+
+ writeObjectMethod = model.writeObjectMethod;
+ readObjectMethod = model.readObjectMethod;
+ readObjectNoDataMethod = model.readObjectNoDataMethod;
+ writeReplaceMethod = model.writeReplaceMethod;
+ readResolveMethod = model.readResolveMethod;
+ if (deserializeEx == null) {
+ deserializeEx = model.deserializeEx;
+ }
+ domains = model.domains;
+ cons = model.cons;
+ fieldRefl = model.fieldRefl;
+ localDesc = model;
+
+ initialized = true;
+ }
+
/**
* Reads non-proxy class descriptor information from given input stream.
* The resulting class descriptor is not fully functional; it can only be
diff --git a/jdk/src/share/classes/sun/misc/Unsafe.java b/jdk/src/share/classes/sun/misc/Unsafe.java
index 99e465802..92fb01669 100644
--- a/jdk/src/share/classes/sun/misc/Unsafe.java
+++ b/jdk/src/share/classes/sun/misc/Unsafe.java
@@ -433,6 +433,8 @@ public final class Unsafe {
/** @see #putByte(long, byte) */
public native void putDouble(long address, double x);
+ public native boolean getUseFastSerializer();
+
/**
* Fetches a native pointer from a given memory address. If the address is
* zero, or does not point into a block obtained from {@link
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/gaoxiang90/openjdk-1.8.0.git
git@gitee.com:gaoxiang90/openjdk-1.8.0.git
gaoxiang90
openjdk-1.8.0
openjdk-1.8.0
master

搜索帮助