14 Stimmen

Java-Socket/Serialisierung, Objekt lässt sich nicht aktualisieren

Ich schreibe ein kleines Socket-basiertes Programm. Ich verwende eine Klasse ModelEvent, um Informationen über den Socket zu übergeben. Innerhalb von ModelEvent gibt es eine Variable obect vom Typ (Object).

Das Objekt selbst ist ein 2D-Array mit einigen Werten.

object[1][2] = 2;
ModelEvent event = new ModelEvent("allo", object);
dispatchEvent(event);

object[2][3] = 2;
ModelEvent event2 = new ModelEvent("you", object);
dispatchEvent(event2);

Nehmen wir an, dass das Array-Objekt mit dem Wert 1 gefüllt ist. Das erste Ereignis (Event) wird vom Client empfangen, und die Daten sind richtig. Das zweite Ereignis wird gesendet, obwohl die Daten nicht richtig sind. Seine Daten sind die gleichen wie in der ersten Versendung. die "allo" und "Sie" ist, um zu sehen, ob ich nicht lesen das gleiche Ereignis zweimal und die Antwort ist es nicht. Die Zeichenfolge ist richtig, aber das Objekt ist nicht, Veranstaltung, wenn es aktualisiert wurde. Ich durchlaufe das Array, bevor ich das zweite Ereignis sende, um zu sehen, ob es auf der Serverseite aktualisiert wurde, und das ist es. Aber auf der Client-Seite, es bleiben immer noch die gleichen wie in der ersten Sendung, auch wenn das Ereignis selbst geändert wird.

29voto

obataku Punkte 28674

Siehe [ObjectOutputStream.reset](http://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html#reset()) .

Beim Zurücksetzen wird der Zustand von Objekten, die bereits in den Stream geschrieben wurden, nicht berücksichtigt. Der Zustand wird so zurückgesetzt, dass er dem eines neuen ObjectOutputStream . Der aktuelle Punkt im Stream wird als zurückgesetzt markiert, so dass der entsprechende ObjectInputStream werden an der gleichen Stelle zurückgesetzt. Bei Objekten, die bereits in den Stream geschrieben wurden, wird nicht darauf verwiesen, dass sie sich bereits im Stream befinden. Sie werden erneut in den Stream geschrieben.

/* prevent using back references */
output.reset();
output.writeObject(...);

Rufen Sie reset vor dem Schreiben desselben Objekts auf, um sicherzustellen, dass sein aktualisierter Zustand serialisiert wird. Andernfalls wird lediglich ein Rückverweis auf das zuvor geschriebene Objekt mit seinem veralteten Zustand.

Alternativ dazu können Sie auch ObjectOutputStream.writeUnshared wie folgt.

Schreibt ein "nicht geteiltes" Objekt in den ObjectOutputStream . Diese Methode ist identisch mit writeObject mit dem Unterschied, dass das angegebene Objekt immer als neues, eindeutiges Objekt in den Stream geschrieben wird (im Gegensatz zu einer Rückreferenz, die auf eine zuvor serialisierte Instanz zeigt).

Konkret:

  • Ein über writeUnshared geschriebenes Objekt wird immer auf die gleiche Weise serialisiert wie ein neu auftretendes Objekt (ein Objekt, das noch nicht in den Stream geschrieben wurde), unabhängig davon, ob das Objekt zuvor geschrieben wurde oder nicht.

  • Si writeObject verwendet wird, um ein Objekt zu schreiben, das zuvor mit writeUnshared geschrieben wurde, wird die vorherige writeUnshared-Operation so behandelt, als ob es sich um das Schreiben eines separaten Objekts handelt. Mit anderen Worten, ObjectOutputStream wird niemals Rückverweise auf Objektdaten erzeugen, die durch Aufrufe von writeUnshared .

Beim Schreiben eines Objekts über writeUnshared an sich keinen eindeutigen Verweis auf das Objekt garantiert, wenn es deserialisiert wird, ermöglicht es, ein einzelnes Objekt mehrfach in einem Stream zu definieren, so dass mehrere Aufrufe von readUnshared des Empfängers nicht in Konflikt geraten. Beachten Sie, dass die oben beschriebenen Regeln nur für das Basisobjekt gelten, das mit writeUnshared und nicht auf irgendwelche transitorisch referenzierten Unterobjekte im zu serialisierenden Objektgraphen.

output.writeUnshared(...);

Beachten Sie, dass es gute Praxis ist, dies mit [ObjectInputStream.readUnshared](http://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html#readUnshared()) .

Liest ein "nicht geteiltes" Objekt aus dem ObjectInputStream . Diese Methode ist identisch mit readObject, mit der Ausnahme, dass sie nachfolgende Aufrufe von readObject y readUnshared zusätzliche Verweise auf die durch diesen Aufruf erhaltene deserialisierte Instanz zurückzugeben.

Konkret:

  • Si readUnshared aufgerufen wird, um eine Rückreferenz (die Stream-Darstellung eines Objekts, das zuvor in den Stream geschrieben wurde) zu deserialisieren, wird ein ObjectStreamException wird geworfen
  • Si readUnshared erfolgreich zurück, dann werden alle nachfolgenden Versuche, Rückverweise auf das Stream-Handle zu deserialisieren, das von readUnshared wird eine ObjectStreamException geworfen zu werden.

Deserialisieren eines Objekts über readUnshared macht den mit dem zurückgegebenen Objekt verbundenen Stream-Handle ungültig. Beachten Sie, dass dies an sich keine Garantie dafür ist, dass die Referenz, die von readUnshared ist eindeutig; das deserialisierte Objekt kann eine readResolve Methode, die ein für andere Parteien sichtbares Objekt zurückgibt, oder readUnshared kann ein Class Objekt oder enum Konstante, die an anderer Stelle des Stroms oder durch externe Mittel erhältlich ist. Wenn das deserialisierte Objekt eine readResolve Methode und der Aufruf dieser Methode gibt ein Array zurück, dann readUnshared gibt einen flachen Klon dieses Arrays zurück; dies garantiert, dass das zurückgegebene Array-Objekt eindeutig ist und nicht ein zweites Mal durch einen Aufruf von readObject oder readUnshared auf dem ObjectInputStream auch wenn der zugrunde liegende Datenstrom manipuliert wurde.

obj = input.readUnshared();

4voto

roni bar yanai Punkte 1452

Ich sehe den dispatchEvent-Code nicht, aber von dem, was Sie geschrieben haben, nehme ich Folgendes an: Sie schreiben das gleiche Objekt (nur sein Zustand geändert), das heißt, es wird nur die Referenz zweimal schreiben. Sie können in Java-Ausgabe-Stream-Dokumente (für die Leistung) zu sehen.

sollten Sie writeUnshared() verwenden, das bei jedem Schreibvorgang ein neues Objekt erzeugt

Ich sehe, dass Reset vorgeschlagen wurde. Dies führt zum gleichen Ergebnis, hat aber Auswirkungen auf die Leistung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X