Projects
home:dingli:branches:openEuler:24.09-openjdk
openjdk-11
_service:tar_scm:fast-serializer-jdk11.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:fast-serializer-jdk11.patch of Package openjdk-11
From ad916087e4c2f096791bac009a74c10862d6c0d6 Mon Sep 17 00:00:00 2001 From: miaomiao <miaomiao@miaomiaos-MacBook-Pro.local> Date: Wed, 21 Sep 2022 10:16:33 +0800 Subject: [PATCH] test3 --- src/hotspot/share/prims/unsafe.cpp | 9 +- src/hotspot/share/runtime/globals.hpp | 4 + .../classes/java/io/ObjectInputStream.java | 173 ++++++++++++++---- .../classes/java/io/ObjectOutputStream.java | 44 ++++- .../classes/java/io/ObjectStreamClass.java | 47 +++++ .../java/io/ObjectStreamConstants.java | 5 + .../classes/jdk/internal/misc/Unsafe.java | 2 +- 7 files changed, 241 insertions(+), 43 deletions(-) diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp index db5959405..7f2319bae 100644 --- a/src/hotspot/share/prims/unsafe.cpp +++ b/src/hotspot/share/prims/unsafe.cpp @@ -1007,6 +1007,10 @@ UNSAFE_ENTRY(jint, Unsafe_GetLoadAverage0(JNIEnv *env, jobject unsafe, jdoubleAr return ret; } UNSAFE_END +UNSAFE_ENTRY(jboolean, Unsafe_GetUseFastSerializer(JNIEnv *env, jobject unsafe)) { + return UseFastSerializer; +} +UNSAFE_END /// JVM_RegisterUnsafeMethods @@ -1091,7 +1095,10 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "fullFence", CC "()V", FN_PTR(Unsafe_FullFence)}, {CC "isBigEndian0", CC "()Z", FN_PTR(Unsafe_isBigEndian0)}, - {CC "unalignedAccess0", CC "()Z", FN_PTR(Unsafe_unalignedAccess0)} + {CC "unalignedAccess0", CC "()Z", FN_PTR(Unsafe_unalignedAccess0)}, + + {CC "getUseFastSerializer", CC "()Z", FN_PTR(Unsafe_GetUseFastSerializer)}, + }; #undef CC diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index a14477b80..f49edbe2a 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -2686,6 +2686,10 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); JFR_ONLY(product(ccstr, StartFlightRecording, NULL, \ "Start flight recording with options")) \ \ + experimental(bool, UseFastSerializer, false, \ + "Cache-based serialization.It is extremely fast, but it can only" \ + "be effective in certain scenarios.") \ + \ experimental(bool, UseFastUnorderedTimeStamps, false, \ "Use platform unstable time where supported for timestamps only") diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 02346fac8..996b6fe67 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -38,6 +38,7 @@ import java.security.PrivilegedExceptionAction; import java.util.Arrays; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; import jdk.internal.misc.SharedSecrets; import jdk.internal.event.DeserializationEvent; @@ -327,6 +328,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. @@ -340,6 +344,25 @@ 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(); + /** * Creates an ObjectInputStream that reads from the specified InputStream. * A serialization stream header is read from the stream and verified. @@ -417,6 +440,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 @@ -705,11 +731,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 @@ -748,16 +783,26 @@ public class ObjectInputStream throws IOException, ClassNotFoundException { String name = desc.getName(); - try { - return Class.forName(name, false, latestUserDefinedLoader()); - } catch (ClassNotFoundException ex) { - Class<?> cl = primClasses.get(name); + Class<?> cl = null; + + if (useFastSerializer) { + cl = nameToClass.get(name); if (cl != null) { return cl; - } else { + } + } try { + cl = Class.forName(name, false, latestUserDefinedLoader()); + } catch (ClassNotFoundException ex) { + cl = primClasses.get(name); + if (cl == null) { throw ex; } } + if (useFastSerializer) { + nameToClass.put(name, cl); + } + + return cl; } /** @@ -931,9 +976,25 @@ 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", 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; + } + } else if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) { + throw new StreamCorruptedException( + String.format("invalid stream header: %04X%04X", s0, s1)); } } @@ -947,6 +1008,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 @@ -957,6 +1023,29 @@ 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) { + // This desc is localDesc. It may be different from the descriptor + // obtained from the stream. + 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; @@ -2014,36 +2103,52 @@ public class ObjectInputStream skipCustomData(); - try { - totalObjectRefs++; - depth++; - desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false)); + totalObjectRefs++; + depth++; - 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; + 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); + // 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--; } - } finally { - depth--; } handles.finish(descHandle); @@ -2942,8 +3047,6 @@ public class ObjectInputStream } } - private static final Unsafe UNSAFE = Unsafe.getUnsafe(); - /** * Performs a "freeze" action, required to adhere to final field semantics. * diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 99105f553..acaf76a71 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.StringJoiner; +import jdk.internal.misc.Unsafe; import sun.reflect.misc.ReflectUtil; /** @@ -188,7 +189,6 @@ public class ObjectOutputStream private final boolean enableOverride; /** if true, invoke replaceObject() */ private boolean enableReplace; - // values below valid only during upcalls to writeObject()/writeExternal() /** * Context during upcalls to class-defined writeObject methods; holds @@ -211,6 +211,14 @@ public class ObjectOutputStream new sun.security.action.GetBooleanAction( "sun.io.serialization.extendedDebugInfo")).booleanValue(); + 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(); + /** * Creates an ObjectOutputStream that writes to the specified OutputStream. * This constructor writes the serialization stream header to the @@ -324,6 +332,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 @@ -632,7 +643,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); } @@ -647,6 +662,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 @@ -664,7 +682,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); + } } /** @@ -1268,7 +1293,13 @@ public class ObjectOutputStream 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); } @@ -1281,8 +1312,9 @@ public class ObjectOutputStream annotateClass(cl); bout.setBlockDataMode(false); bout.writeByte(TC_ENDBLOCKDATA); - - writeClassDesc(desc.getSuperDesc(), false); + if (!useFastSerializer) { + writeClassDesc(desc.getSuperDesc(), false); + } } /** diff --git a/src/java.base/share/classes/java/io/ObjectStreamClass.java b/src/java.base/share/classes/java/io/ObjectStreamClass.java index 1f7647bac..8db60cc96 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -431,6 +431,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. */ @@ -617,6 +626,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/src/java.base/share/classes/java/io/ObjectStreamConstants.java b/src/java.base/share/classes/java/io/ObjectStreamConstants.java index 43a480ce4..96157782a 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamConstants.java +++ b/src/java.base/share/classes/java/io/ObjectStreamConstants.java @@ -38,6 +38,11 @@ public interface ObjectStreamConstants { */ static final short STREAM_MAGIC = (short)0xaced; + /** + * Magic number that is written to the stream header when using fastserilizer. + */ + static final short STREAM_MAGIC_FAST = (short)0xdeca; + /** * Version number that is written to the stream header. */ diff --git a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index 031b5aae5..d78caabdc 100644 --- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -3703,7 +3703,7 @@ public final class Unsafe { private static long convEndian(boolean big, long n) { return big == BE ? n : Long.reverseBytes(n) ; } - + public native boolean getUseFastSerializer(); private native long allocateMemory0(long bytes); private native long reallocateMemory0(long address, long bytes); private native void freeMemory0(long address); -- 2.30.1 (Apple Git-130)
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2