Este proceso también se puede implementar a través de la red, que primero puede crear un objeto en la máquina de Windows, serializarlo y luego enviarlo a una máquina Unix a través de la red, y luego volver a ensamblarlo con precisión. ¿Por qué cada uno de los objetos Java de RMI, Socket, JMS y EJB?
El mecanismo de serialización del objeto Java generalmente tiene dos usos:
Java Javabeans: la información de estado de Bean generalmente se configura en el tiempo de diseño. . Lea el estado del objeto para reconstruir el objeto y restaurar el estado del programa.
RMI permite que los objetos en máquinas remotas se operen como en máquinas nativas;
Podemos serializar las clases haciendo que las clases implementen la interfaz Java.io.Serializable. Esta interfaz es una interfaz del fabricante. Es decir, para que la clase la implementa, la interfaz no necesita implementar ningún método. Se utiliza principalmente para notificar a Java Virtual Machines (JVMS) que un objeto necesita ser serializado.
Hay algunos puntos que debemos aclarar esto:
No todas las clases pueden ser serializadas.
Hay muchas clases básicas en Java que han implementado interfaces serializables, como cadena, vector, etc. Pero, por ejemplo, Hashtable no implementa la interfaz Serializable.
Hay dos clases principales para leer o escribir objetos a las transmisiones: ObjectOutputStream y ObjectInputStream.ObjectOutputStream proporciona un método WriteObject utilizado para escribir objetos en la transmisión de salida, y ObjectInputStream proporciona un método Readobject para leer objetos de la secuencia de entrada. Los objetos que usan estos métodos deben haber sido serializados. Es decir, la interfaz serializable debe haberse implementado. Si desea escribir un objeto hashtable, obtendrá una excepción.
El proceso de serialización es escribir objetos y leer objetos de la transmisión de bytes. Después de convertir el estado del objeto en una secuencia de bytes, puede guardarlo en un archivo utilizando varias clases de transmisión de bytes en el paquete Java.io, tuve en otro hilo o enviar datos de objetos a otro host a través de una conexión de red. La función de serialización del objeto es muy simple y potente, y se usa en RMI, Socket, JMS y EJB. El problema de serialización del objeto no es el tema más emocionante en la programación de redes, pero es bastante importante y tiene muchos significados prácticos.
La serialización de los objetos puede implementar objetos distribuidos. Aplicaciones principales como: RMI utiliza la serialización de objetos para ejecutar servicios en hosts remotos, al igual que cuando se ejecuta objetos en máquinas locales.
La serialización del objeto Java no solo conserva los datos de un objeto, sino que también guarda de manera recursiva los datos de cada objeto referenciado por el objeto. Toda la jerarquía de objetos se puede escribir en una secuencia de bytes, guardar en un archivo o pasar en una conexión de red. La serialización del objeto se puede usar para realizar una "copia profunda" del objeto, es decir, copiar el objeto en sí y el objeto en el referenciado mismo. La serialización de un objeto puede dar lugar a toda la secuencia de objetos.
La serialización de Java es relativamente simple y generalmente no requiere escribir código personalizado para guardar y restaurar el estado del objeto. Los objetos de clase que implementan la interfaz Java.io.Serializable se pueden convertir o recuperarse de las secuencias de bytes sin agregar ningún código a la clase. Solo en casos raros se requiere código personalizado para guardar o restaurar el estado del objeto. Nota aquí: no todas las clases pueden ser serializadas, y algunas clases no pueden ser serializadas.
Mecanismo de serialización:
La serialización se divide en dos partes: serialización y deserialización. La serialización es la primera parte de este proceso, dividiendo los datos en un flujo de bytes para el almacenamiento en un archivo o transmisión a través de una red. La deserialización es abrir la corriente de byte y reconstruir el objeto. La serialización de los objetos no solo requiere convertir el tipo de datos básicos en la representación de bytes, sino que a veces también recupera los datos. La recuperación de datos requiere una instancia del objeto que restaura los datos. El proceso de serialización en ObjectOutputStream está conectado a una secuencia de bytes, que incluye el tipo de objeto y la información de la versión. Durante la deserialización, el JVM genera una instancia de objeto con información del encabezado y luego copia los datos de la secuencia de bytes del objeto a los miembros de los datos del objeto. Vamos a explicarlo en dos partes:
Flujo de objetos de procesamiento: ( proceso de serialización y proceso de deserialización)
El paquete Java.io tiene dos clases que serializan objetos. ObjectOutputStream es responsable de escribir objetos en una secuencia de bytes, y ObjectInputStream reconstruye objetos de una secuencia de bytes.
Primero entendamos la clase ObjectOutputStream. La clase ObjectOutputStream extiende la interfaz DataOutput.
El método WriteObject () es el método más importante para la serialización de los objetos. Si el objeto contiene referencias a otros objetos, el método WriteObject () es serializa recursivamente estos objetos. Cada ObjectOutputStream mantiene una tabla de referencia de objeto serializada para evitar que se envíen múltiples copias del mismo objeto. (Esto es importante) Dado que WriteObject () puede serializar todo el conjunto de objetos de referencia cruzada, se puede solicitar accidentalmente la misma instancia de ObjectOutputStream para serializar el mismo objeto. En este momento, la serialización antirreferencia se realiza en lugar de escribir en la transmisión de bytes del objeto nuevamente.
A continuación, comprendamos la clase ObjectOutputStream del ejemplo.
La copia del código es la siguiente:
// Serializa la fecha de hoy en un archivo.
FileOutputStream F = nuevo FileOutputStream ("TMP");
ObjectOutputStream S = nuevo ObjectOutputStream (f);
S.WriteObject ("hoy");
S.WriteObject (nueva fecha ());
S.Flush ();
Ahora, comprendamos la clase ObjectInputStream. Es similar a ObjectOutputStream. Extiende la interfaz DataAnput. Métodos en ObjectInputStream refleja el método público para leer los tipos de datos básicos de Java en DataInputStream. El método ReadObject () deserializa un objeto de una secuencia de bytes. Cada vez que se llama el método ReadObject (), se devuelve el siguiente objeto en la secuencia. La secuencia de bytes del objeto no transmite el código bytecodo de la clase, pero incluye el nombre de la clase y su firma. Cuando ReadObject () recibe el objeto, el JVM carga la clase especificada en el encabezado. Si no se puede encontrar esta clase, ReadObject () lanza una ClassNotFoundException. El resto de los métodos ObjectInputStream se utilizan para personalizar el proceso de deserialización.
Los ejemplos son los siguientes:
La copia del código es la siguiente:
// Deserializar objetos de cadena y objetos de fecha desde el archivo
FileInputStream in = new FileInputStream ("TMP");
ObjectInputStream S = New ObjectInputStream (in);
String Today = (String) S.ReadObject ();
Fecha fecha = (fecha) s.ReadObject ();
Proceso de serialización personalizado:
La serialización generalmente se puede hacer automáticamente, pero a veces el proceso puede controlarse. Java puede declarar clases como serializables, pero aún puede controlar manualmente a los miembros de los datos declarados como estáticos o transitorios.
Ejemplo: una clase de serialización muy simple.
La copia del código es la siguiente:
clase pública SimplePleSerializableClass implementa serializable {
String stoday = "Today:";
fecha transitoria dttoday = new Date ();
}
Al serializar, todos los miembros de los datos de la clase deben ser serializables, excepto los declarados transitorios o estáticos. Declarando la variable como transitorio le dice a JVM que seremos responsables de serializar los argumentos. Después de declarar un miembro de datos como transitorio, el proceso de serialización no puede agregarlo a la secuencia de bytes del objeto, y no hay datos enviados desde el miembro de datos transitorios. Al deserializar los datos posteriores, el miembro de los datos debe reconstruirse (porque es parte de la definición de clase), pero no contiene ningún datos porque este miembro de datos no escribe ningún dato en la transmisión. Recuerde que las corrientes de objeto no serializan estáticos o transitorios. Nuestra clase necesita usar los métodos WriteObject () y ReadObject () para procesar estos miembros de datos. Al usar los métodos WriteObject () y ReadObject (), también debe prestar atención a leer estos miembros de datos en el orden en que están escritos.
Algunos de los códigos sobre cómo usar la serialización personalizada son los siguientes
La copia del código es la siguiente:
// Reescribe el método WriteObject () para manejar los miembros transitorios.
public void writeObject (ObjectOutputStream OutputStream) lanza ioexception {
outputStream.defaultWriteObject (); // hacer el método de writeObject () personalizado para
// Use la lógica incorporada en serialización automática.
outputStream.WriteObject (Osocket.GetInetAddress ());
outputStream.WriteInt (Osocket.getPort ());
}
// Reescribe el método ReadObject () para recibir miembros transitorios.
Private void ReadObject (ObjectInputStream InputStream) lanza ioexception,
ClassNotFoundException {
InputStream.defaultreadObject (); // defaultreadObject () Suplementos de serialización automática
Inetaddress oaddress = (inetAddress) inputStream.ReadObject ();
int iPort = inputStream.ReadInt ();
Osocket = nuevo socket (oaddress, iPort);
iid = getId ();
dttoday = new Date ();
}
Personaliza completamente el proceso de serialización:
Si una clase es completamente responsable de su propia serialización, implementa la interfaz externalizable en lugar de la interfaz serializable. La definición de interfaz externalizable incluye dos métodos WriteExternal () y ReadExternal (). Estos métodos se pueden usar para controlar cómo se escriben los miembros de los datos de los objetos en las transmisiones de bytes. , no hay serialización automática en absoluto. Presta atención aquí. La clase de declaración implementa interfaces externalizables con riesgos de seguridad significativos. Los métodos WriteExternal () y ReadExternal () se declaran públicos, y las clases maliciosas pueden usar estos métodos para leer y escribir datos de objetos. Si el objeto contiene información confidencial, tenga mucho cuidado. Esto incluye usar enchufes seguros o encriptar todo el flujo de bytes. En este punto, hemos aprendido el conocimiento básico de la serialización.