📄 objectstreamclass.java
字号:
{ String name1 = c1.getName(); String name2 = c2.getName(); int id1 = name1.lastIndexOf('.'); int id2 = name2.lastIndexOf('.'); // Handle the default package if (id1 == -1 || id2 == -1) return id1 == id2; String package1 = name1.substring(0, id1); String package2 = name2.substring(0, id2); return package1.equals(package2); } final static Class[] noArgs = new Class[0]; private static Method findAccessibleMethod(String name, Class from) { for (Class c = from; c != null; c = c.getSuperclass()) { try { Method res = c.getDeclaredMethod(name, noArgs); int mods = res.getModifiers(); if (c == from || Modifier.isProtected(mods) || Modifier.isPublic(mods) || (! Modifier.isPrivate(mods) && inSamePackage(c, from))) { AccessController.doPrivileged(new SetAccessibleAction(res)); return res; } } catch (NoSuchMethodException e) { } } return null; } private void cacheMethods() { Method[] methods = forClass().getDeclaredMethods(); readObjectMethod = findMethod(methods, "readObject", new Class[] { ObjectInputStream.class }, Void.TYPE, true); writeObjectMethod = findMethod(methods, "writeObject", new Class[] { ObjectOutputStream.class }, Void.TYPE, true); // readResolve and writeReplace can be in parent classes, as long as they // are accessible from this class. readResolveMethod = findAccessibleMethod("readResolve", forClass()); writeReplaceMethod = findAccessibleMethod("writeReplace", forClass()); } private ObjectStreamClass(Class cl) { uid = 0; flags = 0; isProxyClass = Proxy.isProxyClass(cl); clazz = cl; cacheMethods(); name = cl.getName(); setFlags(cl); setFields(cl); // to those class nonserializable, its uid field is 0 if ( (Serializable.class).isAssignableFrom(cl) && !isProxyClass) uid = getClassUID(cl); superClass = lookup(cl.getSuperclass()); } // Sets bits in flags according to features of CL. private void setFlags(Class cl) { if ((java.io.Externalizable.class).isAssignableFrom(cl)) flags |= ObjectStreamConstants.SC_EXTERNALIZABLE; else if ((java.io.Serializable.class).isAssignableFrom(cl)) // only set this bit if CL is NOT Externalizable flags |= ObjectStreamConstants.SC_SERIALIZABLE; if (writeObjectMethod != null) flags |= ObjectStreamConstants.SC_WRITE_METHOD; } // Sets fields to be a sorted array of the serializable fields of // clazz. private void setFields(Class cl) { SetAccessibleAction setAccessible = new SetAccessibleAction(); if (!isSerializable() || isExternalizable()) { fields = NO_FIELDS; return; } try { final Field f = cl.getDeclaredField("serialPersistentFields"); setAccessible.setMember(f); AccessController.doPrivileged(setAccessible); int modifiers = f.getModifiers(); if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) && Modifier.isPrivate(modifiers)) { fields = getSerialPersistentFields(cl); if (fields != null) { Arrays.sort (fields); // Retrieve field reference. for (int i=0; i < fields.length; i++) { try { fields[i].lookupField(cl); } catch (NoSuchFieldException _) { fields[i].setToSet(false); } } calculateOffsets(); return; } } } catch (NoSuchFieldException ignore) { } catch (IllegalAccessException ignore) { } int num_good_fields = 0; Field[] all_fields = cl.getDeclaredFields(); int modifiers; // set non-serializable fields to null in all_fields for (int i = 0; i < all_fields.length; i++) { modifiers = all_fields[i].getModifiers(); if (Modifier.isTransient(modifiers) || Modifier.isStatic(modifiers)) all_fields[i] = null; else num_good_fields++; } // make a copy of serializable (non-null) fields fields = new ObjectStreamField[ num_good_fields ]; for (int from = 0, to = 0; from < all_fields.length; from++) if (all_fields[from] != null) { final Field f = all_fields[from]; setAccessible.setMember(f); AccessController.doPrivileged(setAccessible); fields[to] = new ObjectStreamField(all_fields[from]); to++; } Arrays.sort(fields); // Make sure we don't have any duplicate field names // (Sun JDK 1.4.1. throws an Internal Error as well) for (int i = 1; i < fields.length; i++) { if(fields[i - 1].getName().equals(fields[i].getName())) throw new InternalError("Duplicate field " + fields[i].getName() + " in class " + cl.getName()); } calculateOffsets(); } // Returns the serial version UID defined by class, or if that // isn't present, calculates value of serial version UID. private long getClassUID(Class cl) { try { // Use getDeclaredField rather than getField, since serialVersionUID // may not be public AND we only want the serialVersionUID of this // class, not a superclass or interface. final Field suid = cl.getDeclaredField("serialVersionUID"); SetAccessibleAction setAccessible = new SetAccessibleAction(suid); AccessController.doPrivileged(setAccessible); int modifiers = suid.getModifiers(); if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) && suid.getType() == Long.TYPE) return suid.getLong(null); } catch (NoSuchFieldException ignore) { } catch (IllegalAccessException ignore) { } // cl didn't define serialVersionUID, so we have to compute it try { MessageDigest md; try { md = MessageDigest.getInstance("SHA"); } catch (NoSuchAlgorithmException e) { // If a provider already provides SHA, use it; otherwise, use this. Gnu gnuProvider = new Gnu(); Security.addProvider(gnuProvider); md = MessageDigest.getInstance("SHA"); } DigestOutputStream digest_out = new DigestOutputStream(nullOutputStream, md); DataOutputStream data_out = new DataOutputStream(digest_out); data_out.writeUTF(cl.getName()); int modifiers = cl.getModifiers(); // just look at interesting bits modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL | Modifier.INTERFACE | Modifier.PUBLIC); data_out.writeInt(modifiers); // Pretend that an array has no interfaces, because when array // serialization was defined (JDK 1.1), arrays didn't have it. if (! cl.isArray()) { Class[] interfaces = cl.getInterfaces(); Arrays.sort(interfaces, interfaceComparator); for (int i = 0; i < interfaces.length; i++) data_out.writeUTF(interfaces[i].getName()); } Field field; Field[] fields = cl.getDeclaredFields(); Arrays.sort(fields, memberComparator); for (int i = 0; i < fields.length; i++) { field = fields[i]; modifiers = field.getModifiers(); if (Modifier.isPrivate(modifiers) && (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) continue; data_out.writeUTF(field.getName()); data_out.writeInt(modifiers); data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType())); } // write class initializer method if present if (VMObjectStreamClass.hasClassInitializer(cl)) { data_out.writeUTF("<clinit>"); data_out.writeInt(Modifier.STATIC); data_out.writeUTF("()V"); } Constructor constructor; Constructor[] constructors = cl.getDeclaredConstructors(); Arrays.sort (constructors, memberComparator); for (int i = 0; i < constructors.length; i++) { constructor = constructors[i]; modifiers = constructor.getModifiers(); if (Modifier.isPrivate(modifiers)) continue; data_out.writeUTF("<init>"); data_out.writeInt(modifiers); // the replacement of '/' with '.' was needed to make computed // SUID's agree with those computed by JDK data_out.writeUTF (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.')); } Method method; Method[] methods = cl.getDeclaredMethods(); Arrays.sort(methods, memberComparator); for (int i = 0; i < methods.length; i++) { method = methods[i]; modifiers = method.getModifiers(); if (Modifier.isPrivate(modifiers)) continue; data_out.writeUTF(method.getName()); data_out.writeInt(modifiers); // the replacement of '/' with '.' was needed to make computed // SUID's agree with those computed by JDK data_out.writeUTF (TypeSignature.getEncodingOfMethod(method).replace('/', '.')); } data_out.close(); byte[] sha = md.digest(); long result = 0; int len = sha.length < 8 ? sha.length : 8; for (int i = 0; i < len; i++) result += (long) (sha[i] & 0xFF) << (8 * i); return result; } catch (NoSuchAlgorithmException e) { throw new RuntimeException ("The SHA algorithm was not found to use in computing the Serial Version UID for class " + cl.getName(), e); } catch (IOException ioe) { throw new RuntimeException(ioe); } } /** * Returns the value of CLAZZ's private static final field named * `serialPersistentFields'. It performs some sanity checks before * returning the real array. Besides, the returned array is a clean * copy of the original. So it can be modified. * * @param clazz Class to retrieve 'serialPersistentFields' from. * @return The content of 'serialPersistentFields'. */ private ObjectStreamField[] getSerialPersistentFields(Class clazz) throws NoSuchFieldException, IllegalAccessException { ObjectStreamField[] fieldsArray = null; ObjectStreamField[] o; // Use getDeclaredField rather than getField for the same reason // as above in getDefinedSUID. Field f = clazz.getDeclaredField("serialPersistentFields"); f.setAccessible(true); int modifiers = f.getModifiers(); if (!(Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) && Modifier.isPrivate(modifiers))) return null; o = (ObjectStreamField[]) f.get(null); if (o == null) return null; fieldsArray = new ObjectStreamField[ o.length ]; System.arraycopy(o, 0, fieldsArray, 0, o.length); return fieldsArray; } /** * Returns a new instance of the Class this ObjectStreamClass corresponds * to. * Note that this should only be used for Externalizable classes. * * @return A new instance. */ Externalizable newInstance() throws InvalidClassException { synchronized(this) { if (constructor == null) { try { final Constructor c = clazz.getConstructor(new Class[0]); AccessController.doPrivileged(new PrivilegedAction() { public Object run() { c.setAccessible(true); return null; } }); constructor = c; } catch(NoSuchMethodException x) { throw new InvalidClassException(clazz.getName(), "No public zero-argument constructor"); } } } try { return (Externalizable)constructor.newInstance(null); } catch(Exception x) { throw (InvalidClassException) new InvalidClassException(clazz.getName(), "Unable to instantiate").initCause(x); } } public static final ObjectStreamField[] NO_FIELDS = {}; private static Hashtable classLookupTable = new Hashtable(); private static final NullOutputStream nullOutputStream = new NullOutputStream(); private static final Comparator interfaceComparator = new InterfaceComparator(); private static final Comparator memberComparator = new MemberComparator(); private static final Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class }; private ObjectStreamClass superClass; private Class clazz; private String name; private long uid; private byte flags; // this field is package protected so that ObjectInputStream and // ObjectOutputStream can access it directly ObjectStreamField[] fields; // these are accessed by ObjectIn/OutputStream int primFieldSize = -1; // -1 if not yet calculated int objectFieldCount; Method readObjectMethod; Method readResolveMethod; Method writeReplaceMethod; Method writeObjectMethod; boolean realClassIsSerializable; boolean realClassIsExternalizable; ObjectStreamField[] fieldMapping; Constructor firstNonSerializableParentConstructor; private Constructor constructor; // default constructor for Externalizable boolean isProxyClass = false; // This is probably not necessary because this class is special cased already // but it will avoid showing up as a discrepancy when comparing SUIDs. private static final long serialVersionUID = -6120832682080437368L; // interfaces are compared only by name private static final class InterfaceComparator implements Comparator { public int compare(Object o1, Object o2) { return ((Class) o1).getName().compareTo(((Class) o2).getName()); } } // Members (Methods and Constructors) are compared first by name, // conflicts are resolved by comparing type signatures private static final class MemberComparator implements Comparator { public int compare(Object o1, Object o2) { Member m1 = (Member) o1; Member m2 = (Member) o2; int comp = m1.getName().compareTo(m2.getName()); if (comp == 0) return TypeSignature.getEncodingOfMember(m1). compareTo(TypeSignature.getEncodingOfMember(m2)); else return comp; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -