Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Java - ObjectInputStream readClassDescriptor() method



Description

The Java ObjectInputStream readClassDescriptor() method reads and returns the class descriptor (ObjectStreamClass) for the next object in the serialization stream. readClassDescriptor() is protected, so it must be used inside a subclass of ObjectInputStream.

Declaration

Following is the declaration for java.io.ObjectInputStream.readClassDescriptor() method −

protected ObjectStreamClass readClassDescriptor()

Parameters

NA

Return Value

This method returns the class descriptor read.

Exception

  • ClassNotFoundException − If the Class of a serialized object used in the class descriptor representation cannot be found.

  • IOException − If an I/O error has occurred.

Example - Logging and Debugging Class Descriptors

The following example shows the usage of Java ObjectInputStream readClassDescriptor() method. This example logs class descriptor information to track serialization changes.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;

class Product implements Serializable {
   private static final long serialVersionUID = 2L;
   String name;
   double price;

   public Product(String name, double price) {
      this.name = name;
      this.price = price;
   }
}

// Custom ObjectInputStream to log class descriptor details
class LoggingObjectInputStream extends ObjectInputStream {
   public LoggingObjectInputStream(InputStream in) throws IOException {
      super(in);
   }

   @Override
   protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
      ObjectStreamClass descriptor = super.readClassDescriptor();
      System.out.println("Reading Class Descriptor: " + descriptor.getName());
      System.out.println("SerialVersionUID: " + descriptor.getSerialVersionUID());
      return descriptor;
   }
}

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      try {
         // Serialize Product object
         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("product.dat"));
         oos.writeObject(new Product("Laptop", 1200.99));
         oos.close();

         // Deserialize with logging
         LoggingObjectInputStream ois = new LoggingObjectInputStream(new FileInputStream("product.dat"));
         Product product = (Product) ois.readObject();
         ois.close();

         System.out.println("Deserialized Product: " + product.name + ", " + product.price);
      } catch (IOException | ClassNotFoundException e) {
         e.printStackTrace();
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Reading Class Descriptor: Product
SerialVersionUID: 2
Deserialized Product: Laptop, 1200.99

Explanation

  • Serializes a Product object.

  • Logs the class descriptor before deserialization.

  • Helps detect class version changes (serialVersionUID).

Example - Reading and Printing Class Descriptor

The following example shows the usage of Java ObjectInputStream readClassDescriptor() method. This example reads the class descriptor of a serialized object and prints its metadata.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;

class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    String name;
    int age;

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

// Custom ObjectInputStream to read class descriptor
class CustomObjectInputStream extends ObjectInputStream {
    public CustomObjectInputStream(InputStream in) throws IOException {
        super(in);
    }

    @Override
    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
        ObjectStreamClass descriptor = super.readClassDescriptor();
        System.out.println("Class Name: " + descriptor.getName());
        System.out.println("SerialVersionUID: " + descriptor.getSerialVersionUID());
        return descriptor;
    }
}

public class ObjectInputStreamDemo {
    public static void main(String[] args) {
        try {
            // Serialize object
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("employee.dat"));
            oos.writeObject(new Employee("Alice", 30));
            oos.close();

            // Deserialize object and read class descriptor
            CustomObjectInputStream ois = new CustomObjectInputStream(new FileInputStream("employee.dat"));
            Employee emp = (Employee) ois.readObject();
            ois.close();

            System.out.println("Deserialized Employee: " + emp.name + ", " + emp.age);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Output

Let us compile and run the above program, this will produce the following result−

Class Name: Employee
SerialVersionUID: 1
Deserialized Employee: Alice, 30

Explanation

  • Serializes an Employee object to employee.dat.

  • Custom ObjectInputStream reads the class descriptor before deserializing.

  • Prints the class name and serialVersionUID.

Example - Modifying Class Descriptor Before Deserialization

The following example shows the usage of Java ObjectInputStream readClassDescriptor() method. This example changes the class name in the descriptor, useful for migrating old class versions.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;

// Old class (Simulating an old version)
class OldEmployee implements Serializable {
   private static final long serialVersionUID = 1L;
   String fullName;
   int age;

   public OldEmployee(String fullName, int age) {
      this.fullName = fullName;
      this.age = age;
   }
}

// New class
class NewEmployee implements Serializable {
   private static final long serialVersionUID = 1L;
   String name;
   int age;

   public NewEmployee(String name, int age) {
      this.name = name;
      this.age = age;
   }

   @Override
   public String toString() {
      return "NewEmployee{name='" + name + "', age=" + age + "}";
   }
}

// Custom ObjectInputStream to change class descriptor
class VersionedObjectInputStream extends ObjectInputStream {
   public VersionedObjectInputStream(InputStream in) throws IOException {
      super(in);
   }

   @Override
   protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
      ObjectStreamClass descriptor = super.readClassDescriptor();
      if (descriptor.getName().equals("com.tutorialspoint.OldEmployee")) {
         return ObjectStreamClass.lookup(NewEmployee.class); // Change class mapping
      }
      return descriptor;
   }
}

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      try {
         // Serialize OldEmployee object
         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("employee_v2.dat"));
         oos.writeObject(new OldEmployee("John Doe", 40));
         oos.close();

         // Deserialize with modified class mapping
         VersionedObjectInputStream ois = new VersionedObjectInputStream(new FileInputStream("employee_v2.dat"));
         NewEmployee emp = (NewEmployee) ois.readObject();
         ois.close();

         System.out.println("Deserialized Employee: " + emp);
      } catch (IOException | ClassNotFoundException e) {
         e.printStackTrace();
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Deserialized Employee: NewEmployee{name='John Doe', age=40}

Explanation

  • Serializes an OldEmployee object.

  • Custom ObjectInputStream changes the descriptor to NewEmployee.

  • Maps old serialized data to a new class, enabling version migration.

java_io_objectinputstream.htm
Advertisements