objectinputstream.java
来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· Java 代码 · 共 1,847 行 · 第 1/4 页
JAVA
1,847 行
class_name = (String)readObject(); else class_name = String.valueOf(type_code); fields[i] = new ObjectStreamField(field_name, class_name, currentLoader); } /* Now that fields have been read we may resolve the class * (and read annotation if needed). */ Class clazz = resolveClass(osc); boolean oldmode = setBlockDataMode(true); osc.setClass(clazz, lookupClass(clazz.getSuperclass())); classLookupTable.put(clazz, osc); setBlockDataMode(oldmode); // find the first non-serializable, non-abstract // class in clazz's inheritance hierarchy Class first_nonserial = clazz.getSuperclass(); while (Serializable.class.isAssignableFrom(first_nonserial) || Modifier.isAbstract(first_nonserial.getModifiers())) first_nonserial = first_nonserial.getSuperclass(); osc.firstNonSerializableParent = first_nonserial; osc.realClassIsSerializable = Serializable.class.isAssignableFrom(clazz); osc.realClassIsExternalizable = Externalizable.class.isAssignableFrom(clazz); ObjectStreamField[] stream_fields = osc.fields; ObjectStreamField[] real_fields = ObjectStreamClass.lookup(clazz).fields; ObjectStreamField[] fieldmapping = new ObjectStreamField[2 * Math.max(stream_fields.length, real_fields.length)]; int stream_idx = 0; int real_idx = 0; int map_idx = 0; while (stream_idx < stream_fields.length || real_idx < real_fields.length) { ObjectStreamField stream_field = null; ObjectStreamField real_field = null; if (stream_idx == stream_fields.length) { real_field = real_fields[real_idx++]; } else if (real_idx == real_fields.length) { stream_field = stream_fields[stream_idx++]; } else { int comp_val = real_fields[real_idx].compareTo (stream_fields[stream_idx]); if (comp_val < 0) { real_field = real_fields[real_idx++]; } else if (comp_val > 0) { stream_field = stream_fields[stream_idx++]; } else { stream_field = stream_fields[stream_idx++]; real_field = real_fields[real_idx++]; if(stream_field.getType() != real_field.getType()) throw new InvalidClassException ("invalid field type for " + real_field.getName() + " in class " + name); } } if (stream_field != null) { if (stream_field.getOffset() < 0) stream_field = null; else if (!stream_field.isToSet()) real_field = null; } if (real_field != null && !real_field.isToSet()) real_field = null; /* If some of stream_fields does not correspond to any of real_fields, * or the opposite, then fieldmapping will go short. */ if (map_idx == fieldmapping.length) { ObjectStreamField[] newfieldmapping = new ObjectStreamField[fieldmapping.length + 2]; System.arraycopy(fieldmapping, 0, newfieldmapping, 0, fieldmapping.length); fieldmapping = newfieldmapping; } fieldmapping[map_idx++] = stream_field; fieldmapping[map_idx++] = real_field; } osc.fieldMapping = fieldmapping; return osc; } /** * Reads the current objects non-transient, non-static fields from * the current class from the underlying output stream. * * This method is intended to be called from within a object's * <code>private void readObject (ObjectInputStream)</code> * method. * * @exception ClassNotFoundException The class that an object being * read in belongs to cannot be found. * * @exception NotActiveException This method was called from a * context other than from the current object's and current class's * <code>private void readObject (ObjectInputStream)</code> * method. * * @exception IOException Exception from underlying * <code>OutputStream</code>. */ public void defaultReadObject() throws ClassNotFoundException, IOException, NotActiveException { if (this.currentObject == null || this.currentObjectStreamClass == null) throw new NotActiveException("defaultReadObject called by non-active" + " class and/or object"); if (fieldsAlreadyRead) throw new NotActiveException("defaultReadObject called but fields " + "already read from stream (by " + "defaultReadObject or readFields)"); boolean oldmode = setBlockDataMode(false); readFields(this.currentObject, this.currentObjectStreamClass); setBlockDataMode(oldmode); fieldsAlreadyRead = true; } /** * Registers a <code>ObjectInputValidation</code> to be carried out * on the object graph currently being deserialized before it is * returned to the original caller of <code>readObject ()</code>. * The order of validation for multiple * <code>ObjectInputValidation</code>s can be controled using * <code>priority</code>. Validators with higher priorities are * called first. * * @see java.io.ObjectInputValidation * * @exception InvalidObjectException <code>validator</code> is * <code>null</code> * * @exception NotActiveException an attempt was made to add a * validator outside of the <code>readObject</code> method of the * object currently being deserialized */ public void registerValidation(ObjectInputValidation validator, int priority) throws InvalidObjectException, NotActiveException { if (this.currentObject == null || this.currentObjectStreamClass == null) throw new NotActiveException("registerValidation called by non-active " + "class and/or object"); if (validator == null) throw new InvalidObjectException("attempt to add a null " + "ObjectInputValidation object"); this.validators.addElement(new ValidatorAndPriority (validator, priority)); } /** * Called when a class is being deserialized. This is a hook to * allow subclasses to read in information written by the * <code>annotateClass (Class)</code> method of an * <code>ObjectOutputStream</code>. * * This implementation looks up the active call stack for a * <code>ClassLoader</code>; if a <code>ClassLoader</code> is found, * it is used to load the class associated with <code>osc</code>, * otherwise, the default system <code>ClassLoader</code> is used. * * @exception IOException Exception from underlying * <code>OutputStream</code>. * * @see java.io.ObjectOutputStream#annotateClass (java.lang.Class) */ protected Class resolveClass(ObjectStreamClass osc) throws ClassNotFoundException, IOException { return Class.forName(osc.getName(), true, currentLoader()); } /** * This method invokes the method currentClassLoader for the * current security manager (or build an empty one if it is not * present). * * @return The most recent non-system ClassLoader on the execution stack. * @see java.lang.SecurityManager#currentClassLoader() */ private ClassLoader currentLoader() { SecurityManager sm = System.getSecurityManager(); if (sm == null) sm = new SecurityManager () {}; return currentClassLoader(sm); } /** * Lookup a class stored in the local hashtable. If it is not * use the global lookup function in ObjectStreamClass to build * the ObjectStreamClass. This method is requested according to * the behaviour detected in the JDK by Kaffe's team. * * @param clazz Class to lookup in the hash table or for which * we must build a descriptor. * @return A valid instance of ObjectStreamClass corresponding * to the specified class. */ private ObjectStreamClass lookupClass(Class clazz) { ObjectStreamClass oclazz; oclazz = (ObjectStreamClass)classLookupTable.get(clazz); if (oclazz == null) return ObjectStreamClass.lookup(clazz); else return oclazz; } /** * Reconstruct class hierarchy the same way * {@link java.io.ObjectStreamClass.getObjectStreamClasses(java.lang.Class)} does * but using lookupClass instead of ObjectStreamClass.lookup. This * dup is necessary localize the lookup table. Hopefully some future * rewritings will be able to prevent this. * * @param clazz This is the class for which we want the hierarchy. * * @return An array of valid {@link java.io.ObjectStreamClass} instances which * represent the class hierarchy for clazz. */ private ObjectStreamClass[] inputGetObjectStreamClasses(Class clazz) { ObjectStreamClass osc = lookupClass(clazz); if (osc == null) return new ObjectStreamClass[0]; else { Vector oscs = new Vector(); while (osc != null) { oscs.addElement(osc); osc = osc.getSuper(); } int count = oscs.size(); ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[count]; for (int i = count - 1; i >= 0; i--) sorted_oscs[count - i - 1] = (ObjectStreamClass) oscs.elementAt(i); return sorted_oscs; } } /** * Allows subclasses to resolve objects that are read from the * stream with other objects to be returned in their place. This * method is called the first time each object is encountered. * * This method must be enabled before it will be called in the * serialization process. * * @exception IOException Exception from underlying * <code>OutputStream</code>. * * @see #enableResolveObject(boolean) */ protected Object resolveObject(Object obj) throws IOException { return obj; } protected Class resolveProxyClass(String[] intfs) throws IOException, ClassNotFoundException { SecurityManager sm = System.getSecurityManager(); if (sm == null) sm = new SecurityManager() {}; ClassLoader cl = currentClassLoader(sm); Class[] clss = new Class[intfs.length]; if(cl == null) { for (int i = 0; i < intfs.length; i++) clss[i] = Class.forName(intfs[i]); cl = ClassLoader.getSystemClassLoader(); } else for (int i = 0; i < intfs.length; i++) clss[i] = cl.loadClass(intfs[i]); try { return Proxy.getProxyClass(cl, clss); } catch (IllegalArgumentException e) { throw new ClassNotFoundException(null, e); } } /** * If <code>enable</code> is <code>true</code> and this object is * trusted, then <code>resolveObject (Object)</code> will be called * in subsequent calls to <code>readObject (Object)</code>. * Otherwise, <code>resolveObject (Object)</code> will not be called. * * @exception SecurityException This class is not trusted. */ protected boolean enableResolveObject (boolean enable) throws SecurityException { if (enable) { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPermission(new SerializablePermission("enableSubstitution")); } boolean old_val = this.resolveEnabled; this.resolveEnabled = enable; return old_val; } /** * Reads stream magic and stream version information from the * underlying stream. * * @exception IOException Exception from underlying stream. * * @exception StreamCorruptedException An invalid stream magic * number or stream version was read from the stream. */ protected void readStreamHeader() throws IOException, StreamCorruptedException { if(dump) dumpElement("STREAM MAGIC "); if (this.realInputStream.readShort() != STREAM_MAGIC) throw new StreamCorruptedException("Invalid stream magic number"); if(dump) dumpElementln("STREAM VERSION "); if (this.realInputStream.readShort() != STREAM_VERSION) throw new StreamCorruptedException("Invalid stream version number"); } public int read() throws IOException { if (this.readDataFromBlock) { if (this.blockDataPosition >= this.blockDataBytes) readNextBlock(); return (this.blockData[this.blockDataPosition++] & 0xff); } else return this.realInputStream.read(); } public int read(byte[] data, int offset, int length) throws IOException { if (this.readDataFromBlock) { if (this.blockDataPosition + length > this.blockDataBytes) { int remain = this.blockDataBytes - this.blockDataPosition; if (remain != 0) { System.arraycopy(this.blockData, this.blockDataPosition, data, offset, remain); offset += remain; length -= remain; } readNextBlock (); } System.arraycopy(this.blockData, this.blockDataPosition, data, offset, length); this.blockDataPosition += length; return length; } else return this.realInputStream.read(data, offset, length); } public int available() throws IOException { if (this.readDataFromBlock) { if (this.blockDataPosition >= this.blockDataBytes) readNextBlock (); return this.blockDataBytes - this.blockDataPosition; } else return this.realInputStream.available(); } public void close() throws IOException { this.realInputStream.close(); } public boolean readBoolean() throws IOException { boolean switchmode = true; boolean oldmode = this.readDataFromBlock; if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1) switchmode = false; if (switchmode) oldmode = setBlockDataMode (true); boolean value = this.dataInputStream.readBoolean (); if (switchmode) setBlockDataMode (oldmode); return value; } public byte readByte() throws IOException { boolean switchmode = true; boolean oldmode = this.readDataFromBlock; if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1) switchmode = false; if (switchmode) oldmode = setBlockDataMode(true); byte value = this.dataInputStream.readByte(); if (switchmode) setBlockDataMode(oldmode); return value; } public int readUnsignedByte() throws IOException { boolean switchmode = true; boolean oldmode = this.readDataFromBlock; if (!oldmode || this.blockDataBytes - this.blockDataPosition >= 1) switchmode = false; if (switchmode) oldmode = setBlockDataMode(true); int value = this.dataInputStream.readUnsignedByte(); if (switchmode)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?