Why Does Writeobject Throw Java.Io.Notserializableexception and How to Fix It

Why does writeObject throw java.io.NotSerializableException and how do I fix it?

The fields of your object have in turn their fields, some of which do not implement Serializable. In your case the offending class is TransformGroup. How to solve it?

  • if the class is yours, make it Serializable
  • if the class is 3rd party, but you don't need it in the serialized form, mark the field as transient
  • if you need its data and it's third party, consider other means of serialization, like JSON, XML, BSON, MessagePack, etc. where you can get 3rd party objects serialized without modifying their definitions.

I keep getting java.io.NotSerializableException: java.io.ObjectOutputStream

Only primitives and classes that implement Serializable interface can be serialized. ObjectOutputStream doesn't implement this interface.

Quick solution: use the ObjectOutputStream in the narrowest possible scope, declare it in the method where it's being used, not as a field in the class. Do similar with other utility classes like Scanner.

abstract class Account implements Serializable {
protected String accountHolderName;
protected long balance;

//protected ObjectOutputStream accData;

//Scanner input = new Scanner(System.in);
}

class Savings extends Account implements Serializable {

Savings() throws IOException {
Scanner input = new Scanner(System.in);
System.out.print("enter your name: ");
accountHolderName = input.nextLine();
System.out.print("\n");
System.out.print("enter your balance: ");
balance = input.nextLong();
ObjectOutputStream accData = new ObjectOutputStream(new FileOutputStream(accountHolderName + ".bin"));
accData.writeObject(this);
accData.close();
}
}

Another solution may be just marking these fields as transient so they won't be serialized/deserialized:

abstract class Account implements Serializable {
protected String accountHolderName;
protected long balance;

protected transient ObjectOutputStream accData;

transient Scanner input = new Scanner(System.in);
}

Why I receive NotSerializableException while attempting to Serialize an Object

The whole object graph needs to be serializable, if at least one of the fields doesn't implement Serializable interface you'll get an exception while attempting to serialize the instance of this class.

Quote from the documentation:

When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.

Primitive types and most of the data-types built-in in the JDK are serializable.

You can run into troubles only with these types:

  • Object doesn't implement Serializable, hence Object type fields are not allowed in the class that is meant to be serializable.
  • Optional as well as OptionalInt, OptionalLong and OptianalDouble aren't serializable because optional types were introduced as limited mechanism
    for return types and not intended to be used as fields.
  • Your custom types used as a field of a serializable class has to be serializable. Tiles class has to implement Serializable and if there are some custom field types inside the Tiles, they must be serializable as well.

If you don't want a particular field to be serialized, you can mark it as transient. Transient fields as well as static fields are ignored during the serialization process.

So if you would make the fields tileGroup and loadingTiles to be transient, then Tiles class will not be required to implement Serializable because these attributes will be excluded from the serialized version. And as a consiquence after deserialization they will be initialized to null.

In general, serialization is meant to be used for temporary data-storage or transferring the data. To ensure that an object retrieved from memory is compatible with the .class file that you have it a good practice to define static final long serialVersionUID field, which denotes the current version of the class.

The serialization runtime associates with each serializable class a
version number, called a serialVersionUID, which is used during
deserialization to verify that the sender and receiver of a serialized
object have loaded classes for that object that are compatible with
respect to serialization. If the receiver has loaded a class for the
object that has a different serialVersionUID than that of the
corresponding sender's class, then deserialization will result in an
InvalidClassException. A serializable class can declare its own
serialVersionUID explicitly by declaring a field named
"serialVersionUID" that must be static, final, and of type long:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

Also, you should be aware that serialization has some serious draw-backs (take a look at the link provided above).

Sidenote: class-names are usually singular nouns like Student, Employee, Tile because their instances are meant to represent a single object.

java.io.NotSerializableException even tho the class implements Serializable

Implementing Serializable is not sufficient.

If you attempt to serialize an object, all its non-transient attributes are serialized, too. If any of those attributes is not Serializable, it will not work.

In your case, Song contains an attribute of type File and File is not serializable. With Clip, you have the same problem.

In order to get around this, you can do custom serialization.

Looking at the docs of Serializable, you can find this:

Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures:

 private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;

The writeObject method is responsible for writing the state of the object for its particular class so that the corresponding readObject method can restore it. The default mechanism for saving the Object's fields can be invoked by calling out.defaultWriteObject. The method does not need to concern itself with the state belonging to its superclasses or subclasses. State is saved by writing the individual fields to the ObjectOutputStream using the writeObject method or by using the methods for primitive data types supported by DataOutput.

The readObject method is responsible for reading from the stream and restoring the classes fields. It may call in.defaultReadObject to invoke the default mechanism for restoring the object's non-static and non-transient fields.

This means that you can create the methods writeObject and readObject where you specify how to (de)serialize the object.

If you want to keep the default (de)serialization of the attributes supporting serialization, you can mark all fields not supporting serialization transient and call out.defaultWriteObject/in.defaultReadObject in the writeObject/readObject methods.

Marking an attribute transient means that serialization ignores it. You can then use your custom logic.


Note that serialization comes with some problems and you might not want to use it.

On one hand, it can lead to serious denial of service and even remote code execution vulnerabilities if you deserialize untrusted data. This is also noted in the docs of Serializable:

Warning: Deserialization of untrusted data is inherently dangerous and should be avoided. Untrusted data should be carefully validated according to the "Serialization and Deserialization" section of the Secure Coding Guidelines for Java SE. Serialization Filtering describes best practices for defensive use of serial filters.

Another problem of serialization is that it binds your application to a fixed format and makes it difficult to be compatible with old serialized data when update your application if you didn't carefully think it through when initially creating it.

For more information about this, you may want to consider reading the book Effective Java.

java.io.NotSerializableException by ObjectOutputStream.write Object

Is resolved.

I had PersonDaten as Inner Class.

Have PersonDaten maked as own class and have no problems.

MyClass NotSerializableException

To fix this error implement the Serializable interface and give it an id.

 Public class Foo implements Serializable {
private static final long serialversionUID = 1L; // example
//code then
}


Related Topics



Leave a reply



Submit