15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.io;
27
28 import java.lang.ref.Reference;
29 import java.lang.ref.ReferenceQueue;
30 import java.lang.ref.SoftReference;
31 import java.lang.ref.WeakReference;
32 import java.lang.reflect.Constructor;
33 import java.lang.reflect.Field;
34 import java.lang.reflect.InvocationTargetException;
35 import java.lang.reflect.Member;
36 import java.lang.reflect.Method;
37 import java.lang.reflect.Modifier;
38 import java.lang.reflect.Proxy;
39 import java.security.AccessController;
40 import java.security.MessageDigest;
41 import java.security.NoSuchAlgorithmException;
42 import java.security.PrivilegedAction;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collections;
46 import java.util.Comparator;
47 import java.util.HashSet;
48 import java.util.Set;
49 import java.util.concurrent.ConcurrentHashMap;
50 import java.util.concurrent.ConcurrentMap;
51 import sun.misc.Unsafe;
52 import sun.reflect.CallerSensitive;
53 import sun.reflect.Reflection;
54 import sun.reflect.ReflectionFactory;
55 import sun.reflect.misc.ReflectUtil;
56
57 /**
58 * Serialization's descriptor for classes. It contains the name and
59 * serialVersionUID of the class. The ObjectStreamClass for a specific class
60 * loaded in this Java VM can be found/created using the lookup method.
61 *
62 * <p>The algorithm to compute the SerialVersionUID is described in
63 * <a href="../../../platform/serialization/spec/class.html#4100">Object
64 * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
65 *
66 * @author Mike Warres
67 * @author Roger Riggs
68 * @see ObjectStreamField
69 * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
70 * @since JDK1.1
156 /** exception (if any) to throw if non-enum deserialization attempted */
157 private ExceptionInfo deserializeEx;
158 /** exception (if any) to throw if non-enum serialization attempted */
159 private ExceptionInfo serializeEx;
160 /** exception (if any) to throw if default serialization attempted */
161 private ExceptionInfo defaultSerializeEx;
162
163 /** serializable fields */
164 private ObjectStreamField[] fields;
165 /** aggregate marshalled size of primitive fields */
166 private int primDataSize;
167 /** number of non-primitive fields */
168 private int numObjFields;
169 /** reflector for setting/getting serializable field values */
170 private FieldReflector fieldRefl;
171 /** data layout of serialized objects described by this class desc */
172 private volatile ClassDataSlot[] dataLayout;
173
174 /** serialization-appropriate constructor, or null if none */
175 private Constructor<?> cons;
176 /** class-defined writeObject method, or null if none */
177 private Method writeObjectMethod;
178 /** class-defined readObject method, or null if none */
179 private Method readObjectMethod;
180 /** class-defined readObjectNoData method, or null if none */
181 private Method readObjectNoDataMethod;
182 /** class-defined writeReplace method, or null if none */
183 private Method writeReplaceMethod;
184 /** class-defined readResolve method, or null if none */
185 private Method readResolveMethod;
186
187 /** local class descriptor for represented class (may point to self) */
188 private ObjectStreamClass localDesc;
189 /** superclass descriptor appearing in stream */
190 private ObjectStreamClass superDesc;
191
192 /** true if, and only if, the object has been correctly initialized */
193 private boolean initialized;
194
195 /**
488 } catch (InvalidClassException e) {
489 serializeEx = deserializeEx =
490 new ExceptionInfo(e.classname, e.getMessage());
491 fields = NO_FIELDS;
492 }
493
494 if (externalizable) {
495 cons = getExternalizableConstructor(cl);
496 } else {
497 cons = getSerializableConstructor(cl);
498 writeObjectMethod = getPrivateMethod(cl, "writeObject",
499 new Class<?>[] { ObjectOutputStream.class },
500 Void.TYPE);
501 readObjectMethod = getPrivateMethod(cl, "readObject",
502 new Class<?>[] { ObjectInputStream.class },
503 Void.TYPE);
504 readObjectNoDataMethod = getPrivateMethod(
505 cl, "readObjectNoData", null, Void.TYPE);
506 hasWriteObjectData = (writeObjectMethod != null);
507 }
508 writeReplaceMethod = getInheritableMethod(
509 cl, "writeReplace", null, Object.class);
510 readResolveMethod = getInheritableMethod(
511 cl, "readResolve", null, Object.class);
512 return null;
513 }
514 });
515 } else {
516 suid = Long.valueOf(0);
517 fields = NO_FIELDS;
518 }
519
520 try {
521 fieldRefl = getReflector(fields, this);
522 } catch (InvalidClassException ex) {
523 // field mismatches impossible when matching local fields vs. self
524 throw new InternalError(ex);
525 }
526
527 if (deserializeEx == null) {
531 deserializeEx = new ExceptionInfo(name, "no valid constructor");
532 }
533 }
534 for (int i = 0; i < fields.length; i++) {
535 if (fields[i].getField() == null) {
536 defaultSerializeEx = new ExceptionInfo(
537 name, "unmatched serializable field(s) declared");
538 }
539 }
540 initialized = true;
541 }
542
543 /**
544 * Creates blank class descriptor which should be initialized via a
545 * subsequent call to initProxy(), initNonProxy() or readNonProxy().
546 */
547 ObjectStreamClass() {
548 }
549
550 /**
551 * Initializes class descriptor representing a proxy class.
552 */
553 void initProxy(Class<?> cl,
554 ClassNotFoundException resolveEx,
555 ObjectStreamClass superDesc)
556 throws InvalidClassException
557 {
558 ObjectStreamClass osc = null;
559 if (cl != null) {
560 osc = lookup(cl, true);
561 if (!osc.isProxy) {
562 throw new InvalidClassException(
563 "cannot bind proxy descriptor to a non-proxy class");
564 }
565 }
566 this.cl = cl;
567 this.resolveEx = resolveEx;
568 this.superDesc = superDesc;
569 isProxy = true;
570 serializable = true;
571 suid = Long.valueOf(0);
572 fields = NO_FIELDS;
573 if (osc != null) {
574 localDesc = osc;
575 name = localDesc.name;
576 externalizable = localDesc.externalizable;
577 writeReplaceMethod = localDesc.writeReplaceMethod;
578 readResolveMethod = localDesc.readResolveMethod;
579 deserializeEx = localDesc.deserializeEx;
580 cons = localDesc.cons;
581 }
582 fieldRefl = getReflector(fields, localDesc);
583 initialized = true;
584 }
585
586 /**
587 * Initializes class descriptor representing a non-proxy class.
588 */
589 void initNonProxy(ObjectStreamClass model,
590 Class<?> cl,
591 ClassNotFoundException resolveEx,
592 ObjectStreamClass superDesc)
593 throws InvalidClassException
594 {
595 long suid = Long.valueOf(model.getSerialVersionUID());
596 ObjectStreamClass osc = null;
597 if (cl != null) {
598 osc = lookup(cl, true);
599 if (osc.isProxy) {
646 isProxy = false;
647 isEnum = model.isEnum;
648 serializable = model.serializable;
649 externalizable = model.externalizable;
650 hasBlockExternalData = model.hasBlockExternalData;
651 hasWriteObjectData = model.hasWriteObjectData;
652 fields = model.fields;
653 primDataSize = model.primDataSize;
654 numObjFields = model.numObjFields;
655
656 if (osc != null) {
657 localDesc = osc;
658 writeObjectMethod = localDesc.writeObjectMethod;
659 readObjectMethod = localDesc.readObjectMethod;
660 readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
661 writeReplaceMethod = localDesc.writeReplaceMethod;
662 readResolveMethod = localDesc.readResolveMethod;
663 if (deserializeEx == null) {
664 deserializeEx = localDesc.deserializeEx;
665 }
666 cons = localDesc.cons;
667 }
668
669 fieldRefl = getReflector(fields, localDesc);
670 // reassign to matched fields so as to reflect local unshared settings
671 fields = fieldRefl.getFields();
672 initialized = true;
673 }
674
675 /**
676 * Reads non-proxy class descriptor information from given input stream.
677 * The resulting class descriptor is not fully functional; it can only be
678 * used as input to the ObjectInputStream.resolveClass() and
679 * ObjectStreamClass.initNonProxy() methods.
680 */
681 void readNonProxy(ObjectInputStream in)
682 throws IOException, ClassNotFoundException
683 {
684 name = in.readUTF();
685 suid = Long.valueOf(in.readLong());
986 requireInitialized();
987 return (readResolveMethod != null);
988 }
989
990 /**
991 * Creates a new instance of the represented class. If the class is
992 * externalizable, invokes its public no-arg constructor; otherwise, if the
993 * class is serializable, invokes the no-arg constructor of the first
994 * non-serializable superclass. Throws UnsupportedOperationException if
995 * this class descriptor is not associated with a class, if the associated
996 * class is non-serializable or if the appropriate no-arg constructor is
997 * inaccessible/unavailable.
998 */
999 Object newInstance()
1000 throws InstantiationException, InvocationTargetException,
1001 UnsupportedOperationException
1002 {
1003 requireInitialized();
1004 if (cons != null) {
1005 try {
1006 return cons.newInstance();
1007 } catch (IllegalAccessException ex) {
1008 // should not occur, as access checks have been suppressed
1009 throw new InternalError(ex);
1010 }
1011 } else {
1012 throw new UnsupportedOperationException();
1013 }
1014 }
1015
1016 /**
1017 * Invokes the writeObject method of the represented serializable class.
1018 * Throws UnsupportedOperationException if this class descriptor is not
1019 * associated with a class, or if the class is externalizable,
1020 * non-serializable or does not define writeObject.
1021 */
1022 void invokeWriteObject(Object obj, ObjectOutputStream out)
1023 throws IOException, UnsupportedOperationException
1024 {
1025 requireInitialized();
1026 if (writeObjectMethod != null) {
|
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.io;
27
28 import java.lang.ref.Reference;
29 import java.lang.ref.ReferenceQueue;
30 import java.lang.ref.SoftReference;
31 import java.lang.ref.WeakReference;
32 import java.lang.reflect.Constructor;
33 import java.lang.reflect.Field;
34 import java.lang.reflect.InvocationTargetException;
35 import java.lang.reflect.UndeclaredThrowableException;
36 import java.lang.reflect.Member;
37 import java.lang.reflect.Method;
38 import java.lang.reflect.Modifier;
39 import java.lang.reflect.Proxy;
40 import java.security.AccessControlContext;
41 import java.security.AccessController;
42 import java.security.MessageDigest;
43 import java.security.NoSuchAlgorithmException;
44 import java.security.PermissionCollection;
45 import java.security.Permissions;
46 import java.security.PrivilegedAction;
47 import java.security.ProtectionDomain;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collections;
51 import java.util.Comparator;
52 import java.util.HashSet;
53 import java.util.Set;
54 import java.util.concurrent.ConcurrentHashMap;
55 import java.util.concurrent.ConcurrentMap;
56 import sun.misc.JavaSecurityAccess;
57 import sun.misc.SharedSecrets;
58 import sun.misc.Unsafe;
59 import sun.reflect.CallerSensitive;
60 import sun.reflect.Reflection;
61 import sun.reflect.ReflectionFactory;
62 import sun.reflect.misc.ReflectUtil;
63
64 /**
65 * Serialization's descriptor for classes. It contains the name and
66 * serialVersionUID of the class. The ObjectStreamClass for a specific class
67 * loaded in this Java VM can be found/created using the lookup method.
68 *
69 * <p>The algorithm to compute the SerialVersionUID is described in
70 * <a href="../../../platform/serialization/spec/class.html#4100">Object
71 * Serialization Specification, Section 4.6, Stream Unique Identifiers</a>.
72 *
73 * @author Mike Warres
74 * @author Roger Riggs
75 * @see ObjectStreamField
76 * @see <a href="../../../platform/serialization/spec/class.html">Object Serialization Specification, Section 4, Class Descriptors</a>
77 * @since JDK1.1
163 /** exception (if any) to throw if non-enum deserialization attempted */
164 private ExceptionInfo deserializeEx;
165 /** exception (if any) to throw if non-enum serialization attempted */
166 private ExceptionInfo serializeEx;
167 /** exception (if any) to throw if default serialization attempted */
168 private ExceptionInfo defaultSerializeEx;
169
170 /** serializable fields */
171 private ObjectStreamField[] fields;
172 /** aggregate marshalled size of primitive fields */
173 private int primDataSize;
174 /** number of non-primitive fields */
175 private int numObjFields;
176 /** reflector for setting/getting serializable field values */
177 private FieldReflector fieldRefl;
178 /** data layout of serialized objects described by this class desc */
179 private volatile ClassDataSlot[] dataLayout;
180
181 /** serialization-appropriate constructor, or null if none */
182 private Constructor<?> cons;
183 /** protection domains that need to be checked when calling the constructor */
184 private ProtectionDomain[] domains;
185
186 /** class-defined writeObject method, or null if none */
187 private Method writeObjectMethod;
188 /** class-defined readObject method, or null if none */
189 private Method readObjectMethod;
190 /** class-defined readObjectNoData method, or null if none */
191 private Method readObjectNoDataMethod;
192 /** class-defined writeReplace method, or null if none */
193 private Method writeReplaceMethod;
194 /** class-defined readResolve method, or null if none */
195 private Method readResolveMethod;
196
197 /** local class descriptor for represented class (may point to self) */
198 private ObjectStreamClass localDesc;
199 /** superclass descriptor appearing in stream */
200 private ObjectStreamClass superDesc;
201
202 /** true if, and only if, the object has been correctly initialized */
203 private boolean initialized;
204
205 /**
498 } catch (InvalidClassException e) {
499 serializeEx = deserializeEx =
500 new ExceptionInfo(e.classname, e.getMessage());
501 fields = NO_FIELDS;
502 }
503
504 if (externalizable) {
505 cons = getExternalizableConstructor(cl);
506 } else {
507 cons = getSerializableConstructor(cl);
508 writeObjectMethod = getPrivateMethod(cl, "writeObject",
509 new Class<?>[] { ObjectOutputStream.class },
510 Void.TYPE);
511 readObjectMethod = getPrivateMethod(cl, "readObject",
512 new Class<?>[] { ObjectInputStream.class },
513 Void.TYPE);
514 readObjectNoDataMethod = getPrivateMethod(
515 cl, "readObjectNoData", null, Void.TYPE);
516 hasWriteObjectData = (writeObjectMethod != null);
517 }
518 domains = getProtectionDomains(cons, cl);
519 writeReplaceMethod = getInheritableMethod(
520 cl, "writeReplace", null, Object.class);
521 readResolveMethod = getInheritableMethod(
522 cl, "readResolve", null, Object.class);
523 return null;
524 }
525 });
526 } else {
527 suid = Long.valueOf(0);
528 fields = NO_FIELDS;
529 }
530
531 try {
532 fieldRefl = getReflector(fields, this);
533 } catch (InvalidClassException ex) {
534 // field mismatches impossible when matching local fields vs. self
535 throw new InternalError(ex);
536 }
537
538 if (deserializeEx == null) {
542 deserializeEx = new ExceptionInfo(name, "no valid constructor");
543 }
544 }
545 for (int i = 0; i < fields.length; i++) {
546 if (fields[i].getField() == null) {
547 defaultSerializeEx = new ExceptionInfo(
548 name, "unmatched serializable field(s) declared");
549 }
550 }
551 initialized = true;
552 }
553
554 /**
555 * Creates blank class descriptor which should be initialized via a
556 * subsequent call to initProxy(), initNonProxy() or readNonProxy().
557 */
558 ObjectStreamClass() {
559 }
560
561 /**
562 * Creates a PermissionDomain that grants no permission.
563 */
564 private ProtectionDomain noPermissionsDomain() {
565 PermissionCollection perms = new Permissions();
566 perms.setReadOnly();
567 return new ProtectionDomain(null, perms);
568 }
569
570 /**
571 * Aggregate the ProtectionDomains of all the classes that separate
572 * a concrete class {@code cl} from its ancestor's class declaring
573 * a constructor {@code cons}.
574 *
575 * If {@code cl} is defined by the boot loader, or the constructor
576 * {@code cons} is declared by {@code cl}, or if there is no security
577 * manager, then this method does nothing and {@code null} is returned.
578 *
579 * @param cons A constructor declared by {@code cl} or one of its
580 * ancestors.
581 * @param cl A concrete class, which is either the class declaring
582 * the constructor {@code cons}, or a serializable subclass
583 * of that class.
584 * @return An array of ProtectionDomain representing the set of
585 * ProtectionDomain that separate the concrete class {@code cl}
586 * from its ancestor's declaring {@code cons}, or {@code null}.
587 */
588 private ProtectionDomain[] getProtectionDomains(Constructor<?> cons,
589 Class<?> cl) {
590 ProtectionDomain[] domains = null;
591 if (cons != null && cl.getClassLoader() != null
592 && System.getSecurityManager() != null) {
593 Class<?> cls = cl;
594 Class<?> fnscl = cons.getDeclaringClass();
595 Set<ProtectionDomain> pds = null;
596 while (cls != fnscl) {
597 ProtectionDomain pd = cls.getProtectionDomain();
598 if (pd != null) {
599 if (pds == null) pds = new HashSet<>();
600 pds.add(pd);
601 }
602 cls = cls.getSuperclass();
603 if (cls == null) {
604 // that's not supposed to happen
605 // make a ProtectionDomain with no permission.
606 // should we throw instead?
607 if (pds == null) pds = new HashSet<>();
608 else pds.clear();
609 pds.add(noPermissionsDomain());
610 break;
611 }
612 }
613 if (pds != null) {
614 domains = pds.toArray(new ProtectionDomain[0]);
615 }
616 }
617 return domains;
618 }
619
620 /**
621 * Initializes class descriptor representing a proxy class.
622 */
623 void initProxy(Class<?> cl,
624 ClassNotFoundException resolveEx,
625 ObjectStreamClass superDesc)
626 throws InvalidClassException
627 {
628 ObjectStreamClass osc = null;
629 if (cl != null) {
630 osc = lookup(cl, true);
631 if (!osc.isProxy) {
632 throw new InvalidClassException(
633 "cannot bind proxy descriptor to a non-proxy class");
634 }
635 }
636 this.cl = cl;
637 this.resolveEx = resolveEx;
638 this.superDesc = superDesc;
639 isProxy = true;
640 serializable = true;
641 suid = Long.valueOf(0);
642 fields = NO_FIELDS;
643 if (osc != null) {
644 localDesc = osc;
645 name = localDesc.name;
646 externalizable = localDesc.externalizable;
647 writeReplaceMethod = localDesc.writeReplaceMethod;
648 readResolveMethod = localDesc.readResolveMethod;
649 deserializeEx = localDesc.deserializeEx;
650 domains = localDesc.domains;
651 cons = localDesc.cons;
652 }
653 fieldRefl = getReflector(fields, localDesc);
654 initialized = true;
655 }
656
657 /**
658 * Initializes class descriptor representing a non-proxy class.
659 */
660 void initNonProxy(ObjectStreamClass model,
661 Class<?> cl,
662 ClassNotFoundException resolveEx,
663 ObjectStreamClass superDesc)
664 throws InvalidClassException
665 {
666 long suid = Long.valueOf(model.getSerialVersionUID());
667 ObjectStreamClass osc = null;
668 if (cl != null) {
669 osc = lookup(cl, true);
670 if (osc.isProxy) {
717 isProxy = false;
718 isEnum = model.isEnum;
719 serializable = model.serializable;
720 externalizable = model.externalizable;
721 hasBlockExternalData = model.hasBlockExternalData;
722 hasWriteObjectData = model.hasWriteObjectData;
723 fields = model.fields;
724 primDataSize = model.primDataSize;
725 numObjFields = model.numObjFields;
726
727 if (osc != null) {
728 localDesc = osc;
729 writeObjectMethod = localDesc.writeObjectMethod;
730 readObjectMethod = localDesc.readObjectMethod;
731 readObjectNoDataMethod = localDesc.readObjectNoDataMethod;
732 writeReplaceMethod = localDesc.writeReplaceMethod;
733 readResolveMethod = localDesc.readResolveMethod;
734 if (deserializeEx == null) {
735 deserializeEx = localDesc.deserializeEx;
736 }
737 domains = localDesc.domains;
738 cons = localDesc.cons;
739 }
740
741 fieldRefl = getReflector(fields, localDesc);
742 // reassign to matched fields so as to reflect local unshared settings
743 fields = fieldRefl.getFields();
744 initialized = true;
745 }
746
747 /**
748 * Reads non-proxy class descriptor information from given input stream.
749 * The resulting class descriptor is not fully functional; it can only be
750 * used as input to the ObjectInputStream.resolveClass() and
751 * ObjectStreamClass.initNonProxy() methods.
752 */
753 void readNonProxy(ObjectInputStream in)
754 throws IOException, ClassNotFoundException
755 {
756 name = in.readUTF();
757 suid = Long.valueOf(in.readLong());
1058 requireInitialized();
1059 return (readResolveMethod != null);
1060 }
1061
1062 /**
1063 * Creates a new instance of the represented class. If the class is
1064 * externalizable, invokes its public no-arg constructor; otherwise, if the
1065 * class is serializable, invokes the no-arg constructor of the first
1066 * non-serializable superclass. Throws UnsupportedOperationException if
1067 * this class descriptor is not associated with a class, if the associated
1068 * class is non-serializable or if the appropriate no-arg constructor is
1069 * inaccessible/unavailable.
1070 */
1071 Object newInstance()
1072 throws InstantiationException, InvocationTargetException,
1073 UnsupportedOperationException
1074 {
1075 requireInitialized();
1076 if (cons != null) {
1077 try {
1078 if (domains == null || domains.length == 0) {
1079 return cons.newInstance();
1080 } else {
1081 JavaSecurityAccess jsa = SharedSecrets.getJavaSecurityAccess();
1082 PrivilegedAction<?> pea = () -> {
1083 try {
1084 return cons.newInstance();
1085 } catch (InstantiationException
1086 | InvocationTargetException
1087 | IllegalAccessException x) {
1088 throw new UndeclaredThrowableException(x);
1089 }
1090 }; // Can't use PrivilegedExceptionAction with jsa
1091 try {
1092 return jsa.doIntersectionPrivilege(pea,
1093 AccessController.getContext(),
1094 new AccessControlContext(domains));
1095 } catch (UndeclaredThrowableException x) {
1096 Throwable cause = x.getCause();
1097 if (cause instanceof InstantiationException)
1098 throw (InstantiationException) cause;
1099 if (cause instanceof InvocationTargetException)
1100 throw (InvocationTargetException) cause;
1101 if (cause instanceof IllegalAccessException)
1102 throw (IllegalAccessException) cause;
1103 // not supposed to happen
1104 throw x;
1105 }
1106 }
1107 } catch (IllegalAccessException ex) {
1108 // should not occur, as access checks have been suppressed
1109 throw new InternalError(ex);
1110 }
1111 } else {
1112 throw new UnsupportedOperationException();
1113 }
1114 }
1115
1116 /**
1117 * Invokes the writeObject method of the represented serializable class.
1118 * Throws UnsupportedOperationException if this class descriptor is not
1119 * associated with a class, or if the class is externalizable,
1120 * non-serializable or does not define writeObject.
1121 */
1122 void invokeWriteObject(Object obj, ObjectOutputStream out)
1123 throws IOException, UnsupportedOperationException
1124 {
1125 requireInitialized();
1126 if (writeObjectMethod != null) {
|