Java > Java Networking > Socket Programming > Socket Input and Output Streams
Object Serialization and Deserialization Over Sockets
This example demonstrates how to send Java objects over a socket connection using object serialization. The server receives a serialized object from the client, deserializes it, and then sends back a response. This showcases the use of ObjectInputStream
and ObjectOutputStream
.
Server Code (Object Serialization)
This server code creates a ServerSocket
to listen for incoming client connections on port 54321. When a client connects, it accepts the connection and obtains an ObjectInputStream
to read serialized objects from the client and an ObjectOutputStream
to send serialized objects back. The server reads a MyObject
instance, modifies it, and sends the modified object back to the client.
import java.io.*;
import java.net.*;
public class ObjectServer {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(54321)) {
System.out.println("Object Server is listening on port 54321");
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected: " + clientSocket.getInetAddress().getHostAddress());
// Input Stream from Client
ObjectInputStream objectInput = new ObjectInputStream(clientSocket.getInputStream());
// Output Stream to Client
ObjectOutputStream objectOutput = new ObjectOutputStream(clientSocket.getOutputStream());
try {
MyObject receivedObject = (MyObject) objectInput.readObject();
System.out.println("Server received object: " + receivedObject);
receivedObject.setMessage("Server processed: " + receivedObject.getMessage());
objectOutput.writeObject(receivedObject);
} catch (ClassNotFoundException e) {
System.err.println("Class not found: " + e.getMessage());
} finally {
clientSocket.close();
}
} catch (IOException e) {
System.err.println("Server exception: " + e.getMessage());
e.printStackTrace();
}
}
}
Client Code (Object Serialization)
The client code creates a Socket
to connect to the server. It creates an ObjectOutputStream
to send a MyObject
instance to the server and an ObjectInputStream
to receive the modified object back. It then prints the received object to the console.
import java.io.*;
import java.net.*;
public class ObjectClient {
public static void main(String[] args) {
String serverAddress = "localhost";
int serverPort = 54321;
try (Socket socket = new Socket(serverAddress, serverPort)) {
// Output Stream to Server
ObjectOutputStream objectOutput = new ObjectOutputStream(socket.getOutputStream());
// Input Stream from Server
ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
MyObject myObject = new MyObject("Hello from client!");
objectOutput.writeObject(myObject);
MyObject receivedObject = (MyObject) objectInput.readObject();
System.out.println("Client received object: " + receivedObject);
} catch (UnknownHostException e) {
System.err.println("Unknown host: " + serverAddress);
} catch (IOException e) {
System.err.println("Client exception: " + e.getMessage());
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.err.println("Class not found: " + e.getMessage());
}
}
}
MyObject Class (Serializable)
The MyObject
class is a simple class that implements the Serializable
interface. This allows instances of this class to be serialized into a byte stream and deserialized back into an object. It contains a message attribute and getter/setter methods.
import java.io.Serializable;
public class MyObject implements Serializable {
private String message;
public MyObject(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "MyObject{message='" + message + '\'' + '}';
}
}
Concepts Behind the Snippet
This example demonstrates object serialization, which is the process of converting an object into a byte stream. This byte stream can then be transmitted over a network or stored in a file. Deserialization is the reverse process of converting a byte stream back into an object. ObjectInputStream
and ObjectOutputStream
are used for object serialization and deserialization, respectively. The Serializable
interface is a marker interface that indicates that a class can be serialized.
Real-Life Use Case
Object serialization is used in several cases:
Best Practices
serialVersionUID
in your serializable classes to ensure compatibility during deserialization after class modifications.transient
.
Interview Tip
Understand the impact of serializing objects with complex relationships (e.g., circular dependencies). Also, be prepared to discuss the role of serialVersionUID
and how it affects serialization compatibility.
When to use them
Use object serialization when you need to easily transmit complex objects over a network connection or persist object states. It simplifies the process of converting objects to a format suitable for transmission or storage.
Memory footprint
The memory footprint during object serialization depends on the size of the object graph being serialized. Larger and more complex objects will require more memory. Be mindful of the size of serialized objects, especially when transmitting them over the network, to avoid performance bottlenecks.
Alternatives
Alternatives to Java serialization include:
Pros
Cons
FAQ
-
What is
serialVersionUID
?
serialVersionUID
is a static member field that identifies the version of a serialized class. It's used to ensure that the same class is loaded during deserialization as was used during serialization. If theserialVersionUID
of the class being deserialized does not match theserialVersionUID
of the class in the JVM, anInvalidClassException
will be thrown. -
What are transient fields?
Transient fields are fields that are marked with thetransient
keyword. These fields are not serialized during the serialization process. This is useful for fields that are derived or can be recomputed, or for fields that contain sensitive data that should not be serialized. -
How do I handle exceptions during serialization/deserialization?
Wrap the serialization and deserialization code in a try-catch block to handleIOException
andClassNotFoundException
. Also, consider logging the exceptions for debugging purposes.