Java - ObjectInputStream resolveProxyClass(String[] interfaces) method



Description

The Java ObjectInputStream resolveProxyClass(String[] interfaces) method returns a proxy class that implements the interfaces named in a proxy class descriptor; subclasses may implement this method to read custom data from the stream along with the descriptors for dynamic proxy classes, allowing them to use an alternate loading mechanism for the interfaces and the proxy class.

Declaration

Following is the declaration for java.io.ObjectInputStream.resolveProxyClass(String[] interfaces) method.

protected Class<?> resolveProxyClass(String[] interfaces)

Parameters

interfaces − The list of interface names that were deserialized in the proxy class descriptor.

Return Value

This method returns a proxy class for the specified interfaces.

Exception

  • IOException − Any exception thrown by the underlying InputStream.

  • ClassNotFoundException − If the proxy class or any of the named interfaces could not be found.

Example - Usage of ObjectInputStream resolveProxyClass(String[] interfaces) method

The following example shows the usage of Java ObjectInputStream resolveProxyClass(String[] interfaces) method.

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.Serializable;

public class ObjectInputStreamDemo extends ObjectInputStream {

   public ObjectInputStreamDemo(InputStream in) throws IOException {
      super(in);
   }

   public static void main(String[] args) {
      String s = "Hello World";
      
      try {
         // create a new file with an ObjectOutputStream
         FileOutputStream out = new FileOutputStream("test.txt");
         ObjectOutputStream oout = new ObjectOutputStream(out);

         // write something in the file
         oout.writeUTF(s);
         oout.flush();

         // create an ObjectInputStream for the file we created before
         ObjectInputStreamDemo ois = new ObjectInputStreamDemo(new FileInputStream("test.txt"));

         // create a list that will be used to resolve proxy class
         String[] list = {Serializable.class.getName()};

         // print the class proxy
         System.out.println("" + ois.resolveProxyClass(list));
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
}

Output

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

class com.sun.proxy.$Proxy0

Example - Resolving a Proxy Class

The following example shows the usage of Java ObjectInputStream resolveProxyClass(String[] interfaces) method. We create a dynamic proxy class that implements an interface, serialize it, and then override resolveProxyClass() to control its resolution during deserialization.

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.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      Object proxyInstance = Proxy.newProxyInstance(
         MyInterface.class.getClassLoader(),
         new Class<?>[]{MyInterface.class},
         new MyInvocationHandler()
      );

      // Step 1: Serialize proxy instance
      try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("proxy.ser"))) {
         oos.writeObject(proxyInstance);
         System.out.println("Proxy object serialized.");
      } catch (IOException e) {
         e.printStackTrace();
      }

      // Step 2: Deserialize with custom ObjectInputStream
      try (CustomObjectInputStream ois = new CustomObjectInputStream(new FileInputStream("proxy.ser"))) {
         Object obj = ois.readObject();
         System.out.println("Deserialized object: " + obj.getClass().getName());
      } catch (IOException | ClassNotFoundException e) {
         e.printStackTrace();
      }
   }
   static interface MyInterface extends Serializable {
      void myMethod();
   }

   // Invocation handler for the proxy
   static class MyInvocationHandler implements InvocationHandler, Serializable {
      private static final long serialVersionUID = 1L;

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         System.out.println("Proxy method called: " + method.getName());
         return null;
      }
   }

   // Custom ObjectInputStream to override resolveProxyClass()
   static class CustomObjectInputStream extends ObjectInputStream {
      public CustomObjectInputStream(InputStream in) throws IOException {
         super(in);
      }

      @Override
      protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
         System.out.println("Resolving Proxy Class...");
         ClassLoader loader = Thread.currentThread().getContextClassLoader();
         Class<?>[] interfaceClasses = new Class<?>[interfaces.length];

         for (int i = 0; i < interfaces.length; i++) {
            interfaceClasses[i] = Class.forName(interfaces[i], false, loader);
         }

         return Proxy.getProxyClass(loader, interfaceClasses);
      }
   }
}

Output

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

Proxy object serialized.
Resolving Proxy Class...
Deserialized object: com.mycompany.javaio.$Proxy0

Explanation

  • Creates a dynamic proxy that implements MyInterface.

  • Serializes the proxy object into a file.

  • Overrides resolveProxyClass() to manually load interface classes during deserialization.

  • Deserializes the proxy object and prints its class name.

Example - Blocking Certain Proxy Classes During Deserialization

The following example shows the usage of Java ObjectInputStream resolveProxyClass(String[] interfaces) method. We modify the deserialization process to block certain proxy classes (e.g., BlockedInterface) for security reasons.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      InvocationHandler handler = new MyInvocationHandler();
      Object blockedProxy = Proxy.newProxyInstance(
         BlockedInterface.class.getClassLoader(),
         new Class<?>[]{BlockedInterface.class},
         handler
      );

      // Step 1: Serialize proxy instance
      try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("blockedProxy.ser"))) {
         oos.writeObject(blockedProxy);
         System.out.println("Blocked Proxy object serialized.");
      } catch (IOException e) {
         e.printStackTrace();
      }

      // Step 2: Deserialize with security checks
      try (SecureObjectInputStream ois = new SecureObjectInputStream(new FileInputStream("blockedProxy.ser"))) {
         Object obj = ois.readObject();
         System.out.println("Deserialized object: " + obj.getClass().getName());
      } catch (InvalidClassException e) {
         System.out.println("Security Warning: " + e.getMessage());
      } catch (IOException | ClassNotFoundException e) {
         e.printStackTrace();
      }
   }

   static interface AllowedInterface extends Serializable {
      void allowedMethod();
   }

   static interface BlockedInterface extends Serializable {
      void blockedMethod();
   }

   static class MyInvocationHandler implements InvocationHandler, Serializable {
      private static final long serialVersionUID = 1L;

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         System.out.println("Blocked method called: " + method.getName());
         return null;
      }
   }

   // Custom ObjectInputStream to prevent blocked proxies
   static class SecureObjectInputStream extends ObjectInputStream {
      public SecureObjectInputStream(InputStream in) throws IOException {
         super(in);
         enableResolveObject(true);
      }

      @Override
      protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
         System.out.println("Resolving Proxy Class...");

         // Load classes for interfaces
         // ClassLoader loader = Thread.currentThread().getContextClassLoader();
         ClassLoader loader = ObjectInputStreamDemo.class.getClassLoader();
         Class<?>[] interfaceClasses = new Class<?>[interfaces.length];

         for (int i = 0; i < interfaces.length; i++) {
            interfaceClasses[i] = Class.forName(interfaces[i], false, loader);

            // Block Proxy Classes that Implement "BlockedInterface"
            if (interfaces[i].equals(BlockedInterface.class.getName())) {
               throw new InvalidClassException("Blocked proxy class: " + interfaces[i]);
            }
         }

         return Proxy.getProxyClass(loader, interfaceClasses);
      }
   }
}

Output

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

Blocked Proxy object serialized.
Resolving Proxy Class...
Security Warning: Blocked proxy class: com.tutorialspoint.ObjectInputStreamDemo$BlockedInterface

Explanation

  • Creates a proxy for BlockedInterface and serializes it.

  • Overrides resolveProxyClass() to check for restricted proxies.

  • If BlockedInterface is detected, it throws InvalidClassException.

  • Deserializing a blocked proxy will fail, preventing security risks.

java_io_objectinputstream.htm
Advertisements