Freitag, 15. April 2011
Serialisierungsprobleme mit RMI (PR: 5A, 5B)
Remote Method Invocation funktioniert nur für Objekte, welche serialisiert werden können (die also das Interface
Dazu kann man die Methoden des Interfaces
Serializable
implementieren). Wird innerhalb eines Objekts, welches über RMI gebunden werden soll, eine Referenz auf ein nicht serialisierbares Objekt benötigt, so bekommt man immer eine Exception der Art (z.B. für RandomAccessFile
):sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source) java.rmi.Naming.rebind(Naming.java:177) rmi.Server.run(Server.java:43) rmi.Server.main(Server.java:68) error marshalling arguments; nested exception is: java.io.NotSerializableException: java.io.RandomAccessFile
RandomAccessFile
ist nicht serialisierbar, weil der innere Zustand so eines Objekts von der Laufzeitumgebung (Betriebssystem, Dateisystem, etc.) abhängt. Eine Referenz auf ein RandomAccessFile
-Objekt muss als transient
deklariert werden. Wenn nötig, dann muss der Zustand selbst gespeichert bzw. wiederhergestellt werden, z.B. in Form des Dateinamens und der Position innerhalb der Datei.Dazu kann man die Methoden des Interfaces
Serializable
implementieren:private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; private void readObjectNoData() throws ObjectStreamException;Für die Zwecke der
Data
-Klasse genügen die ersten beiden Methoden. Folgender Ausschnitt aus der Data
-Klasse soll dies verdeutlichen:public class Data implements DB, Header, Serializable { private static final long serialVersionUID = -8958941842720498616L; private transient RandomAccessFile database; private String filename; private transient Logger log = Logger.getLogger(LOGURL); private DBHeader header; private TreeMapHier ist auch der Logger transient, da auch der Logger vom Dateisystem abhängt und nicht serialisiert werden kann.data; private int lastDeleted = -1; // zuletzt gelöschter Datensatz private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); stream.writeLong(database.getFilePointer()); } private void readObject(ObjectInputStream stream) throws IOException { try { stream.defaultReadObject(); } catch (ClassNotFoundException e) { String msg = "Unable to find class"; if (e.getMessage() != null) msg += ": " + e.getMessage(); throw new IOException(msg); } database = new RandomAccessFile(filename, "rw"); database.seek(stream.readLong()); log = Logger.getLogger(LOGURL); } //... weiterer Code entfernt }
Abonnieren Posts [Atom]
Kommentar veröffentlichen