Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (527)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (593)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  ObjectOutputStream  (Read 1788 times)
0 Members and 1 Guest are viewing this topic.
Offline Cero
« Posted 2012-06-25 00:08:23 »

When you use ObjectOutputStream to save, for example a save game to file, then you change the code - you break it.
I recall Cas said that he does this and breaks save games often with it.

Isn't there something you can do to avoid it besides serializing it differently/yourself ?

Like, I would like it if a old/incompatible save game was loaded, it would only load the variables that still match and dont care about the rest.
Basically it should do "whatever it can", load variables that still have the same name and type, forget about the stuff that doesnt match.
Not possible with ObjectOutputStream/Serializable ?

Offline UprightPath
« Reply #1 - Posted 2012-06-25 01:44:44 »

1  
2  
3  
4  
5  
public class ClassName {
private static long serialVersionUID = 1L;

//REST OF YOUR CODE
}

A serialVersionUID is used to allow you to programmatically enforce a form of 'version' control on your serialized objects. When you use it, you say what the ID is, and control when that Id gets changed. If a object that has been serialized with a different Id is unserialized, you'll get an exception. Basically, if your not changing the actual data representation of your code, such as the variables in your code, you can leave your serialVersionUID the same, and it probably will be able to unserialize correctly, regardless of what you did to the other code.

Offline i30817

Junior Devvie





« Reply #2 - Posted 2012-06-25 02:15:23 »

*snip*

Not really what he wants  - that's the uncommon case where nothing data changes -

edit: -> this is where i went off the rails (it's not actually what he wants either) Smiley


he wants (quite naturally) to avoid breaking the serialization of critical data when something in another part of the graph breaks. Java serialization doesn't really go out of it's way to help with this; but i can tell you that isolation of the unchanging data in a another file/stream is key:
http://www.java-gaming.org/topics/quick-questions-for-mechanims-optimizations/26700/msg/235429/view.html#msg235429

Something like that should avoid most problems (except uniqueness == issues, which it may cause because of multiple graphs).

In retrospect serialization should have been position independent somehow if that was possible - as a generic protocol it's utter failure when something as dynamic as code is represented.
If you try to do it as 'it is meant to be used' your major version readObject() conversions (if you don't give up on that) will be byzantine - modify the order of the fields in a holder class? Hello serializable error, goodbye user state.

Now if you're actually talking about changing the (supposedly final) user data; you need to overload readObject and check a version number or something like that you wrote to the stream.
You can maybe try a cascaded switch of versions, with default values on top. I don't know because i am hoping to avoid that layer of hell forever, also, f**k the users.


Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline i30817

Junior Devvie





« Reply #3 - Posted 2012-06-25 03:22:41 »

I just thought of another way than reading stuff in 'manually' in readObject. You still need to do the transformations (that is, taking the old object and reading what you can to the new format), but it should be easier not having to deal with readObject:

http://docs.oracle.com/javase/6/docs/platform/serialization/spec/input.html#5903

Quote
The readResolve method is called when ObjectInputStream has read an object from the stream and is preparing to return it to the caller. ObjectInputStream checks whether the class of the object defines the readResolve method. If the method is defined, the readResolve method is called to allow the object in the stream to designate the object to be returned. The object returned should be of a type that is compatible with all uses. If it is not compatible, a ClassCastException will be thrown when the type mismatch is discovered.

So... keep old major version of the dataclass around, use interface, read replace old versions to new versions... profit? Not so sure if changing the interface would be allowed... prob not since the old versions implement it... but maybe if you delete that 'implements' and keep the serialversionUID. I dunno...

Or you can just bite the bullet and use versions since there is no magic available for the actual transformations.
Offline sproingie

JGO Kernel


Medals: 202



« Reply #4 - Posted 2012-06-25 06:24:15 »

Serialization is all right for transferring objects or caching them when you don't mind blowing them away.  It's crap for any kind of long-term persistence.  Do not use serialization for save games if you ever plan on changing any of the classes in development or a patch.

Offline princec

« JGO Spiffy Duke »


Medals: 425
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #5 - Posted 2012-06-25 09:00:24 »

If you put a serialVersionUID in a class, Java already does what you want and attempts to read in as many variables as it can and ignores the rest. Generally though this means your save game is broken anyway. The problem cannot actually be magically solved by any other solution; Java already implements it exactly as you would do it yourself. I break saved games all the time because the changes I usually make are massively incompatible, so it's usually totally deliberate.

sproingie reckons serialisation is crap for long-term persistence and he's right in that it's quite a pain to actually migrate data from an old version to a new version - like you could do with a database for example. It is however no more nor less tricky or crappy than using, say, XML, or your own proprietary solution, so don't sweat it. Just make sure everything's got a serialVersionUID. Eclipse has a warning that you can turn on for that.

"Works for me."

Cas Smiley

Offline nsigma
« Reply #6 - Posted 2012-06-25 11:55:46 »

What about java.beans.XMLEncoder? Never used it though.

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline princec

« JGO Spiffy Duke »


Medals: 425
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #7 - Posted 2012-06-25 12:24:21 »

Suffers exactly the same problems as serialization does, really, with the added bonus of massively verbose files. "Advantage" is you can hack the files by hand or with some other XML processing tool.

Cas Smiley

Offline Cero
« Reply #8 - Posted 2012-06-25 12:33:21 »

If you put a serialVersionUID in a class, Java already does what you want and attempts to read in as many variables as it can and ignores the rest.

Actually this is what I wanted to hear.
In my case this problem is not for patches after the game has been released - but I use save games in debugging. While programming I change a lot obviously, it automatically saves where I was and stuff; and I just want to jump right in again.
So it would for example load the X and Y and current map which but not any new stuff.
Gonna try it out, but then it should work like I want it to.

Offline nsigma
« Reply #9 - Posted 2012-06-25 13:08:00 »

Suffers exactly the same problems as serialization does, really, with the added bonus of massively verbose files.

Now, why doesn't that surprise me?  Roll Eyes  Like I said, never used it or plan to - just seemed it might be the simplest way of getting XML saving without 3rd-party code.

Incidentally, googling for simple XML serialization does (for some reason!  Smiley ) bring up http://simple.sourceforge.net/home.php

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline sproingie

JGO Kernel


Medals: 202



« Reply #10 - Posted 2012-06-25 15:34:07 »

I'm partial to multi-format storage backends using the same API.  Jackson does XML, JSON, and BSON.  You could write out saves as xml or json for debugging, and BSON when you want something compact.

Just to walk back a bit, Java serialization actually isn't that bad if you have dedicated data objects and don't just slap Serializable on your in-game classes.  Just make sure to write lots of tests for your migration code if you do change the format.
Offline Danny02
« Reply #11 - Posted 2012-06-25 16:45:42 »

If you really need to supported old file version.
You should probably create some converter for each new version which takes as input the old one.

i.e. you hav a file with the version 5 and the programm is running with the version 8

file_v5 -> convert5_6 -> convert6_7 -> convert7_8


Each converter would try to load and convert as much information as possible(use default values for new fields and so on)
Offline princec

« JGO Spiffy Duke »


Medals: 425
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #12 - Posted 2012-06-25 18:11:56 »

I look at the amount of hair pulling, angst and grief I will get by breaking customers saved games and the resulting email support fallout versus the amount of time I'd spend making upgrade systems and versioning etc. Depending on the number of customers you can make a reasonably informed choice.

Cas Smiley

Offline Cero
« Reply #13 - Posted 2012-06-25 18:23:06 »

I going to use ObjectOutputStream for save games UNTIL release, for debugging, because its easy... and once I release, I write my own files that always work and stuff.

Offline Nate

« JGO Bitwise Duke »


Medals: 158
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #14 - Posted 2012-06-25 21:58:15 »

https://code.google.com/p/kryo/#Compatibility
Can support no compatibility (the default, FieldSerializer), adding fields only (TaggedFieldSerializer), and adding or removing fields (CompatibleFieldSerializer). There currently isn't a serializer for changing field types, but it could be done.

Protobuf supports adding/removing fields and limited changing types, but you'll have to maintain a schema by hand.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

PocketCrafter7 (12 views)
2014-11-28 16:25:35

PocketCrafter7 (7 views)
2014-11-28 16:25:09

PocketCrafter7 (8 views)
2014-11-28 16:24:29

toopeicgaming1999 (74 views)
2014-11-26 15:22:04

toopeicgaming1999 (64 views)
2014-11-26 15:20:36

toopeicgaming1999 (15 views)
2014-11-26 15:20:08

SHC (29 views)
2014-11-25 12:00:59

SHC (27 views)
2014-11-25 11:53:45

Norakomi (32 views)
2014-11-25 11:26:43

Gibbo3771 (28 views)
2014-11-24 19:59:16
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!