objectstreamclass.java
来自「JAVA 所有包」· Java 代码 · 共 1,822 行 · 第 1/4 页
JAVA
1,822 行
Object newInstance() throws InstantiationException, InvocationTargetException, UnsupportedOperationException { if (cons != null) { try { return cons.newInstance(new Object[0]); } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed InternalError ie = new InternalError(); ie.initCause( ex ) ; throw ie ; } } else { throw new UnsupportedOperationException(); } } /** * Returns public no-arg constructor of given class, or null if none found. * Access checks are disabled on the returned constructor (if any), since * the defining class may still be non-public. */ private static Constructor getExternalizableConstructor(Class cl) { try { Constructor cons = cl.getDeclaredConstructor(new Class[0]); cons.setAccessible(true); return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ? cons : null; } catch (NoSuchMethodException ex) { return null; } } /** * Returns subclass-accessible no-arg constructor of first non-serializable * superclass, or null if none found. Access checks are disabled on the * returned constructor (if any). */ private static Constructor getSerializableConstructor(Class cl) { Class initCl = cl; while (Serializable.class.isAssignableFrom(initCl)) { if ((initCl = initCl.getSuperclass()) == null) { return null; } } try { Constructor cons = initCl.getDeclaredConstructor(new Class[0]); int mods = cons.getModifiers(); if ((mods & Modifier.PRIVATE) != 0 || ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && !packageEquals(cl, initCl))) { return null; } cons = bridge.newConstructorForSerialization(cl, cons); cons.setAccessible(true); return cons; } catch (NoSuchMethodException ex) { return null; } } /* * Return the ObjectStreamClass of the local class this one is based on. */ final ObjectStreamClass localClassDescriptor() { return localClassDesc; } /* * Get the Serializability of the class. */ boolean isSerializable() { return serializable; } /* * Get the externalizability of the class. */ boolean isExternalizable() { return externalizable; } boolean isNonSerializable() { return ! (externalizable || serializable); } /* * Calculate the size of the array needed to store primitive data and the * number of object references to read when reading from the input * stream. */ private void computeFieldInfo() { primBytes = 0; objFields = 0; for (int i = 0; i < fields.length; i++ ) { switch (fields[i].getTypeCode()) { case 'B': case 'Z': primBytes += 1; break; case 'C': case 'S': primBytes += 2; break; case 'I': case 'F': primBytes += 4; break; case 'J': case 'D' : primBytes += 8; break; case 'L': case '[': objFields += 1; break; } } } private static void msg( String str ) { System.out.println( str ) ; } /* JDK 1.5 has introduced some new modifier bits (such as SYNTHETIC) * that can affect the SVUID computation (see bug 4897937). These bits * must be ignored, as otherwise interoperability with ORBs in earlier * JDK versions can be compromised. I am adding these masks for this * purpose as discussed in the CCC for this bug (see http://ccc.sfbay/4897937). */ public static final int CLASS_MASK = Modifier.PUBLIC | Modifier.FINAL | Modifier.INTERFACE | Modifier.ABSTRACT ; public static final int FIELD_MASK = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE ; public static final int METHOD_MASK = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE | Modifier.ABSTRACT | Modifier.STRICT ; /* * Compute a hash for the specified class. Incrementally add * items to the hash accumulating in the digest stream. * Fold the hash into a long. Use the SHA secure hash function. */ private static long _computeSerialVersionUID(Class cl) { if (DEBUG_SVUID) msg( "Computing SerialVersionUID for " + cl ) ; ByteArrayOutputStream devnull = new ByteArrayOutputStream(512); long h = 0; try { MessageDigest md = MessageDigest.getInstance("SHA"); DigestOutputStream mdo = new DigestOutputStream(devnull, md); DataOutputStream data = new DataOutputStream(mdo); if (DEBUG_SVUID) msg( "\twriteUTF( \"" + cl.getName() + "\" )" ) ; data.writeUTF(cl.getName()); int classaccess = cl.getModifiers(); classaccess &= (Modifier.PUBLIC | Modifier.FINAL | Modifier.INTERFACE | Modifier.ABSTRACT); /* Workaround for javac bug that only set ABSTRACT for * interfaces if the interface had some methods. * The ABSTRACT bit reflects that the number of methods > 0. * This is required so correct hashes can be computed * for existing class files. * Previously this hack was previously present in the VM. */ Method[] method = cl.getDeclaredMethods(); if ((classaccess & Modifier.INTERFACE) != 0) { classaccess &= (~Modifier.ABSTRACT); if (method.length > 0) { classaccess |= Modifier.ABSTRACT; } } // Mask out any post-1.4 attributes classaccess &= CLASS_MASK ; if (DEBUG_SVUID) msg( "\twriteInt( " + classaccess + " ) " ) ; data.writeInt(classaccess); /* * Get the list of interfaces supported, * Accumulate their names their names in Lexical order * and add them to the hash */ if (!cl.isArray()) { /* In 1.2fcs, getInterfaces() was modified to return * {java.lang.Cloneable, java.io.Serializable} when * called on array classes. These values would upset * the computation of the hash, so we explicitly omit * them from its computation. */ Class interfaces[] = cl.getInterfaces(); Arrays.sort(interfaces, compareClassByName); for (int i = 0; i < interfaces.length; i++) { if (DEBUG_SVUID) msg( "\twriteUTF( \"" + interfaces[i].getName() + "\" ) " ) ; data.writeUTF(interfaces[i].getName()); } } /* Sort the field names to get a deterministic order */ Field[] field = cl.getDeclaredFields(); Arrays.sort(field, compareMemberByName); for (int i = 0; i < field.length; i++) { Field f = field[i]; /* Include in the hash all fields except those that are * private transient and private static. */ int m = f.getModifiers(); if (Modifier.isPrivate(m) && (Modifier.isTransient(m) || Modifier.isStatic(m))) continue; if (DEBUG_SVUID) msg( "\twriteUTF( \"" + f.getName() + "\" ) " ) ; data.writeUTF(f.getName()); // Mask out any post-1.4 bits m &= FIELD_MASK ; if (DEBUG_SVUID) msg( "\twriteInt( " + m + " ) " ) ; data.writeInt(m); if (DEBUG_SVUID) msg( "\twriteUTF( \"" + getSignature(f.getType()) + "\" ) " ) ; data.writeUTF(getSignature(f.getType())); } if (hasStaticInitializer(cl)) { if (DEBUG_SVUID) msg( "\twriteUTF( \"<clinit>\" ) " ) ; data.writeUTF("<clinit>"); if (DEBUG_SVUID) msg( "\twriteInt( " + Modifier.STATIC + " )" ) ; data.writeInt(Modifier.STATIC); // TBD: what modifiers does it have if (DEBUG_SVUID) msg( "\twriteUTF( \"()V\" )" ) ; data.writeUTF("()V"); } /* * Get the list of constructors including name and signature * Sort lexically, add all except the private constructors * to the hash with their access flags */ MethodSignature[] constructors = MethodSignature.removePrivateAndSort(cl.getDeclaredConstructors()); for (int i = 0; i < constructors.length; i++) { MethodSignature c = constructors[i]; String mname = "<init>"; String desc = c.signature; desc = desc.replace('/', '.'); if (DEBUG_SVUID) msg( "\twriteUTF( \"" + mname + "\" )" ) ; data.writeUTF(mname); // mask out post-1.4 modifiers int modifier = c.member.getModifiers() & METHOD_MASK ; if (DEBUG_SVUID) msg( "\twriteInt( " + modifier + " ) " ) ; data.writeInt( modifier ) ; if (DEBUG_SVUID) msg( "\twriteUTF( \"" + desc+ "\" )" ) ; data.writeUTF(desc); } /* Include in the hash all methods except those that are * private transient and private static. */ MethodSignature[] methods = MethodSignature.removePrivateAndSort(method); for (int i = 0; i < methods.length; i++ ) { MethodSignature m = methods[i]; String desc = m.signature; desc = desc.replace('/', '.'); if (DEBUG_SVUID) msg( "\twriteUTF( \"" + m.member.getName()+ "\" )" ) ; data.writeUTF(m.member.getName()); // mask out post-1.4 modifiers int modifier = m.member.getModifiers() & METHOD_MASK ; if (DEBUG_SVUID) msg( "\twriteInt( " + modifier + " ) " ) ; data.writeInt( modifier ) ; if (DEBUG_SVUID) msg( "\twriteUTF( \"" + desc + "\" )" ) ; data.writeUTF(desc); } /* Compute the hash value for this class. * Use only the first 64 bits of the hash. */ data.flush(); byte hasharray[] = md.digest(); for (int i = 0; i < Math.min(8, hasharray.length); i++) { h += (long)(hasharray[i] & 255) << (i * 8); } } catch (IOException ignore) { /* can't happen, but be deterministic anyway. */ h = -1; } catch (NoSuchAlgorithmException complain) { SecurityException se = new SecurityException() ; se.initCause( complain ) ; throw se ; } return h; } private static long computeStructuralUID(com.sun.corba.se.impl.io.ObjectStreamClass osc, Class cl) { ByteArrayOutputStream devnull = new ByteArrayOutputStream(512); long h = 0; try { if ((!java.io.Serializable.class.isAssignableFrom(cl)) || (cl.isInterface())){ return 0; } if (java.io.Externalizable.class.isAssignableFrom(cl)) { return 1; } MessageDigest md = MessageDigest.getInstance("SHA"); DigestOutputStream mdo = new DigestOutputStream(devnull, md); DataOutputStream data = new DataOutputStream(mdo); // Get SUID of parent Class parent = cl.getSuperclass(); if ((parent != null)) // SerialBug 1; acc. to spec the one for // java.lang.object // should be computed and put // && (parent != java.lang.Object.class)) { //data.writeLong(computeSerialVersionUID(null,parent)); data.writeLong(computeStructuralUID(lookup(parent), parent)); } if (osc.hasWriteObject()) data.writeInt(2); else data.writeInt(1); // CORBA formal 00-11-03 10.6.2: For each field of the // class that is mapped to IDL, sorted lexicographically // by Java field name, in increasing order... ObjectStreamField[] field = osc.getFields(); if (field.length > 1) { Arrays.sort(field, compareObjStrFieldsByName); } // ...Java field name in UTF encoding, field // descriptor, as defined by the JVM spec... for (int i = 0; i < field.length; i++) { data.writeUTF(field[i].getName()); data.writeUTF(field[i].getSignature()); } /* Compute the hash value for this class. * Use only the first 64 bits of the hash. */ data.flush(); byte hasharray[] = md.digest(); // int minimum = Math.min(8, hasharray.length); // SerialBug 3: SHA computation is wrong; for loop reversed //for (int i = minimum; i > 0; i--) for (int i = 0; i < Math.min(8, hasharray.length); i++) { h += (long)(hasharray[i] & 255) << (i * 8); } } catch (IOException ignore) { /* can't happen, but be deterministic anyway. */ h = -1; } catch (NoSuchAlgorithmException complain) { SecurityException se = new SecurityException(); se.initCause( complain ) ; throw se ; } return h; } /** * Compute the JVM signature for the class. */ static String getSignature(Class clazz) { String type = null; if (clazz.isArray()) { Class cl = clazz; int dimensions = 0; while (cl.isArray()) { dimensions++; cl = cl.getComponentType(); } StringBuffer sb = new StringBuffer(); for (int i = 0; i < dimensions; i++) { sb.append("["); } sb.append(getSignature(cl)); type = sb.toString(); } else if (clazz.isPrimitive()) { if (clazz == Integer.TYPE) { type = "I"; } else if (clazz == Byte.TYPE) { type = "B"; } else if (clazz == Long.TYPE) { type = "J"; } else if (clazz == Float.TYPE) { type = "F"; } else if (clazz == Double.TYPE) { type = "D"; } else if (clazz == Short.TYPE) { type = "S"; } else if (clazz == Character.TYPE) { type = "C"; } else if (clazz == Boolean.TYPE) { type = "Z"; } else if (clazz == Void.TYPE) { type = "V"; } } else { type = "L" + clazz.getName().replace('.', '/') + ";"; } return type; } /* * Compute the JVM method descriptor for the method. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?