I want to know in which order the attributes of the following example class would be serialized:
public class Example implements Serializable {
private static final long serialVersionUID = 8845294179690379902L;
public int score;
public String name;
public Date eventDate;
}
EDIT:
Why i wanna know this:
I got a serialized string in a file for a class of mine which has no implementation for
readObject() or writeObject(). now that implementation changed ( some properties are gone )
and i want to write a readObject() method that handles the old serialized class.
There i would just read this property but wouldnt save it to the created object.
This is basically just for legacy i use a database now but need to support the old
serialized files.
to write this readObject() i need the order of properties that in the stream.
Based on a brief reading of the spec.
The fields are written in the order of the field descriptors the class descriptor
The field descriptors are in "canonical order" which is defined as follows:
"The descriptors for primitive typed fields are written first sorted by field name followed by descriptors for the object typed fields sorted by field name. The names are sorted using String.compareTo."
(I suspect that the bit about the canonical order should not matter. The actual order of the fields in the serialization should be recoverable from the actual order of the field descriptors in the class descriptor in the same serialization. I suspect that the reason a canonical order is specified is that it affects the computed serialization id. But I could easily be wrong about this :-) )
Reference:
Java Object Serialization Specification - Section 4.3 and Section 6.4.1 (the comment on the "nowrclass" production)
With regards to your original problem, some testing would suggest that if you've maintained your serialVersionUID and haven't removed fields containing values you need, you can probably just deserialize your old objects without error.
Any fields you no longer have will be ignored. Any new fields will be initialised to default values (e.g. null, or 0 etc.).
Bear in mind, this approach might violate constraints you've placed upon your class. For example, it may not be legal (in your eyes) to have null values in your fields.
Final warning: this is based on some testing of mine and research on the Internet. I haven't yet encountered any hard proof that this is guaranteed to work in all situations, nor that it is guaranteed to continue to work in the future. Tread carefully.
It doesn't matter. Fields are serialized along with their names. Changing the order doesn't affect serialization compatibility, as long as the serialVersionUID is the same. There are a lot of other things that don't mater either. See the Versioning chapter in the Object Serialization Specification.
Related
I have noticed many of the library classes "ArrayList", "String" even the exceptions are having a serialVersionUID. Why they have made it like this. Whats the practical use of doing that.FYI I am familiar with the concept of Serialization. Please point out the practical purpose of it.
For your reference find the serialversionUid for ClassCastException
public class ClassCastException extends RuntimeException {
private static final long serialVersionUID = -9223365651070458532L;
Where these object's state going to persist? And where will these objects state going to be retrieved ?
I am currently working in a project where we are making REST controllers whose input and output parameters will be JSON.We are creating simple POJOs for i/p and o/p parameters.I have seen people making those POJOs serializable .Whats the point in doing that ?
But I havent seen **out.readObject** or out.writeobject which is used to write and read the state of object.Will the POJO's state persist just making it serializable? If yes where it will be stored?
If you want the full story, read the spec: Java Object Serialization Specification.
[...] many of the library classes "ArrayList", "String" even the exceptions are having a serialVersionUID. Why they have made it like this.
To support backwards compatibility when reading objects that were written in an older version of the class. See Stream Unique Identifiers.
Where these object's state going to persist?
Wherever you decide. See Writing to an Object Stream.
And where will these objects state going to be retrieved ?
Wherever you put it. See Reading from an Object Stream.
[...] input and output parameters will be JSON. [...] I have seen people making those POJOs serializable. Whats the point in doing that ?
None. JSON is not using Java serialization. Java serialization creates a binary stream. JSON creates text.
Will the POJO's state persist just making it serializable? If yes where it will be stored?
No, see above.
What is the point to a serializable class? To my understanding its so that you can send objects across a network and know that on both ends that the object will be verified that it is the correct object. For example, if I have a server with a serializable class and want to send data to an app via object output stream, I can use the serializable class with the same UID on both ends to verify that the object is legitimate and not hacked? Please correct me if I'm wrong but that's how I am understanding the documentation on the serializable interface
Security and Serialization both are different.
Java serialization is to convert the objects to bytes. Period.
The optional UID field is to assure the serialized and deserialized object (structure) versions match.
Serialization is useful to convert an object into a file and reload it back into an object later in future, and of course you can send that file (stream) over the network also.
You're correct, but you can think of it more broadly.
You can convert a serializable class to bytes
You can add an object of this type to a serializable collection and it will be properly serialized (e.g. you can make a list of them and serialize the list if the list is serializable)
By the way, the serialVersionUID is optional. It will generate one on its own, though it will be a bit more fragile - if you change, for example, a method signature, the jvm will translate this to an altered signature and believe that the class is now incompatible with previous serialized versions, even if you haven't changed data fields. If you create your own you're essentially overriding this mechanism.
I am asking very generic question and the answer can vary from requirement to requirement, but for "general" or "rule of thumb", can we say the following is a good design rule:
The classes to be cached (static/reference data) should be designed as
immutable, with exceptions reasoned.
What could be design/performance issues with the above statement, if this is not true?
#JohnB has a good answer about the underlying data.
If, however, the question is referring to the immutability of the cached classes themselves (which are holding the data in the cache), then the answer is that mutable classes can cause thread-safety issues if the instances of the classes are referenced by multiple threads (as can often happen with data shared via a cache). Additionally, "accidental" modification of the data may occur, where a shared instance is unintentionally modified (because the modifying code did not know that the data was shared).
This is because of what a cache does, which is hold data rather than retrieving it from the data source again. For example, you query the database for a value then put it in a memory-based cache so you don't have to query the DB again. However, if the value in the DB can change then the value in the cache will be out of date and your application will be using the wrong data.
Therefore, caching is best if the data cannot change during the live of the application. If the data can change, then a strategy must be developed to regularly check to see if the data has changed.
What jtahlborn is explaining in other words : an immutable class will provide methods to obtain "static" data.
If your class is immutable, you will NOT have setters except the parameters in the constructor.
Take care making this : immutable classes are not made to be used only once, it would result in a performance loss, since copies of inner attributes have to be done each time you access the get... methods.
Example :
class MyImmutableThing {
private final String myProperty;
MyImmutableThing(String myProperty) {
this.myProperty = myProperty;
}
String obtainMyProperty() {
return myProperty;
}
// note there is no mean to modify the myProperty value : the original value remains ;)
// That's it !
}
How can I implement serialization on my own. Meaning I don't want my class to implement serializable. But I want to implement serialization myself. So that without implementing serializable I can transfer objects over network or write them to a file and later retrieve them in same state. I want to do it since I want to learn and explore things.
Serialization is the process of translating the structure of an object into another format that could be easily transfered across network or could be stored in a file. Java serializes objects into a binary format. This is not necessary if bandwidth/disk-space is not a problem. You can simply encode your objects as XML:
// Code is for illustration purpose only, I haven't compiled it!!!
public class Person {
private String name;
private int age;
// ...
public String serializeToXml() {
StringBuilder xml = new StringBuilder();
xml.append("<person>");
xml.append("<attribute name=\"age\" type=\"int\">").append(age);
xml.append("</attribute>");
xml.append("<attribute name=\"name\" type=\"string\">").append(name);
xml.append("</attribute>");
xml.append("</person>");
return xml.toString();
}
Now you can get an object's XML representation and "serialize" it to a file or a network connection. A program written in any language that can parse XML can "deserialize" this object into its own data structure.
If you need a more compact representation, you can think of binary encoding:
// A naive binary serializer.
public byte[] serializeToBytes() {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
// Object name and number of attributes.
// Write the 4 byte length of the string and the string itself to
// the ByteArrayOutputStream.
writeString("Person", bytes);
bytes.write(2); // number of attributes;
// Serialize age
writeString("age", bytes);
bytes.write(1); // type = 1 (i.e, int)
writeString(Integer.toString(age), bytes);
// serialize name
writeString("name", bytes);
bytes.write(2); // type = 2 (i.e, string)
writeString(name, bytes);
return bytes.toByteArray();
}
private static void writeString(String s, ByteArrayOutputStream bytes) {
bytes.write(s.length());
bytes.write(s.toBytes());
}
To learn about a more compact binary serialization scheme, see the Java implementation of Google Protocol Buffers.
You can use Externalizable and implement your own serialization mechanism. One of the difficult aspects of serialization is versioning so this can be a challenging exercise to implement. You can also look at protobuf and Avro as binary serialization formats.
You start with reflection. Get the object's class and declared fields of its class and all superclasses. Then obtain value of each field and write it to dump.
When deserializing, just reverse the process: get class name from your serialized form, instantiate an object and set its fields accordingly to the dump.
That's the simplistic approach if you just want to learn. There's many issues that can come up if you want to do it "for real":
Versioning. What if one end of the application is running new version, but the other end has an older class definition with some fields missing or renamed?
Overwriting default behavior. What if some object is more complex and cannot be recreated on a simple field-by-field basis?
Recreating dependencies between objects, including cyclic ones.
... and probably many more.
Get the Java Source code and understand how Serialization is implemented. I did this some month ago, and now have a Serialization that uses only 16% of the space and 20% of the time of "normal" serialization, at the cost of assuming that the classes that wrote the serialized data have not changed. I use this for client-server serialization where I can use this assumption.
As a supplement to #Konrad Garus' answer. There is one issue that is a show-stopper for a full reimplementation of Java serialization.
When you deserialize an object, you need to use one of the object's class's constructors to recreate an instance. But which constructor should you use? If there is a no-args constructor, you could conceivably use that. However, the no-args constructor (or indeed any constructor) might do something with the object in addition to creating it. For example, it might send a notification to something else that a new instance has been created ... passing the instance that isn't yet completely deserialized.
In fact, it is really difficult replicate what standard Java deserialization code does. What it does is this:
It determines the class to be created.
Create an instance of the class without calling any of its constructors.
It uses reflection to fill in the instance's fields, including private fields, with objects and values reconstructed from the serialization.
The problem is that step 2. involves some "black magic" that a normal Java class is not permitted to do.
(If you want to understand the gory details, read the serialization spec and take a look at the implementation in the OpenJDK codebase.)
If a similar question is already posted on stackoverflow, pls just post the link.
What is the need to implement Serializable interface (with no methods) for objects which are to be serialized ?
The Java API says -
- If its not implemented then it will throw java.io.NotSerializableException.
That's because of the following code in ObjectOutputStream.java
............................
writeObject0(Object obj, boolean unshared){
.............
} else if (cl.isArray()) {
writeArray(obj, desc, unshared);
} else if (obj instanceof Serializable) {
writeOrdinaryObject(obj, desc, unshared);
} else {
throw new NotSerializableException(cl.getName());
}
................
But my question is why its necessary to implement Serializable and thereby inform or tell Java/JVM that a class can be serialized. (Is it only to avoid the exception ?).
In this is the case, If we write a similar functionality which writes objects to streams without the check of whether the class in an instanceOf Serializable, Will the objects of a class not implemneting Serializable serialized ?
Any help is appreciated.
It's a good question. The Serializable is know as a marker interface, and can be viewed as a tag on a class to identify it as having capabilities or behaviours. e.g. you can use this to identify classes that you want to serialise that don't have serialVersionUid defined (and this may be an error).
Note that the commonly used serialisation library XStream (and others) don't require Serializable to be defined.
It is needed so that the JVM can know whether or not a class can be safely serialized. Some things (database connections for example) contain state or connections to external resources that cannot really be serialized.
Also, you'll want to make sure that you put a serialVersionUID member in every serializable class to ensure that serialized objects can be de-serialized after a code change or recompile:
// Set to some arbitrary number.
// Change if the definition/structure of the class changes.
private static final long serialVersionUID = 1;
The serialization allows you to save objects directly to binary files without having to parse them to text, write the string out and then create a new object, and parse the string inputs when reading back in. The primary purpose is to allow you to save objects with all their data to a binary file. I found it to be extremely useful when having to work with linked lists containing lots of objects of the same type and I needed to save them and open them.
The reason is that not all classes can be serialized. Examples:
I/O stuff: InputStream, HTTP connections, channels. They depend on objects created outside the scope of the Java VM and there is no simple way to restore them.
OS resources like windows, images, etc.