-
Bug
-
Resolution: Fixed
-
P4
-
1.2.2
-
beta
-
sparc
-
solaris_7
-
Verified
Name: stC104175 Date: 06/26/2000
java version "1.2.2"
Solaris VM (build Solaris_JDK_1.2.2_05a, native threads, sunwjit)
During deserialization I am trying to substitute one class for another by
subclassing ObjectInputStream and overriding resolveClass(). The new
class is exactly the same class (with identical Serial version UID) -
except that the new one is part of a package structure while the original
was not.
The original class' full qualified class name was simply "Project" while
new one's is "com.phor.perspective.v1classes.Project".
The exception I get when trying to deserialize:
java.io.InvalidClassException: com.phor.perspective.v1classes.Project;
Incompatible local class name. Expected class name compatible with Project
....
at
java.io.ObjectStreamClass.validateLocalClass(ObjectStreamClass.java:448)
....
If you look at this line in the source code, you will see that the
exception is thrown because java.io.ObjectStreamClass.compareClassNames()
is returning false for my two class names. And if you have a look at
compareClassNames() you will see that is unable to handle the case
where the one class is part of a package structure and the other
is not.
Here is a short program using the compareClassName code to
demonstrate how I am getting the exception when I shouldn't.
The program takes as its arguments two fully qualified class
names.
---------------------------------------------------------
public class test {
public static void main( String[] args ) {
String a = args[0].trim();
String b = args[1].trim();
if( compareClassNames( a, b, '.' ) ) {
System.out.println("MATCH!");
}
else {
System.out.println("NO MATCH! BOOO!");
}
}
static boolean compareClassNames(String streamName,
String localName,
char pkgSeparator) {
int streamNameIndex = streamName.lastIndexOf(pkgSeparator);
if (streamNameIndex < 0)
streamNameIndex = 0;
//else
// streamNameIndex++
int localNameIndex = localName.lastIndexOf(pkgSeparator);
if (localNameIndex < 0)
localNameIndex = 0;
//else
// localNameIndex++;
return streamName.regionMatches(true, streamNameIndex,
localName, localNameIndex,
streamName.length() - streamNameIndex);
}
}
----------------------------------------------------------------------
After compiling and experimentation you will find:
1. Project matches Project
2. com.Project matches com.phor.Project
3. Project !match com.phor.Project
The reason case 3 doesn't match is
that the regionMatch is getting the index
of the "pkgSeparator" for classes that have
them, and for those that don't it gets the
index of first letter of the unqualified class
name (i.e. 0).
So in case 3 it ends up trying to compare
"Project" and ".Project" which is the source
of the error. My fix is the commented 'else'
statements which (if uncommented) will cause the
regionMatch() to get indeces which are always
the first letter of the unqualified class name.
This bug is a real pain, since it prevents me
from being able to move the upcoming version of this
project into a proper package structure.
(Review ID: 106496)
======================================================================