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 + -
显示快捷键?