Circular reference - Serialisierung

Kr0e

Gesperrter Benutzer
Hallo!

ich wollte heute meinem Serialisierungmechanismus (Nciht die Java Serialisierung!) die Fähigkeiten bescheren, "Circular References" zu beherrschen.

Erst dachte ich :

"hm, ansich sollte das ja total einfach sein! Einfach alle Objekte mit einer HashMap vergleichen beim schreiben und wenn es das Objekt bereits gibt, einfach den Index schreiben, wo diese Objekt zu finden ist" - Aber beim deserialisieren kam ich dann in einen logischen Konflikt =(.

Kurz zum hintergrund: Einige kennen vlt. "Kryo" (Kann leider auch nicht Circular-References ab..)... So ähnlcih ist auch mein Serialisierungskonzept. Hier und da etwas anders, aber im Prinzip ähnlich.

Nun mein logisches Problem wäre z.B. sowas hier:

Java:
        Object[] o = new Object[]{"0123456789", "0123456789", null};
        o[2] = o;

Der 2te String wird einfahc nur als Index geschrieben, denn der erste String ist ja identisch. Als dritten Wert bekommt das Objektarray eine REferenz auf sich selbst... hier endet Kryo natürlich in einem StackOverflow... Java Serialisierung nicht und mich würde gerne interesieren, wie die das macht.

Ich meine klar, beim serialisieren ist das kein Problem:

(Auszug aus meinem System)
Java:
        //Put the index
        Integer oldIndex = cache.get(message);

        if (oldIndex != null) {
            //Put invalid codec id
            raw().put((byte) CodecRegistry.INVALID_CODEC_ID);

            //Write the old index
            raw().putInt(oldIndex);    //HIER schreibe ich einfach den Index des alten Codecs.
        } else {
            //Put in cache
            cache.put(message, objectCounter);  //HIER füge ich das unique object in die map ein, da es das erste ist seiner art...

            //Write object
            writeObject(message, writeCodec(message)); //DAS ist nicht Java Serialisierung, sondern mein System...
        }

        //Just increase the object counter...
        objectCounter++;

Nun beim Deserialisieren gibt es aber bei mir folgendes Problem:
(BTW: Es wird rekursiv serialisiert und deserialisiert!)

Hier mal etwas pseudo code:

LESE CodecId
FALLS CodecId = CIRCULAR_REFERENCE...
GIB_ZURÜCK object_aus_cache
ANSONSTEN
*OBJECT* = DESERIALISIERE NORMAL!

SPEICHERE *OBJECT* NUN IM CACHE

GIB_ZURÜCK *OBJECT*


Zurück beim Arraybeispiel hab nun das Problem, dass quasi mein Codec aufgerufen wird, der Arrays speichert - Dieser ruft dann für alle Inhalte den jeweiligen Codec auf und-so-weiter.

Beim dritten Objekt gäbe es nun eine Zwickmühle:

Das Problem weiß zwar "Hey, das folgende Objekt, bist du selbst!" - Also der dritte Paramter ist ja das Array selber... Aber wie aus dem Pseudocode zu erkennen ist, kann ja beim deserialsieren, die Objekte erst in den Cache packen, sobald sie "DESERIALISIERT" sind... Sprich das Object[]-Array ist erst deserialisiert, wenn alle komponenten auch serialisiert sind...

Ich hoffe, ich kann mein Problem einigermaßen verständlich machen....

Leider hab ich grad ein Brett vorm Kopf und mir fällt einfach nicht ein, wie ich den Algorithmus anpassen kann.

Danke schonmal =)

Gruß,

Chris
 

Marco13

Top Contributor
Erst dachte ich :

"hm, ansich sollte das ja total einfach sein!


Offenbar ist es recht nahe liegend, das zu denken :oops:

Es ist jetzt nicht klar, was "deserialisiere normal" genau macht, aber vielleicht ist das auch nicht so wichtig. Irgendwie muss die Rekursion abbrechen. Unabhängig davon, wie man das genau im Programm umsetzt: Wäre das Problem nicht gelöst, wenn man sich merken würde, welche Objekte gerade eben serialisiert werden (quasi die, die im Stack weiter oben stehen), sich merkt, wo diese Objekte verwendet werden sollen (da bricht man dann die Rekursion ab, weil die Objekte ja noch nicht fertig sind), und man, sobald man den Stack wieder runterläuft und die Objekte "fertig" werden, sie an alle Stellen schreibt, wo sie gebraucht worden wären?
(Insbesondere das letzte wäre eben tricky, aber... vielleicht findet man da ja eine Möglichkeit)
 

Kr0e

Gesperrter Benutzer
Hi Marco,

ja ich hatte schon befuerchtet, dass ich sowas in der Art einbauen muss :(. Ich hatte allerdings gehofft , die Fasade ansich nicht zu aendern... Mal sehen gut sich sowas nachtraeglich integrieren laesst...

DAs GRundproblem ist einfach, dass das Objekt das quasi ne Circular-Reference hat, nicht fertig ist ohne diese. Von daher kann ich ja nicht einfach abbrechen... Ich koennte hoechsten im Falle einer Circular-Reference zuerat null ausgeben und danach dann den verweis finden und ihn erneut fuellen, aber dann mit dem aktuellen Wert...

Hm...

Danke und Gruss,

Chris
 

Marco13

Top Contributor
Hmja, wie gesagt, eine konkrete Idee für die Umsetzung hätte ich nicht - also speziell wie man sich diese "Da-muss-ich-noch-was-schreiben"-Sache merken könne. (Ein Runnable in eine Queue? :rolleyes: Vermutlich sollte es ja auch noch effizient sein ... obwohl die Anzahl der Stellen, an denen das nötig wäre, vielleicht gar nicht so hoch wäre - es sind ja nur die Stellen, wo sich ein Kreis schließt...)
 

Kr0e

Gesperrter Benutzer
Lustig wirds, (faellt mir grad noch ein...) wenn ein Objekt, dass sich gerade wieder herstellt quasi, diesen Wert braucht, um andere Wert zu initialisieren ... Ich hab versucht, aus der ObjektInputStream Sache schlau zu werden, aber die haben sich da ja vlt was zusammen gehudelt... >D

Naja, genug fuer heute...

Gruss,

Chris
 

Illuvatar

Top Contributor
Eigentlich müsste man doch nicht viel ändern, denke ich
Code:
ANSONSTEN
  *OBJECT* = DESERIALISIERE NORMAL!
  SPEICHERE *OBJECT* NUN IM CACHE
Bei dem Ding weiß man (wie Marco gesagt hat) eben nicht, was "deserialisiere normal" bedeutet. Aber müsste man nicht etwas in der Art draus machen können:
Code:
ANSONSTEN
  ERSTELLE *OBJECT* (mit default-Werten)
  SPEICHERE *OBJECT* NUN IM CACHE
  DESERIALISIERE INHALTE VON *OBJECT* (NORMAL?)
 

Kr0e

Gesperrter Benutzer
Hi!


Ja ich hätte das gestern noch genauer erklären müssen...

Ich poste mal das Codec-Interface von dem ich so oft rede:

Java:
package com.pote.engine.util.data.serialization;

/**
 *
 * @author Christopher Probst
 */
public interface Codec {

    public Object decode(Decoder decoder, CodecRegistration codecRegistration)
            throws Exception;

    public void encode(Encoder encoder, CodecRegistration codecRegistration,
            Object message) throws Exception;

    public Class<?>[] getMessageTypes();

    public MessageFilter[] getMessageFilters();
}

Nun, die letzten beiden Methoden sind nicht relevant für das deserialisieren ansich... grundsätzlich funktioniert das Ganze so, dass man am Anfang mit Hilfe eines ServiceLoaders, alle verfügbaren Codecs aufspürt und dann diese in der CodecRegistry speichert.

Ein Codec kann für mehrere Classes bzw mehrere MessageFilters registriert werden.

Das Problem ist nun, dass quasi das hier leider nicht geht:

ANSONSTEN
ERSTELLE *OBJECT* (mit default-Werten)
SPEICHERE *OBJECT* NUN IM CACHE
DESERIALISIERE INHALTE VON *OBJECT* (NORMAL?)

Denn das Erstellen des Objektes geschieht parallel mit dem füllen der Inhalte innerhalb der decode()-Methode. Ich denke das ist auch genau das Problem... Java Serialisierung schickt ja die Namen der Klassen und erstellt diese aus dem nichts und füllt sie dann...

Ich wollte hier Speicherbedarf sparen und nur typeIds (als Byte, ich hab nicht mehr als 255 Typen z. Z.) Und wenn quasi beim Decoder die Id des StringDEcoders drinsteht, dann wird die Methode "decode" vom StringDecoder aufgerufen... Dieser kümmert sich dann um die Deserialisierung.

Ich werde dann wohl diesen Weg gehen müssen... Also quasi dem Decoder eine Methode "publishToCache" oder so bescheren. Dann ist allerdings der User des Codecs dafür verantwortlich, dass Objekte im Cache landen, bevor diese auch geholt werden können...

Nagut, danke soweit!

Gruß,

Chris
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Kirby.exe Cannot make a static reference to the non-static field rimWidth Allgemeine Java-Themen 12
R Erste Schritte Object reference funktioniert nicht. Wie mach ichs richtig? Allgemeine Java-Themen 3
M Lambda "invalid method reference no suitable method found" Allgemeine Java-Themen 2
W Threads Cannot make a static reference.. Allgemeine Java-Themen 13
M Java - Call by value <-> Call by reference Allgemeine Java-Themen 16
S Cannot make a static reference to the non-static field MySecondClass.Points Allgemeine Java-Themen 3
E wie call by reference mit Wrapper-Klassen? Allgemeine Java-Themen 2
Schandro Warum illegal forward reference bei Exemplarinitialisierer Allgemeine Java-Themen 9
F Pointer oder Reference? Allgemeine Java-Themen 8
G Reference-Counter Allgemeine Java-Themen 3
B Array von Vektoren by reference übergeben Allgemeine Java-Themen 5
conan2 "Cannot make a static reference to the non-static field Allgemeine Java-Themen 8
A Static reference to non-static field Allgemeine Java-Themen 10
sliwalker Call by Reference - Was stimmt denn nun ? Allgemeine Java-Themen 14
H Aus der FAQ: Call by Value <-> Call by Reference Allgemeine Java-Themen 8
O Pointer/reference on method Allgemeine Java-Themen 10
antonia09 Einkaufszettel Persistenz und Serialisierung Allgemeine Java-Themen 6
D Serialisierung und Deserialisierung von Objekten - Frageprogramm Allgemeine Java-Themen 4
R Datentypen Korrekte integer in Hex ASCII Konvertierung und serialisierung Allgemeine Java-Themen 1
M Serialisierung funktioniert nicht Allgemeine Java-Themen 9
Z Best Practice Serialisierung Allgemeine Java-Themen 2
Arif Input/Output Serialisierung - Datei wird nicht erzeugt Allgemeine Java-Themen 3
M Alternative zur Serialisierung.. Protobuf? Allgemeine Java-Themen 9
E Serialisierung - Deserialisierung Allgemeine Java-Themen 4
Thallius Serialisierung schlägt fehl. Allgemeine Java-Themen 3
M Serialisierung & Verschlüsselung Allgemeine Java-Themen 2
E Serialisierung - Sinn einer generierten serialVersionUID? Allgemeine Java-Themen 4
V Serialisierung von Instanz eigener Klasse Allgemeine Java-Themen 5
A Input/Output Serialisierung und Object.hashCode() Allgemeine Java-Themen 3
K Serialisierung einer verschachtelten Datenstuktur Allgemeine Java-Themen 9
Tobse Input/Output Dateiformat: Serialisierung VS Custom format Allgemeine Java-Themen 6
A Problem bei Serialisierung von Bibliotheks-Klassen Allgemeine Java-Themen 6
A Input/Output Serialisierung Sonderzeichen Allgemeine Java-Themen 3
P Serialisierung der Oberklasse Allgemeine Java-Themen 2
K Serialisierung in Properties-Datei möglich? Allgemeine Java-Themen 3
B Serialisierung mit Unterobjekten über Netzwerk Allgemeine Java-Themen 3
C Serialisierung - Standardwert für nachträglich hinzugefügtes Feld Allgemeine Java-Themen 2
S Serialisierung der Kindklasse Allgemeine Java-Themen 5
K Serialisierung komplett selbst machen Allgemeine Java-Themen 13
C Serialisierung ohne Serializable Allgemeine Java-Themen 4
S Serialisierung und Referenzen Allgemeine Java-Themen 6
S Viele Bilder -> Speicher ausgelastet? / (De-)serialisierung geht nicht mehr richtig Allgemeine Java-Themen 8
E Objekt bei Serialisierung ändern Allgemeine Java-Themen 2
Q Serialisierung / Speicherung Geschwindingkeit & Aktuelle Position Allgemeine Java-Themen 7
Z Serialisierung und Deserialisierung einer HashMap Allgemeine Java-Themen 17
W Serialisierung Allgemeine Java-Themen 6
K Serialisierung von Hashmap in Vector Allgemeine Java-Themen 3
F Serialisierung und Obfuscation? Allgemeine Java-Themen 7
G (De)serialisierung und Referenzen Allgemeine Java-Themen 5
T Serialisierung: Wie macht RMI das so schnell? Allgemeine Java-Themen 14
J Serialisierung: readInt + writeInt Allgemeine Java-Themen 4
X Einige Fragen zu Serialisierung Allgemeine Java-Themen 2
J bean + serialisierung + serialVersionUID Allgemeine Java-Themen 3
K Serialisierung Allgemeine Java-Themen 6
thE_29 Wie funktioniert Serialisierung? Allgemeine Java-Themen 10
S Problem mit Serialisierung Allgemeine Java-Themen 2
C Serialisierung von JComboBox Allgemeine Java-Themen 4

Ähnliche Java Themen

Neue Themen


Oben