diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2007-01-09 19:58:05 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2007-01-09 19:58:05 +0000 |
commit | 97b8365cafc3a344a22d3980b8ed885f5c6d8357 (patch) | |
tree | 996a5f57d4a68c53473382e45cb22f574cb3e4db /libjava/classpath/java/io | |
parent | c648dedbde727ca3f883bb5fd773aa4af70d3369 (diff) | |
download | gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.zip gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.tar.gz gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.tar.bz2 |
Merged gcj-eclipse branch to trunk.
From-SVN: r120621
Diffstat (limited to 'libjava/classpath/java/io')
22 files changed, 897 insertions, 685 deletions
diff --git a/libjava/classpath/java/io/CharArrayWriter.java b/libjava/classpath/java/io/CharArrayWriter.java index 68e693b..0eead3a 100644 --- a/libjava/classpath/java/io/CharArrayWriter.java +++ b/libjava/classpath/java/io/CharArrayWriter.java @@ -267,7 +267,7 @@ public class CharArrayWriter extends Writer * sequence is wrapped around an input buffer, the results will * depend on the current position and length of that buffer. * - * @param cs the character sequence to append. If cs is null, + * @param seq the character sequence to append. If seq is null, * then the string "null" (the string representation of null) * is appended. * @return a reference to this object. @@ -291,10 +291,10 @@ public class CharArrayWriter extends Writer * output stream underlying this writer, starting and ending at the * specified positions within the sequence. The behaviour of this * method matches the behaviour of writing the result of - * <code>append(cs.subSequence(start,end))</code> when the sequence + * <code>append(seq.subSequence(start,end))</code> when the sequence * is not null. * - * @param cs the character sequence to append. If cs is null, + * @param seq the character sequence to append. If seq is null, * then the string "null" (the string representation of null) * is appended. * @param start the index of the first Unicode character to use from diff --git a/libjava/classpath/java/io/DeleteFileHelper.java b/libjava/classpath/java/io/DeleteFileHelper.java index d73628c..6e33adc 100644 --- a/libjava/classpath/java/io/DeleteFileHelper.java +++ b/libjava/classpath/java/io/DeleteFileHelper.java @@ -1,5 +1,5 @@ /* DeleteFileHelper.java -- Helper class to delete files on VM exit - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -40,22 +40,22 @@ package java.io; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; -import java.util.Iterator; /** * @author Guilhem Lavaux (guilhem@kaffe.org) * @author Jeroen Frijters (jeroen@sumatra.nl) * @author Michael Koch (konqueror@gmx.de) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) */ final class DeleteFileHelper extends Thread { - private static ArrayList filesToDelete; + private static ArrayList<File> filesToDelete; static synchronized void add(File file) { if (filesToDelete == null) { - filesToDelete = new ArrayList(); + filesToDelete = new ArrayList<File>(); AccessController.doPrivileged(new PrivilegedAction() { @@ -81,13 +81,10 @@ final class DeleteFileHelper extends Thread private static synchronized void deleteFiles() { - Iterator it = filesToDelete.iterator(); - - while (it.hasNext()) + for (File file : filesToDelete) { try { - File file = (File) it.next(); file.delete(); } catch (Exception e) diff --git a/libjava/classpath/java/io/File.java b/libjava/classpath/java/io/File.java index ce56876..5d1b3ec 100644 --- a/libjava/classpath/java/io/File.java +++ b/libjava/classpath/java/io/File.java @@ -60,7 +60,7 @@ import java.net.URL; * @author Aaron M. Renn (arenn@urbanophile.com) * @author Tom Tromey (tromey@cygnus.com) */ -public class File implements Serializable, Comparable +public class File implements Serializable, Comparable<File> { private static final long serialVersionUID = 301077366599181567L; @@ -286,7 +286,8 @@ public class File implements Serializable, Comparable // example, is a valid and minimal path). if (plen > 1 && p.charAt (plen - 1) == separatorChar) { - if (! (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':')) + if (! (separatorChar == '\\' && ((plen == 3 && p.charAt(1) == ':') + || (plen == 2 && p.charAt(0) == separatorChar)))) return p.substring (0, plen - 1); } else @@ -303,7 +304,16 @@ public class File implements Serializable, Comparable { dupIndex++; if (dupIndex == plen) - return newpath.toString(); + { + if ((separatorChar == '\\' + && newpath.length() == 2 + && newpath.charAt(1) == ':') + || (separatorChar != '\\' && newpath.length() == 0)) + { + newpath.append(separatorChar); + } + return newpath.toString(); + } } newpath.append(separatorChar); last = dupIndex; @@ -315,7 +325,9 @@ public class File implements Serializable, Comparable int end; if (plen > 1 && p.charAt (plen - 1) == separatorChar) { - if (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':') + if (separatorChar == '\\' + && ((plen == 3 && p.charAt(1) == ':') + || (plen == 2 && p.charAt(0) == separatorChar))) end = plen; else end = plen - 1; @@ -427,45 +439,8 @@ public class File implements Serializable, Comparable { if (isAbsolute()) return path; - else if (separatorChar == '\\' - && path.length() > 0 && path.charAt (0) == '\\') - { - // On Windows, even if the path starts with a '\\' it is not - // really absolute until we prefix the drive specifier from - // the current working directory to it. - return System.getProperty ("user.dir").substring (0, 2) + path; - } - else if (separatorChar == '\\' - && path.length() > 1 && path.charAt (1) == ':' - && ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z') - || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z'))) - { - // On Windows, a process has a current working directory for - // each drive and a path like "G:foo\bar" would mean the - // absolute path "G:\wombat\foo\bar" if "\wombat" is the - // working directory on the G drive. - String drvDir = null; - try - { - drvDir = new File (path.substring (0, 2)).getCanonicalPath(); - } - catch (IOException e) - { - drvDir = path.substring (0, 2) + "\\"; - } - - // Note: this would return "C:\\." for the path "C:.", if "\" - // is the working folder on the C drive, but this is - // consistent with what Sun's JRE 1.4.1.01 actually returns! - if (path.length() > 2) - return drvDir + '\\' + path.substring (2, path.length()); - else - return drvDir; - } - else if (path.equals("")) - return System.getProperty ("user.dir"); else - return System.getProperty ("user.dir") + separatorChar + path; + return VMFile.getAbsolutePath(path); } /** @@ -657,15 +632,7 @@ public class File implements Serializable, Comparable */ public boolean isAbsolute() { - if (separatorChar == '\\') - return path.startsWith(dupSeparator) || - (path.length() > 2 && - ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') || - (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) && - path.charAt(1) == ':' && - path.charAt(2) == '\\'); - else - return path.startsWith(separator); + return VMFile.isAbsolute(path); } /** @@ -787,8 +754,9 @@ public class File implements Serializable, Comparable String files[] = VMFile.list(path); // Check if an error occured in listInternal(). + // This is an unreadable directory, pretend there is nothing inside. if (files == null) - return null; + return new String[0]; if (filter == null) return files; @@ -998,14 +966,7 @@ public class File implements Serializable, Comparable */ public URL toURL() throws MalformedURLException { - // On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt", - // while on UNIX, it returns URLs of the form "file:/foo/bar.txt". - if (separatorChar == '\\') - return new URL ("file:/" + getAbsolutePath().replace ('\\', '/') - + (isDirectory() ? "/" : "")); - else - return new URL ("file:" + getAbsolutePath() - + (isDirectory() ? "/" : "")); + return VMFile.toURL(this); } @@ -1292,32 +1253,6 @@ public class File implements Serializable, Comparable } /** - * This method compares the specified <code>Object</code> to this one - * to test for equality. It does this by comparing the canonical path names - * of the files. This method is identical to <code>compareTo(File)</code> - * except that if the <code>Object</code> passed to it is not a - * <code>File</code>, it throws a <code>ClassCastException</code> - * <p> - * The canonical paths of the files are determined by calling the - * <code>getCanonicalPath</code> method on each object. - * <p> - * This method returns a 0 if the specified <code>Object</code> is equal - * to this one, a negative value if it is less than this one - * a positive value if it is greater than this one. - * - * @return An integer as described above - * - * @exception ClassCastException If the passed <code>Object</code> is - * not a <code>File</code> - * - * @since 1.2 - */ - public int compareTo(Object obj) - { - return compareTo((File) obj); - } - - /** * This method renames the file represented by this object to the path * of the file represented by the argument <code>File</code>. * diff --git a/libjava/classpath/java/io/FileDescriptor.java b/libjava/classpath/java/io/FileDescriptor.java index d300c9c..cf9ff20 100644 --- a/libjava/classpath/java/io/FileDescriptor.java +++ b/libjava/classpath/java/io/FileDescriptor.java @@ -39,7 +39,7 @@ exception statement from your version. */ package java.io; -import gnu.java.nio.channels.FileChannelImpl; +import gnu.java.nio.FileChannelImpl; import java.nio.channels.ByteChannel; import java.nio.channels.FileChannel; @@ -133,7 +133,8 @@ public final class FileDescriptor * native file handle, <code>false</code> otherwise */ public boolean valid () - { - return channel != null && channel.isOpen(); + { + ByteChannel c = channel; + return (c != null) && (c.isOpen()); } } diff --git a/libjava/classpath/java/io/FileInputStream.java b/libjava/classpath/java/io/FileInputStream.java index 8ca38b0..8217668 100644 --- a/libjava/classpath/java/io/FileInputStream.java +++ b/libjava/classpath/java/io/FileInputStream.java @@ -38,8 +38,9 @@ exception statement from your version. */ package java.io; -import gnu.java.nio.channels.FileChannelImpl; +import gnu.java.nio.FileChannelImpl; +import java.nio.ByteBuffer; import java.nio.channels.FileChannel; /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 @@ -107,7 +108,20 @@ public class FileInputStream extends InputStream if (s != null) s.checkRead(file.getPath()); - ch = FileChannelImpl.create(file, FileChannelImpl.READ); + try + { + ch = FileChannelImpl.create(file, FileChannelImpl.READ); + } + catch (FileNotFoundException fnfe) + { + throw fnfe; + } + catch (IOException ioe) + { + FileNotFoundException fnfe = new FileNotFoundException(file.getPath()); + fnfe.initCause(ioe); + throw fnfe; + } } /** @@ -266,7 +280,7 @@ public class FileInputStream extends InputStream || offset + len > buf.length) throw new ArrayIndexOutOfBoundsException(); - return ch.read(buf, offset, len); + return ch.read(ByteBuffer.wrap(buf, offset, len)); } /** diff --git a/libjava/classpath/java/io/FileOutputStream.java b/libjava/classpath/java/io/FileOutputStream.java index 10ea6b5..d7561a9 100644 --- a/libjava/classpath/java/io/FileOutputStream.java +++ b/libjava/classpath/java/io/FileOutputStream.java @@ -38,8 +38,9 @@ exception statement from your version. */ package java.io; -import gnu.java.nio.channels.FileChannelImpl; +import gnu.java.nio.FileChannelImpl; +import java.nio.ByteBuffer; import java.nio.channels.FileChannel; /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 @@ -155,10 +156,23 @@ public class FileOutputStream extends OutputStream if (s != null) s.checkWrite(file.getPath()); - ch = FileChannelImpl.create(file, (append - ? FileChannelImpl.WRITE - | FileChannelImpl.APPEND - : FileChannelImpl.WRITE)); + try + { + ch = FileChannelImpl.create(file, (append + ? FileChannelImpl.WRITE + | FileChannelImpl.APPEND + : FileChannelImpl.WRITE)); + } + catch (FileNotFoundException fnfe) + { + throw fnfe; + } + catch (IOException ioe) + { + FileNotFoundException fnfe = new FileNotFoundException(file.getPath()); + fnfe.initCause(ioe); + throw fnfe; + } } /** @@ -266,7 +280,7 @@ public class FileOutputStream extends OutputStream || offset + len > buf.length) throw new ArrayIndexOutOfBoundsException (); - ch.write (buf, offset, len); + ch.write(ByteBuffer.wrap(buf, offset, len)); } /** diff --git a/libjava/classpath/java/io/InputStreamReader.java b/libjava/classpath/java/io/InputStreamReader.java index 936a03c..6c5297f 100644 --- a/libjava/classpath/java/io/InputStreamReader.java +++ b/libjava/classpath/java/io/InputStreamReader.java @@ -135,6 +135,16 @@ public class InputStreamReader extends Reader private boolean hasSavedSurrogate = false; /** + * A byte array to be reused in read(byte[], int, int). + */ + private byte[] bytesCache; + + /** + * Locks the bytesCache above in read(byte[], int, int). + */ + private Object cacheLock = new Object(); + + /** * This method initializes a new instance of <code>InputStreamReader</code> * to read from the specified stream using the default encoding. * @@ -355,9 +365,21 @@ public class InputStreamReader extends Reader throw new IOException("Reader has been closed"); if (isDone) return -1; - if(decoder != null){ - int totalBytes = (int)((double)length * maxBytesPerChar); - byte[] bytes = new byte[totalBytes]; + if(decoder != null) + { + int totalBytes = (int)((double) length * maxBytesPerChar); + if (byteBuffer != null) + totalBytes = Math.max(totalBytes, byteBuffer.remaining()); + byte[] bytes; + // Fetch cached bytes array if available and big enough. + synchronized(cacheLock) + { + bytes = bytesCache; + if (bytes == null || bytes.length < totalBytes) + bytes = new byte[totalBytes]; + else + bytesCache = null; + } int remaining = 0; if(byteBuffer != null) @@ -410,12 +432,40 @@ public class InputStreamReader extends Reader byteBuffer = null; read = cb.position() - startPos; - return (read <= 0) ? -1 : read; - } else { - byte[] bytes = new byte[length]; + + // Put cached bytes array back if we are finished and the cache + // is null or smaller than the used bytes array. + synchronized (cacheLock) + { + if (byteBuffer == null + && (bytesCache == null || bytesCache.length < bytes.length)) + bytesCache = bytes; + } + return (read <= 0) ? -1 : read; + } + else + { + byte[] bytes; + // Fetch cached bytes array if available and big enough. + synchronized (cacheLock) + { + bytes = bytesCache; + if (bytes == null || length < bytes.length) + bytes = new byte[length]; + else + bytesCache = null; + } + int read = in.read(bytes); for(int i=0;i<read;i++) buf[offset+i] = (char)(bytes[i]&0xFF); + + // Put back byte array into cache if appropriate. + synchronized (cacheLock) + { + if (bytesCache == null || bytesCache.length < bytes.length) + bytesCache = bytes; + } return read; } } diff --git a/libjava/classpath/java/io/ObjectInputStream.java b/libjava/classpath/java/io/ObjectInputStream.java index a37ad73..d6c1406 100644 --- a/libjava/classpath/java/io/ObjectInputStream.java +++ b/libjava/classpath/java/io/ObjectInputStream.java @@ -39,7 +39,7 @@ exception statement from your version. */ package java.io; -import gnu.java.io.ObjectIdentityWrapper; +import gnu.classpath.VMStackWalker; import java.lang.reflect.Array; import java.lang.reflect.Constructor; @@ -55,6 +55,13 @@ import java.util.Iterator; import java.util.TreeSet; import java.util.Vector; +/** + * @author Tom Tromey (tromey@redhat.com) + * @author Jeroen Frijters (jeroen@frijters.net) + * @author Guilhem Lavaux (guilhem@kaffe.org) + * @author Michael Koch (konqueror@gmx.de) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants { @@ -97,8 +104,8 @@ public class ObjectInputStream extends InputStream this.blockDataInput = new DataInputStream(this); this.realInputStream = new DataInputStream(in); this.nextOID = baseWireHandle; - this.objectLookupTable = new Hashtable(); - this.classLookupTable = new Hashtable(); + this.objectLookupTable = new Vector<Object>(); + this.classLookupTable = new Hashtable<Class,ObjectStreamClass>(); setBlockDataMode(true); readStreamHeader(); } @@ -197,10 +204,9 @@ public class ObjectInputStream extends InputStream case TC_REFERENCE: { if(dump) dumpElement("REFERENCE "); - Integer oid = new Integer(this.realInputStream.readInt()); - if(dump) dumpElementln(Integer.toHexString(oid.intValue())); - ret_val = ((ObjectIdentityWrapper) - this.objectLookupTable.get(oid)).object; + int oid = realInputStream.readInt(); + if(dump) dumpElementln(Integer.toHexString(oid)); + ret_val = lookupHandle(oid); break; } @@ -348,12 +354,12 @@ public class ObjectInputStream extends InputStream int handle = assignNewHandle(obj); Object prevObject = this.currentObject; ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass; - TreeSet prevObjectValidators = this.currentObjectValidators; + TreeSet<ValidatorAndPriority> prevObjectValidators = + this.currentObjectValidators; this.currentObject = obj; this.currentObjectValidators = null; - ObjectStreamClass[] hierarchy = - inputGetObjectStreamClasses(clazz); + ObjectStreamClass[] hierarchy = hierarchy(clazz); for (int i = 0; i < hierarchy.length; i++) { @@ -539,8 +545,6 @@ public class ObjectInputStream extends InputStream flags, fields); assignNewHandle(osc); - ClassLoader callersClassLoader = currentLoader(); - for (int i = 0; i < field_count; i++) { if(dump) dumpElement(" TYPE CODE="); @@ -560,12 +564,17 @@ public class ObjectInputStream extends InputStream class_name = String.valueOf(type_code); fields[i] = - new ObjectStreamField(field_name, class_name, callersClassLoader); + new ObjectStreamField(field_name, class_name); } /* Now that fields have been read we may resolve the class * (and read annotation if needed). */ Class clazz = resolveClass(osc); + ClassLoader loader = clazz.getClassLoader(); + for (int i = 0; i < field_count; i++) + { + fields[i].resolveType(loader); + } boolean oldmode = setBlockDataMode(true); osc.setClass(clazz, lookupClass(clazz.getSuperclass())); classLookupTable.put(clazz, osc); @@ -753,7 +762,7 @@ public class ObjectInputStream extends InputStream + "ObjectInputValidation object"); if (currentObjectValidators == null) - currentObjectValidators = new TreeSet(); + currentObjectValidators = new TreeSet<ValidatorAndPriority>(); currentObjectValidators.add(new ValidatorAndPriority(validator, priority)); } @@ -775,7 +784,7 @@ public class ObjectInputStream extends InputStream * * @see java.io.ObjectOutputStream#annotateClass (java.lang.Class) */ - protected Class resolveClass(ObjectStreamClass osc) + protected Class<?> resolveClass(ObjectStreamClass osc) throws ClassNotFoundException, IOException { String name = osc.getName(); @@ -814,7 +823,7 @@ public class ObjectInputStream extends InputStream */ private ClassLoader currentLoader() { - return VMObjectInputStream.currentClassLoader(); + return VMStackWalker.firstNonNullClassLoader(); } /** @@ -842,41 +851,20 @@ public class ObjectInputStream extends InputStream } /** - * Reconstruct class hierarchy the same way - * {@link java.io.ObjectStreamClass#getObjectStreamClasses(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. + * Reconstruct class hierarchy the same way {@link + * java.io.ObjectStreamClass#hierarchy} does but using lookupClass + * instead of ObjectStreamClass.lookup. * * @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) - { + private ObjectStreamClass[] hierarchy(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; - } + return osc == null ? new ObjectStreamClass[0] : osc.hierarchy(); } /** @@ -898,12 +886,12 @@ public class ObjectInputStream extends InputStream } - protected Class resolveProxyClass(String[] intfs) + protected Class<?> resolveProxyClass(String[] intfs) throws IOException, ClassNotFoundException { ClassLoader cl = currentLoader(); - Class[] clss = new Class[intfs.length]; + Class<?>[] clss = new Class<?>[intfs.length]; if(cl == null) { for (int i = 0; i < intfs.length; i++) @@ -1560,9 +1548,47 @@ public class ObjectInputStream extends InputStream */ private int assignNewHandle(Object obj) { - this.objectLookupTable.put(new Integer(this.nextOID), - new ObjectIdentityWrapper(obj)); - return this.nextOID++; + int handle = this.nextOID; + this.nextOID = handle + 1; + rememberHandle(obj,handle); + return handle; + } + + /** + * Remember the object associated with the given handle. + * + * @param obj an object + * + * @param handle a handle, must be >= baseWireHandle + * + * @see #lookupHandle + */ + private void rememberHandle(Object obj, int handle) + { + Vector olt = this.objectLookupTable; + handle = handle - baseWireHandle; + + if (olt.size() <= handle) + olt.setSize(handle + 1); + + olt.set(handle, obj); + } + + /** + * Look up the object associated with a given handle. + * + * @param handle a handle, must be >= baseWireHandle + * + * @return the object remembered for handle or null if none. + * + * @see #rememberHandle + */ + private Object lookupHandle(int handle) + { + Vector olt = this.objectLookupTable; + handle = handle - baseWireHandle; + Object result = handle < olt.size() ? olt.get(handle) : null; + return result; } private Object processResolution(ObjectStreamClass osc, Object obj, int handle) @@ -1596,9 +1622,7 @@ public class ObjectInputStream extends InputStream if (this.resolveEnabled) obj = resolveObject(obj); - this.objectLookupTable.put(new Integer(handle), - new ObjectIdentityWrapper(obj)); - + rememberHandle(obj, handle); return obj; } @@ -1875,10 +1899,10 @@ public class ObjectInputStream extends InputStream { try { - Iterator it = currentObjectValidators.iterator(); + Iterator<ValidatorAndPriority> it = currentObjectValidators.iterator(); while(it.hasNext()) { - ValidatorAndPriority vap = (ValidatorAndPriority) it.next(); + ValidatorAndPriority vap = it.next(); ObjectInputValidation validator = vap.validator; validator.validateObject(); } @@ -1931,13 +1955,13 @@ public class ObjectInputStream extends InputStream private boolean useSubclassMethod; private int nextOID; private boolean resolveEnabled; - private Hashtable objectLookupTable; + private Vector<Object> objectLookupTable; private Object currentObject; private ObjectStreamClass currentObjectStreamClass; - private TreeSet currentObjectValidators; + private TreeSet<ValidatorAndPriority> currentObjectValidators; private boolean readDataFromBlock; private boolean fieldsAlreadyRead; - private Hashtable classLookupTable; + private Hashtable<Class,ObjectStreamClass> classLookupTable; private GetField prereadFields; private static boolean dump; diff --git a/libjava/classpath/java/io/ObjectOutputStream.java b/libjava/classpath/java/io/ObjectOutputStream.java index 80d196b..c3c3df9 100644 --- a/libjava/classpath/java/io/ObjectOutputStream.java +++ b/libjava/classpath/java/io/ObjectOutputStream.java @@ -39,7 +39,7 @@ exception statement from your version. */ package java.io; -import gnu.java.io.ObjectIdentityWrapper; +import gnu.java.io.ObjectIdentityMap2Int; import gnu.java.lang.reflect.TypeSignature; import gnu.java.security.action.SetAccessibleAction; @@ -47,8 +47,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.security.AccessController; -import java.util.Hashtable; + /** * An <code>ObjectOutputStream</code> can be used to write objects @@ -115,6 +114,11 @@ import java.util.Hashtable; * @see java.io.Externalizable * @see java.io.ObjectInputStream * @see java.io.Serializable + * @author Tom Tromey (tromey@redhat.com) + * @author Jeroen Frijters (jeroen@frijters.net) + * @author Guilhem Lavaux (guilhem@kaffe.org) + * @author Michael Koch (konqueror@gmx.de) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) */ public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants @@ -140,7 +144,7 @@ public class ObjectOutputStream extends OutputStream replacementEnabled = false; isSerializing = false; nextOID = baseWireHandle; - OIDLookupTable = new Hashtable(); + OIDLookupTable = new ObjectIdentityMap2Int(); protocolVersion = defaultProtocolVersion; useSubclassMethod = false; writeStreamHeader(); @@ -207,11 +211,11 @@ public class ObjectOutputStream extends OutputStream break; } - Integer handle = findHandle(obj); - if (handle != null) + int handle = findHandle(obj); + if (handle >= 0) { realOutput.writeByte(TC_REFERENCE); - realOutput.writeInt(handle.intValue()); + realOutput.writeInt(handle); break; } @@ -225,7 +229,7 @@ public class ObjectOutputStream extends OutputStream writeObject (osc); } else - { + {System.err.println("1"); realOutput.writeByte(TC_PROXYCLASSDESC); Class[] intfs = cl.getInterfaces(); realOutput.writeInt(intfs.length); @@ -338,8 +342,7 @@ public class ObjectOutputStream extends OutputStream Object prevObject = this.currentObject; ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass; currentObject = obj; - ObjectStreamClass[] hierarchy = - ObjectStreamClass.getObjectStreamClasses(clazz); + ObjectStreamClass[] hierarchy = osc.hierarchy(); for (int i = 0; i < hierarchy.length; i++) { @@ -604,11 +607,11 @@ public class ObjectOutputStream extends OutputStream * * @see ObjectInputStream#resolveClass(java.io.ObjectStreamClass) */ - protected void annotateClass(Class cl) throws IOException + protected void annotateClass(Class<?> cl) throws IOException { } - protected void annotateProxyClass(Class cl) throws IOException + protected void annotateProxyClass(Class<?> cl) throws IOException { } @@ -1104,17 +1107,16 @@ public class ObjectOutputStream extends OutputStream // lookup the handle for OBJ, return null if OBJ doesn't have a // handle yet - private Integer findHandle(Object obj) + private int findHandle(Object obj) { - return (Integer)OIDLookupTable.get(new ObjectIdentityWrapper(obj)); + return OIDLookupTable.get(obj); } // assigns the next availible handle to OBJ private int assignNewHandle(Object obj) { - OIDLookupTable.put(new ObjectIdentityWrapper(obj), - new Integer(nextOID)); + OIDLookupTable.put(obj, nextOID); return nextOID++; } @@ -1216,39 +1218,70 @@ public class ObjectOutputStream extends OutputStream { ObjectStreamField[] fields = osc.fields; boolean oldmode = setBlockDataMode(false); - String field_name; - Class type; - for (int i = 0; i < fields.length; i++) + try { - field_name = fields[i].getName(); - type = fields[i].getType(); - - if (dump) - dumpElementln ("WRITE FIELD: " + field_name + " type=" + type); - - if (type == Boolean.TYPE) - realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name)); - else if (type == Byte.TYPE) - realOutput.writeByte(getByteField(obj, osc.forClass(), field_name)); - else if (type == Character.TYPE) - realOutput.writeChar(getCharField(obj, osc.forClass(), field_name)); - else if (type == Double.TYPE) - realOutput.writeDouble(getDoubleField(obj, osc.forClass(), field_name)); - else if (type == Float.TYPE) - realOutput.writeFloat(getFloatField(obj, osc.forClass(), field_name)); - else if (type == Integer.TYPE) - realOutput.writeInt(getIntField(obj, osc.forClass(), field_name)); - else if (type == Long.TYPE) - realOutput.writeLong(getLongField(obj, osc.forClass(), field_name)); - else if (type == Short.TYPE) - realOutput.writeShort(getShortField(obj, osc.forClass(), field_name)); - else - writeObject(getObjectField(obj, osc.forClass(), field_name, - fields[i].getTypeString ())); + writeFields(obj,fields); + } + catch (IllegalArgumentException _) + { + InvalidClassException e = new InvalidClassException + ("writing fields of class " + osc.forClass().getName()); + e.initCause(_); + throw e; } + catch (IOException e) + { + throw e; + } + catch (Exception _) + { + IOException e = new IOException("Unexpected exception " + _); + e.initCause(_); + throw(e); + } + setBlockDataMode(oldmode); } + + + /** + * Helper function for writeFields(Object,ObjectStreamClass): write + * fields from given fields array. Pass exception on. + * + * @param obj the object to be written + * + * @param fields the fields of obj to be written. + */ + private void writeFields(Object obj, ObjectStreamField[] fields) + throws + IllegalArgumentException, IllegalAccessException, IOException + { + for (int i = 0; i < fields.length; i++) + { + ObjectStreamField osf = fields[i]; + Field field = osf.field; + + if (DEBUG && dump) + dumpElementln ("WRITE FIELD: " + osf.getName() + " type=" + osf.getType()); + + switch (osf.getTypeCode()) + { + case 'Z': realOutput.writeBoolean(field.getBoolean(obj)); break; + case 'B': realOutput.writeByte (field.getByte (obj)); break; + case 'S': realOutput.writeShort (field.getShort (obj)); break; + case 'C': realOutput.writeChar (field.getChar (obj)); break; + case 'I': realOutput.writeInt (field.getInt (obj)); break; + case 'F': realOutput.writeFloat (field.getFloat (obj)); break; + case 'J': realOutput.writeLong (field.getLong (obj)); break; + case 'D': realOutput.writeDouble (field.getDouble (obj)); break; + case 'L': + case '[': writeObject (field.get (obj)); break; + default: + throw new IOException("Unexpected type code " + osf.getTypeCode()); + } + } + } // Toggles writing primitive data to block-data buffer. @@ -1307,248 +1340,6 @@ public class ObjectOutputStream extends OutputStream } } - private boolean getBooleanField(Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField(klass, field_name); - boolean b = f.getBoolean(obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private byte getByteField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - byte b = f.getByte (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private char getCharField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - char b = f.getChar (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private double getDoubleField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - double b = f.getDouble (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private float getFloatField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - float b = f.getFloat (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private int getIntField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - int b = f.getInt (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private long getLongField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - long b = f.getLong (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private short getShortField (Object obj, Class klass, String field_name) - throws IOException - { - try - { - Field f = getField (klass, field_name); - short b = f.getShort (obj); - return b; - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException - ("invalid requested type for field " + field_name + " in class " + klass.getName()); - } - catch (IOException e) - { - throw e; - } - catch (Exception _) - { - throw new IOException("Unexpected exception " + _); - } - } - - private Object getObjectField (Object obj, Class klass, String field_name, - String type_code) throws IOException - { - try - { - Field f = getField (klass, field_name); - ObjectStreamField of = new ObjectStreamField(f.getName(), f.getType()); - - /* if of is primitive something went wrong - * in the check for primitive classes in writeFields. - */ - if (of.isPrimitive()) - throw new InvalidClassException - ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field is primitive"); - - if (!of.getTypeString().equals(type_code)) - throw new InvalidClassException - ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field " + of + " has type string " + of.getTypeString() + " instead of " + type_code); - - Object o = f.get (obj); - // FIXME: We should check the type_code here - return o; - } - catch (IOException e) - { - throw e; - } - catch (Exception e) - { - throw new IOException (); - } - } - - private Field getField (Class klass, String name) - throws java.io.InvalidClassException - { - try - { - final Field f = klass.getDeclaredField(name); - setAccessible.setMember(f); - AccessController.doPrivileged(setAccessible); - return f; - } - catch (java.lang.NoSuchFieldException e) - { - throw new InvalidClassException - ("no field called " + name + " in class " + klass.getName()); - } - } - private void dumpElementln (String msg) { for (int i = 0; i < depth; i++) @@ -1576,7 +1367,7 @@ public class ObjectOutputStream extends OutputStream private boolean replacementEnabled; private boolean isSerializing; private int nextOID; - private Hashtable OIDLookupTable; + private ObjectIdentityMap2Int OIDLookupTable; private int protocolVersion; private boolean useSubclassMethod; private SetAccessibleAction setAccessible = new SetAccessibleAction(); diff --git a/libjava/classpath/java/io/ObjectStreamClass.java b/libjava/classpath/java/io/ObjectStreamClass.java index abb26d8..52a1ad4 100644 --- a/libjava/classpath/java/io/ObjectStreamClass.java +++ b/libjava/classpath/java/io/ObjectStreamClass.java @@ -1,6 +1,6 @@ /* ObjectStreamClass.java -- Class used to write class information about serialized objects. - Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -59,8 +59,14 @@ import java.security.Security; import java.util.Arrays; import java.util.Comparator; import java.util.Hashtable; -import java.util.Vector; +/** + * @author Tom Tromey (tromey@redhat.com) + * @author Jeroen Frijters (jeroen@frijters.net) + * @author Guilhem Lavaux (guilhem@kaffe.org) + * @author Michael Koch (konqueror@gmx.de) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + */ public class ObjectStreamClass implements Serializable { static final ObjectStreamField[] INVALID_FIELDS = new ObjectStreamField[0]; @@ -80,7 +86,7 @@ public class ObjectStreamClass implements Serializable * * @see java.io.Serializable */ - public static ObjectStreamClass lookup(Class cl) + public static ObjectStreamClass lookup(Class<?> cl) { if (cl == null) return null; @@ -132,7 +138,7 @@ public class ObjectStreamClass implements Serializable * * @see java.io.ObjectInputStream */ - public Class forClass() + public Class<?> forClass() { return clazz; } @@ -235,37 +241,45 @@ public class ObjectStreamClass implements Serializable return superClass; } - - // returns an array of ObjectStreamClasses that represent the super - // classes of CLAZZ and CLAZZ itself in order from most super to - // CLAZZ. ObjectStreamClass[0] is the highest superclass of CLAZZ - // that is serializable. - static ObjectStreamClass[] getObjectStreamClasses(Class clazz) + /** + * returns an array of ObjectStreamClasses that represent the super + * classes of the class represented by this and the class + * represented by this itself in order from most super to this. + * ObjectStreamClass[0] is the highest superclass of this that is + * serializable. + * + * The result of consecutive calls this hierarchy() will be the same + * array instance. + * + * @return an array of ObjectStreamClass representing the + * super-class hierarchy of serializable classes. + */ + ObjectStreamClass[] hierarchy() { - ObjectStreamClass osc = ObjectStreamClass.lookup(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; + ObjectStreamClass[] result = hierarchy; + if (result == null) + { + int d = 0; + + for(ObjectStreamClass osc = this; osc != null; osc = osc.getSuper()) + d++; + + result = new ObjectStreamClass[d]; + + for (ObjectStreamClass osc = this; osc != null; osc = osc.getSuper()) + { + result[--d] = osc; + } + + hierarchy = result; } + return result; } + /** + * Cache for hierarchy() result. + */ + private ObjectStreamClass[] hierarchy = null; // Returns an integer that consists of bit-flags that indicate // properties of the class represented by this ObjectStreamClass. @@ -298,7 +312,7 @@ public class ObjectStreamClass implements Serializable * already set UID is found. */ void setClass(Class cl, ObjectStreamClass superClass) throws InvalidClassException - { + {hierarchy = null; this.clazz = cl; cacheMethods(); @@ -309,8 +323,8 @@ public class ObjectStreamClass implements Serializable else { // Check that the actual UID of the resolved class matches the UID from - // the stream. - if (uid != class_uid) + // the stream. Mismatches for array classes are ignored. + if (!cl.isArray() && uid != class_uid) { String msg = cl + ": Local class not compatible: stream serialVersionUID=" @@ -425,6 +439,7 @@ public class ObjectStreamClass implements Serializable void setSuperclass (ObjectStreamClass osc) { superClass = osc; + hierarchy = null; } void calculateOffsets() @@ -547,21 +562,62 @@ outer: return null; } - private void cacheMethods() + /** + * Helper routine to check if a class was loaded by boot or + * application class loader. Classes for which this is not the case + * should not be cached since caching prevent class file garbage + * collection. + * + * @param cl a class + * + * @return true if cl was loaded by boot or application class loader, + * false if cl was loaded by a user class loader. + */ + private static boolean loadedByBootOrApplicationClassLoader(Class cl) { - Method[] methods = forClass().getDeclaredMethods(); + ClassLoader l = cl.getClassLoader(); + return + ( l == null /* boot loader */ ) + || (l == ClassLoader.getSystemClassLoader() /* application loader */); + } - readObjectMethod = findMethod(methods, "readObject", - new Class[] { ObjectInputStream.class }, - Void.TYPE, true); - writeObjectMethod = findMethod(methods, "writeObject", - new Class[] { ObjectOutputStream.class }, - Void.TYPE, true); + static Hashtable methodCache = new Hashtable(); + + static final Class[] readObjectSignature = { ObjectInputStream.class }; + static final Class[] writeObjectSignature = { ObjectOutputStream.class }; - // 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 void cacheMethods() + { + Class cl = forClass(); + Method[] cached = (Method[]) methodCache.get(cl); + if (cached == null) + { + cached = new Method[4]; + Method[] methods = cl.getDeclaredMethods(); + + cached[0] = findMethod(methods, "readObject", + readObjectSignature, + Void.TYPE, true); + cached[1] = findMethod(methods, "writeObject", + writeObjectSignature, + Void.TYPE, true); + + // readResolve and writeReplace can be in parent classes, as long as they + // are accessible from this class. + cached[2] = findAccessibleMethod("readResolve", cl); + cached[3] = findAccessibleMethod("writeReplace", cl); + + /* put in cache if classes not loaded by user class loader. + * For a user class loader, the cache may otherwise grow + * without limit. + */ + if (loadedByBootOrApplicationClassLoader(cl)) + methodCache.put(cl,cached); + } + readObjectMethod = cached[0]; + writeObjectMethod = cached[1]; + readResolveMethod = cached[2]; + writeReplaceMethod = cached[3]; } private ObjectStreamClass(Class cl) @@ -713,152 +769,208 @@ outer: calculateOffsets(); } + static Hashtable uidCache = new Hashtable(); + // 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 + long result = 0; + Long cache = (Long) uidCache.get(cl); + if (cache != null) + result = cache.longValue(); + else { - // 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); + try + { + result = getClassUIDFromField(cl); + } + catch (NoSuchFieldException ignore) + { + try + { + result = calculateClassUID(cl); + } + 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); + } + } + + if (loadedByBootOrApplicationClassLoader(cl)) + uidCache.put(cl,new Long(result)); } - catch (NoSuchFieldException ignore) + return result; + } + + /** + * Search for a serialVersionUID field in the given class and read + * its value. + * + * @return the contents of the serialVersionUID field + * + * @throws NoSuchFieldException if such a field does not exist or is + * not static, not final, not of type Long or not accessible. + */ + long getClassUIDFromField(Class cl) + throws NoSuchFieldException + { + long result; + + 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) + result = suid.getLong(null); + else + throw new NoSuchFieldException(); } catch (IllegalAccessException ignore) { + throw new NoSuchFieldException(); } - // 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; + } - return result; + /** + * Calculate class serial version UID for a class that does not + * define serialVersionUID: + * + * @param cl a class + * + * @return the calculated serial varsion UID. + * + * @throws NoSuchAlgorithmException if SHA algorithm not found + * + * @throws IOException if writing to the DigestOutputStream causes + * an IOException. + */ + long calculateClassUID(Class cl) + throws NoSuchAlgorithmException, IOException + { + long result; + MessageDigest md; + try + { + md = MessageDigest.getInstance("SHA"); } 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); + // 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"); } - catch (IOException ioe) + + 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++) { - throw new RuntimeException(ioe); + 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(); + 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; } /** @@ -948,7 +1060,8 @@ outer: public static final ObjectStreamField[] NO_FIELDS = {}; - private static Hashtable classLookupTable = new Hashtable(); + private static Hashtable<Class,ObjectStreamClass> classLookupTable + = new Hashtable<Class,ObjectStreamClass>(); private static final NullOutputStream nullOutputStream = new NullOutputStream(); private static final Comparator interfaceComparator = new InterfaceComparator(); private static final Comparator memberComparator = new MemberComparator(); @@ -956,7 +1069,7 @@ outer: Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class }; private ObjectStreamClass superClass; - private Class clazz; + private Class<?> clazz; private String name; private long uid; private byte flags; diff --git a/libjava/classpath/java/io/ObjectStreamField.java b/libjava/classpath/java/io/ObjectStreamField.java index 61ccdc7..91f5578 100644 --- a/libjava/classpath/java/io/ObjectStreamField.java +++ b/libjava/classpath/java/io/ObjectStreamField.java @@ -1,5 +1,5 @@ /* ObjectStreamField.java -- Class used to store name and class of fields - Copyright (C) 1998, 1999, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,17 +48,24 @@ import java.security.PrivilegedAction; * This class intends to describe the field of a class for the serialization * subsystem. Serializable fields in a serializable class can be explicitly * exported using an array of ObjectStreamFields. + * + * @author Tom Tromey (tromey@redhat.com) + * @author Jeroen Frijters (jeroen@frijters.net) + * @author Guilhem Lavaux (guilhem@kaffe.org) + * @author Michael Koch (konqueror@gmx.de) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) */ -public class ObjectStreamField implements Comparable +public class ObjectStreamField + implements Comparable<Object> { private String name; - private Class type; + private Class<?> type; private String typename; private int offset = -1; // XXX make sure this is correct private boolean unshared; private boolean persistent = false; private boolean toset = true; - private Field field; + Field field; ObjectStreamField (Field field) { @@ -74,7 +81,7 @@ public class ObjectStreamField implements Comparable * @param name Name of the field to export. * @param type Type of the field in the concerned class. */ - public ObjectStreamField (String name, Class type) + public ObjectStreamField (String name, Class<?> type) { this (name, type, false); } @@ -88,7 +95,7 @@ public class ObjectStreamField implements Comparable * @param type Type of the field in the concerned class. * @param unshared true if field will be unshared, false otherwise. */ - public ObjectStreamField (String name, Class type, boolean unshared) + public ObjectStreamField (String name, Class<?> type, boolean unshared) { if (name == null) throw new NullPointerException(); @@ -111,28 +118,10 @@ public class ObjectStreamField implements Comparable { this.name = name; this.typename = typename; - try - { - type = TypeSignature.getClassForEncoding(typename); - } - catch(ClassNotFoundException e) - { - } } - - /** - * There are many cases you can not get java.lang.Class from typename - * if your context class loader cann not load it, then use typename to - * construct the field. - * - * @param name Name of the field to export. - * @param typename The coded name of the type for this field. - * @param loader The class loader to use to resolve class names. - */ - ObjectStreamField (String name, String typename, ClassLoader loader) + + void resolveType(ClassLoader loader) { - this.name = name; - this.typename = typename; try { type = TypeSignature.getClassForEncoding(typename, true, loader); @@ -141,7 +130,7 @@ public class ObjectStreamField implements Comparable { } } - + /** * This method returns the name of the field represented by the * ObjectStreamField instance. @@ -159,7 +148,7 @@ public class ObjectStreamField implements Comparable * * @return A class representing the type of the field. */ - public Class getType () + public Class<?> getType () { return type; } @@ -347,7 +336,7 @@ public class ObjectStreamField implements Comparable */ void checkFieldType() throws InvalidClassException { - Class ftype = field.getType(); + Class<?> ftype = field.getType(); if (!ftype.isAssignableFrom(type)) throw new InvalidClassException diff --git a/libjava/classpath/java/io/OutputStreamWriter.java b/libjava/classpath/java/io/OutputStreamWriter.java index 5726838..2636340 100644 --- a/libjava/classpath/java/io/OutputStreamWriter.java +++ b/libjava/classpath/java/io/OutputStreamWriter.java @@ -223,6 +223,7 @@ public class OutputStreamWriter extends Writer encoder.onMalformedInput(CodingErrorAction.REPLACE); encoder.onUnmappableCharacter(CodingErrorAction.REPLACE); outputBuffer = CharBuffer.allocate(BUFFER_SIZE); + encodingName = EncodingHelper.getOldCanonical(cs.name()); } /** @@ -240,6 +241,11 @@ public class OutputStreamWriter extends Writer this.out = out; encoder = enc; outputBuffer = CharBuffer.allocate(BUFFER_SIZE); + Charset cs = enc.charset(); + if (cs == null) + encodingName = "US-ASCII"; + else + encodingName = EncodingHelper.getOldCanonical(cs.name()); } /** diff --git a/libjava/classpath/java/io/PipedInputStream.java b/libjava/classpath/java/io/PipedInputStream.java index 523ae2c..c0396d2 100644 --- a/libjava/classpath/java/io/PipedInputStream.java +++ b/libjava/classpath/java/io/PipedInputStream.java @@ -279,6 +279,10 @@ public class PipedInputStream extends InputStream if (closed) throw new IOException ("Pipe closed"); + // Don't block if nothing was requested. + if (len == 0) + return 0; + // If the buffer is empty, wait until there is something in the pipe // to read. try diff --git a/libjava/classpath/java/io/PipedReader.java b/libjava/classpath/java/io/PipedReader.java index 90fc10f..8a3363a 100644 --- a/libjava/classpath/java/io/PipedReader.java +++ b/libjava/classpath/java/io/PipedReader.java @@ -261,6 +261,10 @@ public class PipedReader extends Reader if (closed) throw new IOException ("Pipe closed"); + // Don't block if nothing was requested. + if (len == 0) + return 0; + // If the buffer is empty, wait until there is something in the pipe // to read. try diff --git a/libjava/classpath/java/io/PrintStream.java b/libjava/classpath/java/io/PrintStream.java index 98461db..2d747c8 100644 --- a/libjava/classpath/java/io/PrintStream.java +++ b/libjava/classpath/java/io/PrintStream.java @@ -39,6 +39,9 @@ exception statement from your version. */ package java.io; +import java.util.Locale; +import java.util.Formatter; + import gnu.classpath.SystemProperties; /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 @@ -58,8 +61,9 @@ import gnu.classpath.SystemProperties; * * @author Aaron M. Renn (arenn@urbanophile.com) * @author Tom Tromey (tromey@cygnus.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) */ -public class PrintStream extends FilterOutputStream +public class PrintStream extends FilterOutputStream implements Appendable { /* Notice the implementation is quite similar to OutputStreamWriter. * This leads to some minor duplication, because neither inherits @@ -67,7 +71,7 @@ public class PrintStream extends FilterOutputStream // Line separator string. private static final char[] line_separator - = SystemProperties.getProperty("line.separator").toCharArray(); + = SystemProperties.getProperty("line.separator", "\n").toCharArray(); /** * Encoding name @@ -620,5 +624,51 @@ public class PrintStream extends FilterOutputStream setError (); } } -} // class PrintStream + /** @since 1.5 */ + public PrintStream append(char c) + { + print(c); + return this; + } + + /** @since 1.5 */ + public PrintStream append(CharSequence cs) + { + print(cs == null ? "null" : cs.toString()); + return this; + } + + /** @since 1.5 */ + public PrintStream append(CharSequence cs, int start, int end) + { + print(cs == null ? "null" : cs.subSequence(start, end).toString()); + return this; + } + + /** @since 1.5 */ + public PrintStream printf(String format, Object... args) + { + return format(format, args); + } + + /** @since 1.5 */ + public PrintStream printf(Locale locale, String format, Object... args) + { + return format(locale, format, args); + } + + /** @since 1.5 */ + public PrintStream format(String format, Object... args) + { + return format(Locale.getDefault(), format, args); + } + + /** @since 1.5 */ + public PrintStream format(Locale locale, String format, Object... args) + { + Formatter f = new Formatter(this, locale); + f.format(format, args); + return this; + } +} // class PrintStream diff --git a/libjava/classpath/java/io/PrintWriter.java b/libjava/classpath/java/io/PrintWriter.java index 5667e70..5b4294c 100644 --- a/libjava/classpath/java/io/PrintWriter.java +++ b/libjava/classpath/java/io/PrintWriter.java @@ -1,5 +1,5 @@ /* PrintWriter.java -- prints primitive values and objects to a stream as text - Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation + Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation This file is part of GNU Classpath. @@ -37,6 +37,9 @@ exception statement from your version. */ package java.io; +import java.util.Locale; +import java.util.Formatter; + /* Written using "Java Class Libraries", 2nd edition, plus online * API docs for JDK 1.2 beta from http://www.javasoft.com. * Status: Believed complete and correct. @@ -636,5 +639,52 @@ public class PrintWriter extends Writer { write(str, 0, str.length()); } + + /** @since 1.5 */ + public PrintWriter append(char c) + { + write(c); + return this; + } + + /** @since 1.5 */ + public PrintWriter append(CharSequence cs) + { + write(cs == null ? "null" : cs.toString()); + return this; + } + + /** @since 1.5 */ + public PrintWriter append(CharSequence cs, int start, int end) + { + write(cs == null ? "null" : cs.subSequence(start, end).toString()); + return this; + } + + /** @since 1.5 */ + public PrintWriter printf(String format, Object... args) + { + return format(format, args); + } + + /** @since 1.5 */ + public PrintWriter printf(Locale locale, String format, Object... args) + { + return format(locale, format, args); + } + + /** @since 1.5 */ + public PrintWriter format(String format, Object... args) + { + return format(Locale.getDefault(), format, args); + } + + /** @since 1.5 */ + public PrintWriter format(Locale locale, String format, Object... args) + { + Formatter f = new Formatter(this, locale); + f.format(format, args); + return this; + } } diff --git a/libjava/classpath/java/io/RandomAccessFile.java b/libjava/classpath/java/io/RandomAccessFile.java index 84ee5de..036fc8c 100644 --- a/libjava/classpath/java/io/RandomAccessFile.java +++ b/libjava/classpath/java/io/RandomAccessFile.java @@ -38,7 +38,7 @@ exception statement from your version. */ package java.io; -import gnu.java.nio.channels.FileChannelImpl; +import gnu.java.nio.FileChannelImpl; import java.nio.channels.FileChannel; @@ -58,7 +58,7 @@ import java.nio.channels.FileChannel; * @author Aaron M. Renn (arenn@urbanophile.com) * @author Tom Tromey (tromey@cygnus.com) */ -public class RandomAccessFile implements DataOutput, DataInput +public class RandomAccessFile implements DataOutput, DataInput, Closeable { // The underlying file. @@ -122,7 +122,20 @@ public class RandomAccessFile implements DataOutput, DataInput s.checkWrite(fileName); } - ch = FileChannelImpl.create(file, fdmode); + try + { + ch = FileChannelImpl.create(file, fdmode); + } + catch (FileNotFoundException fnfe) + { + throw fnfe; + } + catch (IOException ioe) + { + FileNotFoundException fnfe = new FileNotFoundException(file.getPath()); + fnfe.initCause(ioe); + throw fnfe; + } fd = new FileDescriptor(ch); if ((fdmode & FileChannelImpl.WRITE) != 0) out = new DataOutputStream (new FileOutputStream (fd)); diff --git a/libjava/classpath/java/io/Reader.java b/libjava/classpath/java/io/Reader.java index 7970d9a..6da1813 100644 --- a/libjava/classpath/java/io/Reader.java +++ b/libjava/classpath/java/io/Reader.java @@ -1,5 +1,5 @@ /* Reader.java -- base class of classes that read input as a stream of chars - Copyright (C) 1998, 1999, 2000, 2003 Free Software Foundation + Copyright (C) 1998, 1999, 2000, 2003, 2004, 2005 Free Software Foundation This file is part of GNU Classpath. @@ -37,6 +37,8 @@ exception statement from your version. */ package java.io; +import java.nio.CharBuffer; + /* Written using "Java Class Libraries", 2nd edition, plus online * API docs for JDK 1.2 beta from http://www.javasoft.com. * Status: Believed complete and correct. @@ -53,7 +55,7 @@ package java.io; * @date April 21, 1998. * @author Aaron M. Renn (arenn@urbanophile.com) */ -public abstract class Reader +public abstract class Reader implements Closeable, Readable { /** * This is the <code>Object</code> used for synchronizing critical code @@ -152,6 +154,19 @@ public abstract class Reader return count > 0 ? buf[0] : -1; } + /** @since 1.5 */ + public int read(CharBuffer buffer) throws IOException + { + // We want to call put(), so we don't manipulate the CharBuffer + // directly. + int rem = buffer.remaining(); + char[] buf = new char[rem]; + int result = read(buf, 0, rem); + if (result != -1) + buffer.put(buf, 0, result); + return result; + } + /** * Closes the stream. Any futher attempts to read from the * stream may generate an <code>IOException</code>. diff --git a/libjava/classpath/java/io/SequenceInputStream.java b/libjava/classpath/java/io/SequenceInputStream.java index 7fefe24..5ff85e9 100644 --- a/libjava/classpath/java/io/SequenceInputStream.java +++ b/libjava/classpath/java/io/SequenceInputStream.java @@ -1,5 +1,5 @@ /* SequenceInputStream.java -- Reads multiple input streams in sequence - Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2001, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -71,8 +71,11 @@ public class SequenceInputStream extends InputStream /** Secondary input stream; not used if constructed w/ enumeration. */ private InputStream in2; - /** The enumeration handle; not used if constructed w/ 2 explicit input streams. */ - private Enumeration e; + /** + * The enumeration handle; not used if constructed w/ 2 explicit + * input streams. + */ + private Enumeration<? extends InputStream> e; /** * This method creates a new <code>SequenceInputStream</code> that obtains @@ -82,10 +85,10 @@ public class SequenceInputStream extends InputStream * @param e An <code>Enumeration</code> that will return a list of * <code>InputStream</code>s to read in sequence */ - public SequenceInputStream(Enumeration e) + public SequenceInputStream(Enumeration<? extends InputStream> e) { this.e = e; - in = (InputStream) e.nextElement(); + in = e.nextElement(); in2 = null; } @@ -207,14 +210,13 @@ public class SequenceInputStream extends InputStream if (e != null) { if (e.hasMoreElements()) - nextIn = (InputStream) e.nextElement(); + nextIn = e.nextElement(); + } + else if (in2 != null) + { + nextIn = in2; + in2 = null; } - else - if (in2 != null) - { - nextIn = in2; - in2 = null; - } return nextIn; } diff --git a/libjava/classpath/java/io/StringWriter.java b/libjava/classpath/java/io/StringWriter.java index a1e9aeb..5a16e63 100644 --- a/libjava/classpath/java/io/StringWriter.java +++ b/libjava/classpath/java/io/StringWriter.java @@ -183,6 +183,27 @@ public class StringWriter extends Writer buffer.append(str.substring(offset, offset + len)); } + /** @since 1.5 */ + public StringWriter append(char c) + { + write(c); + return this; + } + + /** @since 1.5 */ + public StringWriter append(CharSequence cs) + { + write(cs == null ? "null" : cs.toString()); + return this; + } + + /** @since 1.5 */ + public StringWriter append(CharSequence cs, int start, int end) + { + write(cs == null ? "null" : cs.subSequence(start, end).toString()); + return this; + } + /** * This is the <code>StringBuffer</code> that we use to store bytes that * are written. diff --git a/libjava/classpath/java/io/Writer.java b/libjava/classpath/java/io/Writer.java index f153e31..660b690 100644 --- a/libjava/classpath/java/io/Writer.java +++ b/libjava/classpath/java/io/Writer.java @@ -53,7 +53,7 @@ package java.io; * @author Aaron M. Renn (arenn@urbanophile.com) * @author Per Bothner (bothner@cygnus.com) */ -public abstract class Writer +public abstract class Writer implements Appendable, Closeable, Flushable { /** * This is the object used to synchronize criticial code sections for @@ -188,5 +188,24 @@ public abstract class Writer write(buf, 0, len); } -} // class Writer + /** @since 1.5 */ + public Writer append(char c) throws IOException + { + write(c); + return this; + } + /** @since 1.5 */ + public Writer append(CharSequence cs) throws IOException + { + write(cs == null ? "null" : cs.toString()); + return this; + } + + /** @since 1.5 */ + public Writer append(CharSequence cs, int start, int end) throws IOException + { + write(cs == null ? "null" : cs.subSequence(start, end).toString()); + return this; + } +} diff --git a/libjava/classpath/java/io/class-dependencies.conf b/libjava/classpath/java/io/class-dependencies.conf new file mode 100644 index 0000000..633bb17 --- /dev/null +++ b/libjava/classpath/java/io/class-dependencies.conf @@ -0,0 +1,100 @@ +# This property file contains dependencies of classes, methods, and +# field on other methods or classes. +# +# Syntax: +# +# <used>: <needed 1> [... <needed N>] +# +# means that when <used> is included, <needed 1> (... <needed N>) must +# be included as well. +# +# <needed X> and <used> are of the form +# +# <class.methodOrField(signature)> +# +# or just +# +# <class> +# +# Within dependencies, variables can be used. A variable is defined as +# follows: +# +# {variable}: value1 value2 ... value<n> +# +# variables can be used on the right side of dependencies as follows: +# +# <used>: com.bla.blu.{variable}.Class.m()V +# +# The use of the variable will expand to <n> dependencies of the form +# +# <used>: com.bla.blu.value1.Class.m()V +# <used>: com.bla.blu.value2.Class.m()V +# ... +# <used>: com.bla.blu.value<n>.Class.m()V +# +# Variables can be redefined when building a system to select the +# required support for features like encodings, protocols, etc. +# +# Hints: +# +# - For methods and fields, the signature is mandatory. For +# specification, please see the Java Virtual Machine Specification by +# SUN. Unlike in the spec, field signatures (types) are in brackets. +# +# - Package names must be separated by '/' (and not '.'). E.g., +# java/lang/Class (this is necessary, because the '.' is used to +# separate method or field names from classes) +# +# - In case <needed> refers to a class, only the class itself will be +# included in the resulting binary, NOT necessarily all its methods +# and fields. If you want to refer to all methods and fields, you can +# write class.* as an abbreviation. +# +# - Abbreviations for packages are also possible: my/package/* means all +# methods and fields of all classes in my/package. +# +# - A line with a trailing '\' continues in the next line. + +java/io/File: \ + java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \ + java/lang/InternalError.<init>(Ljava/lang/String;)V \ + java/io/IOException.<init>(Ljava/lang/String;)V \ + java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V + +java/io/FileDescriptor: \ + java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \ + java/lang/InternalError.<init>(Ljava/lang/String;)V \ + java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V \ + java/io/IOException.<init>(Ljava/lang/String;)V + +java/io/FileInputStream: \ + java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \ + java/lang/InternalError.<init>(Ljava/lang/String;)V \ + java/io/IOException.<init>(Ljava/lang/String;)V \ + java/io/FileNotFoundException.<init>(Ljava/lang/String;)V + +java/io/FileOutputStream: \ + java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \ + java/lang/InternalError.<init>(Ljava/lang/String;)V \ + java/io/FileNotFoundException.<init>(Ljava/lang/String;)V \ + java/io/IOException.<init>(Ljava/lang/String;)V + +java/io/ObjectInputStream: \ + java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \ + java/lang/InternalError.<init>(Ljava/lang/String;)V \ + java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \ + java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V + +java/io/ObjectOutputStream: \ + java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \ + java/lang/InternalError.<init>(Ljava/lang/String;)V \ + java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \ + java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V + +java/io/RandomAccessFile: \ + java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \ + java/lang/InternalError.<init>(Ljava/lang/String;)V \ + java/io/FileNotFoundException.<init>(Ljava/lang/String;)V \ + java/io/IOException.<init>(Ljava/lang/String;)V + +# end of file |