objectstreamclass.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 677 行 · 第 1/2 页

JAVA
677
字号
	  break;
      }
    }

    for (objectFieldCount = 0; i < fcount; ++ i)
      fields[i].setOffset (objectFieldCount++);
  }


  private ObjectStreamClass (Class cl)
  {
    uid = 0;
    flags = 0;
    isProxyClass = Proxy.isProxyClass (cl);

    clazz = cl;
    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;

    try
    {
      Method writeMethod = cl.getDeclaredMethod ("writeObject",
						 writeMethodArgTypes);
      int modifiers = writeMethod.getModifiers ();

      if (writeMethod.getReturnType () == Void.TYPE
	  && Modifier.isPrivate (modifiers)
	  && !Modifier.isStatic (modifiers))
	flags |= ObjectStreamConstants.SC_WRITE_METHOD;
    }
    catch (NoSuchMethodException oh_well)
    {}
  }


  // Sets fields to be a sorted array of the serializable fields of
  // clazz.
  private void setFields (Class cl)
  {
    if (! isSerializable () || isExternalizable ())
    {
      fields = NO_FIELDS;
      return;
    }

    try
    {
      Field serialPersistentFields
	= cl.getDeclaredField ("serialPersistentFields");
      serialPersistentFields.setAccessible(true);
      int modifiers = serialPersistentFields.getModifiers ();

      if (Modifier.isStatic (modifiers)
	  && Modifier.isFinal (modifiers)
	  && Modifier.isPrivate (modifiers))
      {
	fields = getSerialPersistentFields (cl);
	Arrays.sort (fields);
	calculateOffsets ();
	return;
      }
    }
    catch (NoSuchFieldException 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)
      {
	Field f = all_fields[from];
	fields[to] = new ObjectStreamField (f.getName (), f.getType ());
	to++;
      }

    Arrays.sort (fields);
    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.
      Field suid = cl.getDeclaredField ("serialVersionUID");
      suid.setAccessible(true);
      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'.
  private ObjectStreamField[] getSerialPersistentFields (Class clazz)
  {
    ObjectStreamField[] o = null;
    try
      {
	// Use getDeclaredField rather than getField for the same reason
	// as above in getDefinedSUID.
	Field f = clazz.getDeclaredField ("getSerialPersistentFields");
	f.setAccessible(true);
	o = (ObjectStreamField[])f.get (null);
      }
    catch (java.lang.NoSuchFieldException e)
      {
      }
    catch (java.lang.IllegalAccessException e)
      {
      }

    return o;
  }

  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;

  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
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
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 + =
减小字号Ctrl + -
显示快捷键?