Java Socket/Serialization, Object Won't Update

Java socket/serialization, object won't update

See ObjectOutputStream.reset.

Reset will disregard the state of any objects already written to the stream. The state is reset to be the same as a new ObjectOutputStream. The current point in the stream is marked as reset so the corresponding ObjectInputStream will be reset at the same point. Objects previously written to the stream will not be refered to as already being in the stream. They will be written to the stream again.

/* prevent using back references */
output.reset();
output.writeObject(...);

Call reset before writing the same object to ensure its updated state is serialized. Otherwise, it will merely use a back reference to the previously written object with its out-dated state.

Or, you could alternatively use ObjectOutputStream.writeUnshared as follows.

Writes an "unshared" object to the ObjectOutputStream. This method is identical to writeObject, except that it always writes the given object as a new, unique object in the stream (as opposed to a back-reference pointing to a previously serialized instance).

Specifically:

  • An object written via writeUnshared is always serialized in the same manner as a newly appearing object (an object that has not been written to the stream yet), regardless of whether or not the object has been written previously.

  • If writeObject is used to write an object that has been previously written with writeUnshared, the previous writeUnshared operation is treated as if it were a write of a separate object. In other words, ObjectOutputStream will never generate back-references to object data written by calls to writeUnshared.

While writing an object via writeUnshared does not in itself guarantee a unique reference to the object when it is deserialized, it allows a single object to be defined multiple times in a stream, so that multiple calls to readUnshared by the receiver will not conflict. Note that the rules described above only apply to the base-level object written with writeUnshared, and not to any transitively referenced sub-objects in the object graph to be serialized.

output.writeUnshared(...);

Note it's good practice to couple this with ObjectInputStream.readUnshared.

Reads an "unshared" object from the ObjectInputStream. This method is identical to readObject, except that it prevents subsequent calls to readObject and readUnshared from returning additional references to the deserialized instance obtained via this call.

Specifically:

  • If readUnshared is called to deserialize a back-reference (the stream representation of an object which has been written previously to the stream), an ObjectStreamException will be thrown
  • If readUnshared returns successfully, then any subsequent attempts to deserialize back-references to the stream handle deserialized by readUnshared will cause an ObjectStreamException to be thrown.

Deserializing an object via readUnshared invalidates the stream handle associated with the returned object. Note that this in itself does not always guarantee that the reference returned by readUnshared is unique; the deserialized object may define a readResolve method which returns an object visible to other parties, or readUnshared may return a Class object or enum constant obtainable elsewhere in the stream or through external means. If the deserialized object defines a readResolve method and the invocation of that method returns an array, then readUnshared returns a shallow clone of that array; this guarantees that the returned array object is unique and cannot be obtained a second time from an invocation of readObject or readUnshared on the ObjectInputStream, even if the underlying data stream has been manipulated.

obj = input.readUnshared();

ArrayList Doesnt update contents over socket

The ObjectOutputStream, if you ask it to send an object it has already sent, simply sends a reference to the previously sent object. This is what allows sending a complex graph of objects, with bidirectional references or cycles between objects.

If you want the stream to forget about what it has already sent, then you need to call the reset() method.

socket programming serialized objects

The objects are being cached by the ObjectOutputStream. To prevent this, call ObjectOutputStream.reset() after each write. If you are sending simple objects that don't contain other objects, use writeUnshared() instead of writeObject().

Java object serialization/deserialization caching over socket

If write a single object more than once using the same ObjectOutputStream, the ObjectOutputStream will recognize that it has already seen that object and encode it as a reference to the existing object. This is how serialization is able to preserve reference aliasing.

If you don't want reference tracking across messages, construct a new ObjectOutputStream and ObjectInputStream pair for each new message (or #reset the ObjectOutputStream and #readUnshared from the ObjectInputStream). If you don't do either of these, but instead never modify and reuse message objects, you won't have the problem of modifications not being seen, but you'll instead leak resources since the ObjectInputStream will hold a strong reference to every object it's ever deserialized.

Reading Object from Socket Stream Isn't Getting Correct Values

Found the solution to my problem. I have to add the objectoutputstream reset method before I write my object into the output stream, so that it resets the stream and does not backtrack from previous objects.

You can read more about it here: Java socket/serialization, object won't update

The power of researching for the solution!

Java - serializable and sending object via socket

You can not serialize Socket object, therefore you should make socket field transient. If you need some of socket properties, you can put extra fields to Player to represent these fields.

JAVA - receiving objects using sockets and threads not working

JavaFX properties are not Serializable. So if you try to serialize an object that uses JavaFX properties for its state, you will get an exception.

You have a couple of options here. One is simply to not use Java object serialization, but some other serialization technique, such as representing the object with JSON.

The other option is to implement Externalizable instead of Serializable. Externalizable is a subinterface of Serializable in which you define your own process for serializing and deserializing the data. In particular, instead of serializing the JavaFX properties themselves, just serialize their contents.

A simple example:

import java.io.Externalizable ;
import java.io.IOException ;
import java.io.ObjectInput ;
import java.io.ObjectOutput ;

import javafx.beans.property.IntegerProperty ;
import javafx.beans.property.SimpleIntegerProperty ;
import javafx.beans.property.SimpleStringProperty ;
import javafx.beans.property.StringProperty ;

public class Person implements Externalizable {

private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty id = new SimpleIntegerProperty();

public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty().set(name);
}

public IntegerProperty idProperty() {
return id ;
}
public final int getId() {
return idProperty().get();
}
public final void setId(int id) {
idProperty().set(id);
}

// important: must have a no-arg constructor:
public Person() { }

public Person(int id, String name) {
setId(id);
setName(name);
}

@Override
public void writeExternal(ObjectOutput out) throws IOException {
// write id then name
// note we write the contents of the properties, not the properties
// themselves, as the properties are not serializable:
out.writeInt(getId());
out.writeObject(getName());
}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// read data back in same order:
setId(in.readInt());
setName((String)in.readObject());
}
}

Note that this class has a pretty simple structure, so it's easy to implement these two methods. For more complex objects - particularly those which may potentially have circular references - you need to work a bit harder.

Since the class defined above implements Externalizable, it also implements Serializable, and can be serialized in the usual way:

ObjectOutputStream oos = ... ;
oos.writeObject(new Person(007, "James Bond"));

Read my blog post on JavaFX beans and JPA for more.

Writing into an ObjectInputStream repeatedly

Use the same ObjectOutputStream and ObjectInputStream for the life of the socket, at both ends, and look up the ObjectOutputStream reset() and writeUnshared() methods.

See this answer for a discussion.



Related Topics



Leave a reply



Submit