• Post Reply Bookmark Topic Watch Topic
  • New Topic

Deserialize object - Class unknown  RSS feed

 
Anne Forumer
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
All I have is a deserialized object, say in a file. I don't know what class it is. This class information must be obtained, somehow, at runtime. Is this class information part of the deserialized object including where this class can be downloaded from?

Is it possible to deserialize and use such an object? I'd appreciate all details.

Thanks
 
Jeroen T Wenting
Ranch Hand
Posts: 1847
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If the class can be found (in the correct version) on the classpath it will deserialise, if it is nowhere on the classpath you get an exception.
 
Tony Morris
Ranch Hand
Posts: 1608
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jeroen T Wenting:
If the class can be found (in the correct version) on the classpath it will deserialise, if it is nowhere on the classpath you get an exception.


This depends on which class loader that is being used. If you are using RMI for example, the class definition can be obtained remotely. Some more context from the OP is required.
 
Campbell Ritchie
Marshal
Posts: 56225
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Do you have an opportunity to examine the file?
Do you have an opportunity to enter the class name as text anywhere into your app?

Try opening your serialized file with notepad etc, and see whether the printout gives you any indication of what sort of class it is.

Can you get an object of the same class with Class.forName().newInstance()?
Can you cast to thatObject.getClass()?
Can you use getClass() on your deserialized object?

I have tried a little app, to see whether I can get anything to work. Try it.
It gets as far as printing out the name of the class to the "out" PrintStream.
See whether you can get retrieved.getClass() to give you a class to cast to.
The next bit isn't really code, but what happens if you open the ObjectFile.obj with NotePad. It said Campbell for the word.
 
Campbell Ritchie
Marshal
Posts: 56225
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have you read about reflection in the Java tutorial recently? I think that might help with your problems.

CR
[ April 30, 2006: Message edited by: Campbell Ritchie ]
 
Campbell Ritchie
Marshal
Posts: 56225
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
New version of the go() method. Is this any use to you?Does that sort of thing help you?

CR
 
Campbell Ritchie
Marshal
Posts: 56225
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have you found my mistake yet? I forgot something.
I missed out the "finally" blocks which close the ObjectStreams. Sorry.

CR
 
pascal betz
Ranch Hand
Posts: 547
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
the class info is in the serialized data. so you can deserialize it if the required class is on the classpath (as Tony mentioned there are some classloader differences) and the class file has the correct version (serialVerUID).
more likely your program will choke if you deserialize something that your program does not expect:

if the object you read from the ObjectInputStream is not of typee User then you will face a ClassCastException. This means your program needs to be prepared to handle the type of the deserialized object which means it needs to be of a specified class or implement a specified interface so you can reference it properly.


pascal
 
Edwin Dalorzo
Ranch Hand
Posts: 961
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I myself have not tried this. But as far as I understand You could use annotateClass() from the class java.io.ObjectOutputStream to store a class representation or URL of the class and used a ClassLoader in the deserializing class by means of the the resolveClass() method from the class java.io.ObjectInputStream in order to load the class back into memory.

Wouldn't it work?
 
Campbell Ritchie
Marshal
Posts: 56225
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Edwin, please explain more.
It appears you need a SerialVersion UID (SUID) for ObjectOutputStream.annotateClass() to work; I asked Eclipse and it calculated an SUID, so you can add this field to my NewObject class:-
But you can't call the annotateClass() method because it is protected; you would need to extend the ObjectOutputStream class and presumably give the annotateClass() method more visibility.

Similarly ObjectInputStream.resolveClass() requires a class (ObjectStreamClass) with an SUID be passed.

Ann Forumer's original problem was that she couldn't get the name of the class out of the serialized object, so does this actually help?

CR
[ May 01, 2006: Message edited by: Campbell Ritchie ]
 
Edwin Dalorzo
Ranch Hand
Posts: 961
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, Campbell

Look private static final long serialVersionUID is used by the deserialization process to check if the version of the serialized class corresponds to the deserialized one.

You know you could serialize a class today and deserialize it a year after that. That class could have changed.

When you declare a class serializable you should declare private static final long serialVersionUID variable. The initial value of variable can be set by yourself, or you could use the serailver tool that comes with the JDK and that you can find in the bin directory, to generate a unique number identifier for the class, or you could ask Eclipse to do it, just as you did.

Now, let's say I have this serializable class.



I am going to put Jedi.class in my personal Apache Web Server path (at
/var/www), so that the class is available through http://localhost/Jedi.class. Which might perfectly be an atypical way to prove how to use annotateClass() and readResolve(), but it makes a simple example.

Now, in order to user annotateClass() I have to extend the.ObjectOutputStream class, just as you suggested. In this case I am going to save during class annotation that URL path where I can get a class representation for the object I intend to serialize.

Like this:



Now, another JVM is probably going to deserialize your object. You have to make sure if the class is already loaded. In this case I am going to assume that the class was actually not loaded. And I extend a ObjectInputStream in orde to override the readResolve() method, in order to load the class from the previously URL path saved by the annotateClass method.

Like this:



Now, the JVM that serializes the object should do somewhat like this:



Now, the JVM that deserializes the object should do somewhat like this:



When the writeObject method is called, it automatically invoke annotateClass. And when the readObject is invoked, it automatically invoke readResolve().

I would like to know how I can save the binary representation of the class, instead of its URL. I guess I would have to write my own class loader for it.
 
Campbell Ritchie
Marshal
Posts: 56225
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you.
I have tried with an ordinary ObjectOutputStream, without yet extending the class.
It seems you can deserialize an object, provided its class description is in the classpath, as Jeroen Wenting and Tony Morris have told us, or you can get your hands on the class description.

If I put an SUID in my object, it serializes and deserializes easily, and I can get a printout of all its methods, parameters, constructors, etc etc. If I change the class in the classpath, then I get an Exception and a complaint about different SUIDs.
Can Anne Furomer get at the details of a deserialized object only if she has its class, or it is saved as a Bean?

Bye, must be off now.
CR
 
Campbell Ritchie
Marshal
Posts: 56225
171
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you. I have tried overriding the annotateClass and resolveClass methods, and the result appears to be the same as when I was using the ordinary ObjectStreams. So I am obviously annotating and resolving: but how do you see a difference? And how does it help AF with her original query?



CR
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!