diff options
author | Geoff Berry <gcb@gnu.org> | 1998-07-07 08:21:38 +0000 |
---|---|---|
committer | Geoff Berry <gcb@gnu.org> | 1998-07-07 08:21:38 +0000 |
commit | d005ab4f8425f0d8797699f11c722726979a877e (patch) | |
tree | 1ee021c33c9a9987bd01e43ca5955132aec0c6fd | |
parent | 5e60deb246109c4b2372edb7cf480d1b5399ba43 (diff) | |
download | classpath-d005ab4f8425f0d8797699f11c722726979a877e.tar.gz |
See ChangeLog.
-rw-r--r-- | configure.in | 3 | ||||
-rw-r--r-- | gnu/Makefile.am | 2 | ||||
-rw-r--r-- | gnu/java/io/Makefile.am | 2 | ||||
-rw-r--r-- | gnu/java/io/ObjectIdentityWrapper.java (renamed from gnu/java/io/UniqueObjectWrapper.java) | 28 | ||||
-rw-r--r-- | gnu/tools/Makefile.am | 4 | ||||
-rw-r--r-- | gnu/tools/serialver/Main.java | 62 | ||||
-rw-r--r-- | gnu/tools/serialver/Makefile.am | 5 | ||||
-rw-r--r-- | java/io/ChangeLog | 9 | ||||
-rw-r--r-- | java/io/ObjectOutputStream.java | 6 | ||||
-rw-r--r-- | java/io/ObjectStreamClass.java | 51 | ||||
-rw-r--r-- | native/java.io/java_io_ObjectStreamClass.c | 30 | ||||
-rw-r--r-- | native/java.io/java_io_ObjectStreamClass.h | 14 | ||||
-rw-r--r-- | test/java.io/ObjectStreamClassTest.java | 282 |
13 files changed, 412 insertions, 86 deletions
diff --git a/configure.in b/configure.in index a90ac5063..747ad71f1 100644 --- a/configure.in +++ b/configure.in @@ -51,6 +51,8 @@ gnu/java/net/Makefile \ gnu/java/net/content/Makefile \ gnu/java/net/content/text/Makefile \ gnu/java/net/http/Makefile \ +gnu/tools/Makefile \ +gnu/tools/serialver/Makefile \ java/Makefile \ java/io/Makefile \ java/net/Makefile \ @@ -58,6 +60,7 @@ native/Makefile \ native/java.io/Makefile \ native/java.net/Makefile \ test/Makefile \ +test/gnu.java.lang.reflect/Makefile \ test/java.io/Makefile \ test/java.net/Makefile) diff --git a/gnu/Makefile.am b/gnu/Makefile.am index 4163db7d3..10bbe30ba 100644 --- a/gnu/Makefile.am +++ b/gnu/Makefile.am @@ -1,4 +1,4 @@ ## Input file for automake to generate the Makefile.in used by configure -SUBDIRS = java +SUBDIRS = java tools diff --git a/gnu/java/io/Makefile.am b/gnu/java/io/Makefile.am index b55d86bc5..f37781f37 100644 --- a/gnu/java/io/Makefile.am +++ b/gnu/java/io/Makefile.am @@ -2,4 +2,4 @@ gnujavaiodir = $(datadir)/gnu/java/io -gnujavaio_JAVA = NullOutputStream.java UniqueObjectWrapper.java +gnujavaio_JAVA = NullOutputStream.java ObjectIdentityWrapper.java diff --git a/gnu/java/io/UniqueObjectWrapper.java b/gnu/java/io/ObjectIdentityWrapper.java index dc416560a..503930cbc 100644 --- a/gnu/java/io/UniqueObjectWrapper.java +++ b/gnu/java/io/ObjectIdentityWrapper.java @@ -1,7 +1,7 @@ /************************************************************************* -/* UniqueObjectWrapper.java -- Wrapper class used to override equals() -/* and hashCode() to be as discriminating -/* as possible +/* ObjectIdentityWrapper.java -- Wrapper class used to override equals() +/* and hashCode() to be as discriminating +/* as possible /* /* Copyright (c) 1998 by Geoffrey C. Berry (gcb@cs.duke.edu) /* @@ -26,14 +26,14 @@ package gnu.java.io; the methods <code>hashCode()</code> and <code>equals(Object)</code> as discriminating as possible. */ -public class UniqueObjectWrapper +public class ObjectIdentityWrapper { /** - Constructs a <code>UniqueObjectWrapper</code> that is wrapped + Constructs a <code>ObjectIdentityWrapper</code> that is wrapped around o. */ - public UniqueObjectWrapper( Object o ) + public ObjectIdentityWrapper( Object o ) { object = o; } @@ -41,7 +41,7 @@ public class UniqueObjectWrapper /** Uses <code>System.identityHashCode(Object)</code> to compute a hash code for the object wrapped by this - <code>UniqueObjectWrapper</code>. + <code>ObjectIdentityWrapper</code>. @see java.lang.System#identityHashCode(java.lang.Object) @see java.util.Hashtable @@ -54,29 +54,29 @@ public class UniqueObjectWrapper /** Uses the <code>==</code> operator to test for equality between - the object wrapped by this <code>UniqueObjectWrapper</code> and - the object wrapped by the <code>UniqueObjectWrapper</code> o. - Returns false if o is not a <code>UniqueObjectWrapper</code>. + the object wrapped by this <code>ObjectIdentityWrapper</code> and + the object wrapped by the <code>ObjectIdentityWrapper</code> o. + Returns false if o is not a <code>ObjectIdentityWrapper</code>. @see java.util.Hashtable @see java.lang.Object#equals() */ public boolean equals( Object o ) { - if( o instanceof UniqueObjectWrapper ) - return object == ((UniqueObjectWrapper)o).object; + if( o instanceof ObjectIdentityWrapper ) + return object == ((ObjectIdentityWrapper)o).object; else return false; } public String toString() { - return "UniqueObjectWrapper< " + object + ", " + hashCode() + " >"; + return "ObjectIdentityWrapper< " + object + ", " + hashCode() + " >"; } /** The <code>Object</code> wrapped by this - <code>UniqueObjectWrapper</code>. + <code>ObjectIdentityWrapper</code>. */ public Object object; } diff --git a/gnu/tools/Makefile.am b/gnu/tools/Makefile.am new file mode 100644 index 000000000..03630617c --- /dev/null +++ b/gnu/tools/Makefile.am @@ -0,0 +1,4 @@ +## Input file for automake to generate the Makefile.in used by configure + +SUBDIRS = serialver + diff --git a/gnu/tools/serialver/Main.java b/gnu/tools/serialver/Main.java new file mode 100644 index 000000000..de050178f --- /dev/null +++ b/gnu/tools/serialver/Main.java @@ -0,0 +1,62 @@ +/************************************************************************* +/* Main.java -- Implementation of serialver program +/* +/* Copyright (c) 1998 by Geoffrey C. Berry (gcb@cs.duke.edu) +/* +/* This program is free software; you can redistribute it and/or modify +/* it under the terms of the GNU Library General Public License as published +/* by the Free Software Foundation, version 2. (see COPYING.LIB) +/* +/* This program is distributed in the hope that it will be useful, but +/* WITHOUT ANY WARRANTY; without even the implied warranty of +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/* GNU General Public License for more details. +/* +/* You should have received a copy of the GNU General Public License +/* along with this program; if not, write to the Free Software Foundation +/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA +/*************************************************************************/ + +package gnu.tools.serialver; + +import java.io.ObjectStreamClass; + +/** + This class is an implementation of the `serialver' program. Any + number of class names can be passed as arguments, and the serial + version unique identitfier for each class will be printed in a + manner suitable for cuting and pasting into a Java source file. +*/ +public class Main +{ + public static void main( String[] args ) + { + if( args.length == 0 ) + { + System.out.println( "Usage: serialver classname(s)" ); + return; + } + + Class clazz; + ObjectStreamClass osc; + for( int i=0; i < args.length; i++ ) + { + try + { + clazz = Class.forName( args[i] ); + osc = ObjectStreamClass.lookup( clazz ); + + if( osc != null ) + System.out.println( clazz.getName() + ": " + + "static final long serialVersionUID = " + + osc.getSerialVersionUID() + "L;" ); + else + System.err.println( "Class " + args[i] + " is not serializable" ); + } + catch( ClassNotFoundException e ) + { + System.err.println( "Class for " + args[i] + " not found" ); + } + } + } +} diff --git a/gnu/tools/serialver/Makefile.am b/gnu/tools/serialver/Makefile.am new file mode 100644 index 000000000..47205d48f --- /dev/null +++ b/gnu/tools/serialver/Makefile.am @@ -0,0 +1,5 @@ +## Input file for automake to generate the Makefile.in used by configure + +gnutoolsserialverdir = $(datadir)/gnu/tools/serialver + +gnutoolsserialver_JAVA = Main.java diff --git a/java/io/ChangeLog b/java/io/ChangeLog index 2ce975dcd..5261efa23 100644 --- a/java/io/ChangeLog +++ b/java/io/ChangeLog @@ -1,3 +1,12 @@ +1998-07-07 Geoff Berry <gcb@nutzoid.salmon> + + * ObjectStreamClass.java (setFlags(Class)): Use + Class.isAssignableFrom(Class) instead of looking through + interfaces for Serializable and Externalizable. + (hasDefinedSUID(Class)): changed to getDefinedSUID(Class). + Checking for the field is now done in Java to be sure the field is + final. + 1998-07-06 Geoff Berry <gcb@cs.duke.edu> * ObjectStreamClass.java, ObjectStreamConstants.java: Added diff --git a/java/io/ObjectOutputStream.java b/java/io/ObjectOutputStream.java index 654afb64c..c34c5d0fc 100644 --- a/java/io/ObjectOutputStream.java +++ b/java/io/ObjectOutputStream.java @@ -24,7 +24,7 @@ package java.io; import java.lang.reflect.Field; import java.util.Hashtable; -import gnu.java.io.UniqueObjectWrapper; +import gnu.java.io.ObjectIdentityWrapper; import gnu.java.lang.reflect.TypeSignature; public class ObjectOutputStream extends OutputStream @@ -432,13 +432,13 @@ public class ObjectOutputStream extends OutputStream private Integer findHandle( Object obj ) { - return (Integer)myOIDLookupTable.get( new UniqueObjectWrapper( obj ) ); + return (Integer)myOIDLookupTable.get( new ObjectIdentityWrapper( obj ) ); } private int assignNewHandle( Object obj ) { - myOIDLookupTable.put( new UniqueObjectWrapper( obj ), + myOIDLookupTable.put( new ObjectIdentityWrapper( obj ), new Integer( myNextOID ) ); return myNextOID++; } diff --git a/java/io/ObjectStreamClass.java b/java/io/ObjectStreamClass.java index fede7976a..7ee55678e 100644 --- a/java/io/ObjectStreamClass.java +++ b/java/io/ObjectStreamClass.java @@ -18,8 +18,6 @@ /* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA /*************************************************************************/ -// TODO: test suite - package java.io; import java.lang.reflect.Constructor; @@ -233,26 +231,12 @@ public class ObjectStreamClass implements Serializable // Sets bits in myFlags according to features of CL. private void setFlags( Class cl ) { - Class[] interfaces = cl.getInterfaces(); - - boolean serializable = false; - boolean externalizable = false; - for( int i=0; i < interfaces.length; i++ ) - { - if( interfaces[i] == java.io.Serializable.class ) - serializable = true; - else if( interfaces[i] == java.io.Externalizable.class ) - externalizable = true; - } - - - if( externalizable ) + if( java.io.Externalizable.class.isAssignableFrom( cl ) ) myFlags |= ObjectStreamConstants.SC_EXTERNALIZABLE; - else if( serializable ) + else if( java.io.Serializable.class.isAssignableFrom( cl ) ) // only set this bit if CL is NOT Externalizable myFlags |= ObjectStreamConstants.SC_SERIALIZABLE; - try { Method writeMethod = cl.getDeclaredMethod( ourWriteMethodName, @@ -294,7 +278,7 @@ public class ObjectStreamClass implements Serializable num_good_fields++; } - // make a copy of serializable fields + // make a copy of serializable (non-null) fields myFields = new Field[ num_good_fields ]; for( int from=0, to=0; from < all_fields.length; from++ ) if( all_fields[from] != null ) @@ -313,13 +297,18 @@ public class ObjectStreamClass implements Serializable { try { - // hasDefinedSUID sets myUID if it is defined by the class - if( hasDefinedSUID( cl ) ) + Field suid = cl.getDeclaredField( ourSUIDFieldName ); + int modifiers = suid.getModifiers(); + + if( Modifier.isStatic( modifiers ) + && Modifier.isFinal( modifiers ) ) + { + myUID = getDefinedSUID( cl ); return; + } } - catch( NoSuchFieldError oh_well ) + catch( NoSuchFieldException ignore ) {} - // cl didn't define serialVersionUID, so we have to compute it try @@ -409,6 +398,9 @@ public class ObjectStreamClass implements Serializable 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( '/', '.' ) ); } @@ -433,16 +425,11 @@ public class ObjectStreamClass implements Serializable } - // Precomputes jfieldID for the `myUID' field in ObjectStreamClass. - private static native void initializeClass(); - - - // Returns true if CLAZZ has a long field named `serialVersionUID'. - // A side-effect of this method is that this object's `myUID' field is - // set to the value of CLAZZ's `serialVersionUID' field. + // Returns the value of CLAZZ's final static long field named + // `serialVersionUID'. // // A NoSuchFieldError is raised if CLAZZ has no such field. - private native boolean hasDefinedSUID( Class clazz ); + private native long getDefinedSUID( Class clazz ); // Returns true if CLAZZ has a static class initializer @@ -463,6 +450,7 @@ public class ObjectStreamClass implements Serializable private static final Comparator ourSerializableFieldComparator; private static final Comparator ourInterfaceComparartor; private static final Comparator ourMemberComparator; + private static final String ourSUIDFieldName = "serialVersionUID"; private static final String ourWriteMethodName = "writeObject"; private static final Class[] ourWriteMethodArgTypes = { java.io.ObjectOutputStream.class }; @@ -487,7 +475,6 @@ public class ObjectStreamClass implements Serializable //eDEBUG System.loadLibrary( "java_io_ObjectStreamClass" ); - initializeClass(); ourClassLookupTable = new Hashtable(); ourNullOutputStream = new NullOutputStream(); diff --git a/native/java.io/java_io_ObjectStreamClass.c b/native/java.io/java_io_ObjectStreamClass.c index d8bad6854..dd314b301 100644 --- a/native/java.io/java_io_ObjectStreamClass.c +++ b/native/java.io/java_io_ObjectStreamClass.c @@ -21,8 +21,6 @@ #include "java_io_ObjectStreamClass.h" -static jfieldID mysuid_fid = NULL; -static const char * myUID_str = "myUID"; static const char * myLongTypeId = "J"; static const char * serialVersionUID_str = "serialVersionUID"; static const char * class_init_str = "<clinit>"; @@ -30,25 +28,12 @@ static const char * class_init_sig = "()V"; /* - Precomputes jfieldID for the `myUID' field in ObjectStreamClass. -*/ -JNIEXPORT void JNICALL -Java_java_io_ObjectStreamClass_initializeClass( JNIEnv * env, - jclass myclass ) -{ - mysuid_fid = (*env)->GetFieldID( env, myclass, myUID_str, myLongTypeId ); -} - - -/* - Returns true if CLAZZ has a long field named `serialVersionUID'. A - side-effect of this method is that the `myUID' field of SELF is set - to the value of CLAZZ's `serialVersionUID' field. + Returns the value of CLAZZ's static long field named `serialVersionUID'. A NoSuchFieldError is raised if CLAZZ has no such field. */ -JNIEXPORT jboolean JNICALL -Java_java_io_ObjectStreamClass_hasDefinedSUID( JNIEnv * env, +JNIEXPORT jlong JNICALL +Java_java_io_ObjectStreamClass_getDefinedSUID( JNIEnv * env, jobject self, jclass clazz ) { @@ -57,12 +42,9 @@ Java_java_io_ObjectStreamClass_hasDefinedSUID( JNIEnv * env, myLongTypeId ); if( suid_fid == NULL ) - return FALSE; - - (*env)->SetLongField( env, self, mysuid_fid, - (*env)->GetStaticLongField( env, clazz, suid_fid ) ); + return 0; - return TRUE; + return (*env)->GetStaticLongField( env, clazz, suid_fid ); } @@ -81,5 +63,5 @@ Java_java_io_ObjectStreamClass_hasClassInitializer( JNIEnv * env, class_init_str, class_init_sig ); - return !(mid == NULL); + return mid != NULL; } diff --git a/native/java.io/java_io_ObjectStreamClass.h b/native/java.io/java_io_ObjectStreamClass.h index 2d9c43175..f626ab73b 100644 --- a/native/java.io/java_io_ObjectStreamClass.h +++ b/native/java.io/java_io_ObjectStreamClass.h @@ -9,18 +9,10 @@ extern "C" { #endif /* * Class: java_io_ObjectStreamClass - * Method: initializeClass - * Signature: ()V + * Method: getDefinedSUID + * Signature: (Ljava/lang/Class;)J */ -JNIEXPORT void JNICALL Java_java_io_ObjectStreamClass_initializeClass - (JNIEnv *, jclass); - -/* - * Class: java_io_ObjectStreamClass - * Method: hasDefinedSUID - * Signature: (Ljava/lang/Class;)Z - */ -JNIEXPORT jboolean JNICALL Java_java_io_ObjectStreamClass_hasDefinedSUID +JNIEXPORT jlong JNICALL Java_java_io_ObjectStreamClass_getDefinedSUID (JNIEnv *, jobject, jclass); /* diff --git a/test/java.io/ObjectStreamClassTest.java b/test/java.io/ObjectStreamClassTest.java new file mode 100644 index 000000000..14d10a7ee --- /dev/null +++ b/test/java.io/ObjectStreamClassTest.java @@ -0,0 +1,282 @@ +/************************************************************************* +/* ObjectStreamClassTest.java -- Tests ObjectStreamClass class +/* +/* Copyright (c) 1998 by Geoffrey C. Berry (gcb@cs.duke.edu) +/* +/* This program is free software; you can redistribute it and/or modify +/* it under the terms of the GNU General Public License as published +/* by the Free Software Foundation, version 2. (see COPYING) +/* +/* This program is distributed in the hope that it will be useful, but +/* WITHOUT ANY WARRANTY; without even the implied warranty of +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/* GNU General Public License for more details. +/* +/* You should have received a copy of the GNU General Public License +/* along with this program; if not, write to the Free Software Foundation +/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA +/*************************************************************************/ + +import java.io.Externalizable; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.util.Hashtable; +import java.util.Vector; + +public class ObjectStreamClassTest +{ + public static void pass() + { + System.out.print( "PASSED: " ); + } + + public static void fail() + { + System.out.print( "FAILED: " ); + } + + public static void pass( boolean exp_pass ) + { + if( exp_pass ) + pass(); + else + System.out.print( "XPASSED: " ); + } + + public static void fail( boolean exp_pass ) + { + if( exp_pass ) + fail(); + else + System.out.print( "XFAIL: " ); + } + + public static void testLookup( Class cl, boolean non_null ) + { + if( non_null == (ObjectStreamClass.lookup( cl ) != null) ) + pass(); + else + fail(); + + System.out.println( "lookup() for " + cl ); + } + + public static void testGetName( Class cl, String name ) + { + if( ObjectStreamClass.lookup( cl ).getName().equals( name ) ) + pass(); + else + fail(); + + System.out.println( "getName() for " + cl ); + } + + public static void testForClass( Class cl, Class clazz ) + { + if( ObjectStreamClass.lookup( cl ).forClass() == clazz ) + pass(); + else + fail(); + + System.out.println( "forClass() for " + cl ); + } + + public static void testSUID( Class cl, long suid ) + { + testSUID( cl, suid, true ); + } + + public static void testSUID( Class cl, long suid, boolean exp_pass ) + { + if( ObjectStreamClass.lookup( cl ).getSerialVersionUID() == suid ) + pass( exp_pass ); + else + fail( exp_pass ); + + System.out.println( "getSerialVersionUID() for " + cl ); + } + + public static void testHasWrite( Class cl, boolean has_write ) + { + if( ObjectStreamClass.lookup( cl ).hasWriteMethod() == has_write ) + pass(); + else + fail(); + + System.out.println( "hasWriteMethod() for " + cl ); + } + + public static void testIsSerial( Class cl, boolean is_serial ) + { + if( ObjectStreamClass.lookup( cl ).isSerializable() == is_serial ) + pass(); + else + fail(); + + System.out.println( "isSerializable() for " + cl ); + } + + public static void testIsExtern( Class cl, boolean is_extern ) + { + if( ObjectStreamClass.lookup( cl ).isExternalizable() == is_extern ) + pass(); + else + fail(); + + System.out.println( "isExternalizable() for " + cl ); + } + + public static void main( String[] args ) + { + try + { + // lookup + testLookup( Serial.class, true ); + testLookup( NotSerial.class, false ); + + // getName + testGetName( java.lang.String.class, "java.lang.String" ); + testGetName( java.util.Hashtable.class, "java.util.Hashtable" ); + + // forClass + testForClass( java.lang.String.class, java.lang.String.class ); + testForClass( java.util.Vector.class, (new Vector()).getClass() ); + + // getSerialVersionUID + testSUID( A.class, 1577839372146469075L ); + testSUID( B.class, -7069956958769787679L ); + + // NOTE: this fails for JDK 1.1.5v5 on linux because a non-null + // jmethodID is returned from + // GetStaticMethodID( env, C, "<clinit>", "()V" ) + // even though class C does not have a class initializer. + // The JDK's serialver tool does not have this problem somehow. + // I have not tested this on other platforms. + testSUID( C.class, 7441756018870420732L, false ); + + testSUID( Defined.class, 17 ); + testSUID( DefinedNotStatic.class, 8797806279193632512L ); + testSUID( DefinedNotFinal.class, -1014973327673071657L ); + + // hasWriteMethod + testHasWrite( Serial.class, false ); + testHasWrite( HasWrite.class, true ); + testHasWrite( InherWrite.class, false ); + testHasWrite( PubWrite.class, false ); + testHasWrite( StaticWrite.class, false ); + testHasWrite( ReturnWrite.class, false ); + + // isSerializable + testIsSerial( Serial.class, true ); + testIsSerial( Extern.class, false ); + testIsSerial( InherSerial.class, true ); + testIsSerial( InherExtern.class, false ); + + // isExternalizable + testIsExtern( Serial.class, false ); + testIsExtern( Extern.class, true ); + testIsExtern( InherSerial.class, false ); + testIsExtern( InherExtern.class, true ); + } + catch( Exception e ) + { + e.printStackTrace(); + } + } +} + +class NotSerial {} + +class A implements Serializable +{ + int b; + int a; + + public int f() { return 0; } + float g() { return 3; } + + private float c; +} + +abstract class B extends A +{ + private B( int[] ar ) {} + public B() {} + public static void foo() {}; + public abstract void absfoo(); + + private static String s; + public int[] a; + + static + { + s = "hello"; + } +} + +class C extends B implements Cloneable, Externalizable +{ + public void absfoo() {} + public void readExternal( ObjectInput i ) {} + public void writeExternal( ObjectOutput o ) {} +} + + +class Defined implements Serializable +{ + static final long serialVersionUID = 17; +} + +class DefinedNotStatic implements Serializable +{ + final long serialVersionUID = 17; +} + +class DefinedNotFinal implements Serializable +{ + static long serialVersionUID = 17; +} + +class HasWrite implements Serializable +{ + private void writeObject( ObjectOutputStream o ) {} +} + +class InherWrite extends HasWrite {} + +class PubWrite implements Serializable +{ + public void writeObject( ObjectOutputStream o ) {} +} + +class StaticWrite implements Serializable +{ + private static void writeObject( ObjectOutputStream o ) {} +} + +class ReturnWrite implements Serializable +{ + private int writeObject( ObjectOutputStream o ) + { + return -1; + } +} + + +class Serial implements Serializable {} + +class Extern implements Externalizable +{ + public void readExternal( ObjectInput i ) + {} + + public void writeExternal( ObjectOutput o ) + {} +} + +class InherExtern extends Extern implements Serializable {} + +class InherSerial extends Serial {} |