5

Así que ahora mismo, tengo un servidor que se ejecuta con ObjectInputStream y ObjectOutputStream.¿Enviar una clase anónima a través de sockets? (Object..Stream en Java)

El problema que tengo es que tengo una clase personalizada (anónima) que extiende java.lang.Date que estoy tratando de enviar al cliente y luego compilar.

Así que en ninguna parte alguna vez defino la clase en el lado del cliente, pero quiero compilar la clase mediante programación. He intentado muchos métodos diferentes, pero cada vez obtengo un ClassNotFoundException porque la clase no está en el lado del cliente inicialmente.

Class<?> dateClass = (Class<?>) in.readObject(); //This is where the CNF Exception occurs 
Compiler.compileClass(dateClass); 

Respuesta

7

El mecanismo de serialización de Java asume las clases se sabe que la JVM deserializar, no envía las definiciones de clase. En particular, cuando serializa un objeto Class, no envía el código de bytes para esa clase, sino que solo indica a la máquina virtual receptora que busque el objeto Class para una clase con un nombre particular.

También tenga en cuenta que un objeto Class representa una clase definida en la JVM, es decir, el bytecode de la clase ya se ha cargado. Tiene poco sentido intentar compilar en clase para generar ese bytecode después de cargar la clase.

Por lo tanto, tenemos que obtener de alguna manera la definición de clase para el cliente. El enfoque más fácil es hacer esto como cualquier otra clase que el cliente necesite (empaquetándola en el archivo jar del cliente, o cualquier otro medio que use para instalar el programa cliente). Si eso no es posible, puede cargar la definición de clase en la red, por ejemplo, usando un URLClassLoader, o puede enviar el archivo de clase a través de la secuencia de serialización, y al recibirlo en el cliente, use ClassLoader.defineClass para cargar la clase.

PD: Este problema es completamente independiente de si la clase tiene nombre o no. El siguiente código de prueba muestra que los objetos de clases anónimas se pueden serializar y deserializar bien (si la máquina virtual receptor tiene la definición de clase):

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { 
     Serializable payload = new Serializable() { 
      @Override 
      public String toString() { 
       return "hello from the anonymous class"; 
      } 
     }; 
     oos.writeObject(payload); 
     oos.writeObject(payload.getClass()); 
    } 

    try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { 
     System.out.println(in.readObject()); 
     System.out.println(in.readObject()); 
    } 
+1

Esta es una respuesta mucho mejor que el Tosh concisa sobre nonymising, aunque eso es una palabra divertida Como "gelatina" y "gordura". Entonces, si votamos palabras divertidas, esta respuesta debería obtener esos votos ahora. – davidfrancis

+0

Eso es lo que originalmente estaba pensando. Enviar el archivo para la clase a través de la red y luego instalarlo en el DIR cuando llegue allí. Gracias por la tranquilidad: D – Avogadro

+0

Debería estar bien enviar la clase anon a través de un cargador de clases de red, por ejemplo, usar la carga de clase de rmi es la forma nativa de hacerlo. – davidfrancis

Cuestiones relacionadas