2009-07-02 8 views
0

Ich habe ein kleines Spiel, das ein Freund und ich in Java schreiben. Es ist schlecht codiert und wir arbeiten daran, es zu refactoring, aber das ist jetzt nicht wirklich das Problem. Wir beide haben 64-Bit-Maschinen und ich denke, bevor wir beide 32-Bit-JDKs verwendet haben, aber kürzlich hatte ich einige Probleme und so entfernte ich alle JDKs und installierte die neueste 64-Bit-JDK, und ich bin mir nicht sicher, wann aber mein Freund auch ist Jetzt läuft ein 64-Bit-JDK. Unser Spiel lief im 32-Bit-JDK gut, aber mit der 64-Bit-Version wird das Spiel nicht starten. Ich habe versucht, es mit Eclipse zu debuggen, aber es war ein bisschen Schmerz.Alle Fehler oder Inkompatibilitäten in 64-Bit-JVM?

Unser Spiel ist vernetzt und Multithread, und ich denke, wir haben einige Probleme mit, wie wir die Dinge synchronisiert haben (Ich habe die ganze Idee der Synchronisation nicht verstanden, als ich es vorher schrieb). Wir hatten unsere run() Methoden synchronisiert, was keinen Effekt hat, aber trotz der Dummheiten großer Teile unseres Codes läuft das Zeug immer noch auf einer 32 Bit JVM (Windows und Linux).

Das Spiel startet, wenn eine Person ein Spiel hostet, und dann können andere beitreten, bis der Host das Spiel beginnt. Es sendet dann eine Aufforderung an alle Spieler und fragt, ob sie anfangen wollen, und wenn alle Ja sagen, beginnt das Spiel. Was auf der 64-Bit-JVM passiert, ist, dass es die Nachricht sendet, aber es scheint, dass die Antwort verloren geht oder etwas, oder der Server zählt nicht korrekt, dass jeder OK hat, weil das Spiel nicht startet. Tatsächlich erhält der Host ein paar weitere Nachrichten, die der/die andere (n) Spieler nicht bekommt und sich beim Starten des Spiels etwas weiter bewegt, aber der Server scheint irgendwo stecken zu bleiben.

Irgendwelche Ideen, was könnte das Problem sein? Unser Code ist auf github, wenn jemand einen Blick darauf werfen möchte. Ich wäre sehr glücklich, wenn Sie das täten, aber ich erwarte nicht, dass jemand unseren hässlichen Code durchwühlt. Vielen Dank!

Übrigens laufen wir beide auf 64-Bit Windows Vista und JDK 1.6 u12 und u14, aber wir betreiben auch Linux, obwohl ich es noch nicht auf einer 64-Bit Linux JVM testen konnte. Oh, mehr Details darüber, warum ich ziemlich sicher bin, ist es eine 64-Bit-JVM isssue:

So arbeiteten wir auf diese im Grunde im Herbst Semester, und hörten auf für eine Weile daran zu arbeiten. Nach 6 Monaten nehmen wir es wieder auf, taumeln bei unserem schrecklichen Code und versuchen es zu säubern. Dann erkennen wir, dass keiner von uns es richtig ausführen kann. Ich versuche, eine Revision zu finden, die funktioniert, aber ich komme zur letzten Überarbeitung, bevor wir diesen Sommer angefangen haben, daran zu arbeiten, und es funktioniert immer noch nicht. Ich habe dann sogar einige Binärdateien (.jars) überprüft, die ich zuvor kompiliert hatte, und selbst die früheste Version, die ich habe, funktioniert nicht auf der 64-Bit-JVM. Ich habe dann eine 32-Bit-Linux-VM mit der Sun JDK1.6-JVM eingecheckt, und es hat gut funktioniert. Daher bin ich mir ziemlich sicher, dass es ein 64-Bit-Problem ist, da zuvor die gleichen Binärdateien einwandfrei funktionierten.

Ich habe auch bemerkt, dass Vista aus irgendeinem Grund IPv6-Adressen zu meinen Sockets zugewiesen, wenn Sie eine Verbindung zu einem Server auf meinem eigenen Rechner (0: 0: 0: 0: 0 statt 127.0.0.1) aber Ich habe alles repariert, was IPv4-spezifisch war, und es funktioniert immer noch nicht.

Ich habe gerade ein anderes Problem auf meinem Github-Repository erstellt, was eine ganze andere Geschichte von Weh ist, so dass ich meinen neuesten Build auf einer anderen Maschine nicht gerade testen kann. Aber der letzte Build vor dem Refactoring funktioniert gut auf einer 32-Bit-JVM mit einem Dual-Core, so dass es nicht wie eine Race-Condition aussieht.

Oh, eine andere Sache, genau dasselbe Problem läuft unter OpenJDK 6 64 Bit unter Linux. Ich schätze, es ist eine Race Condition, die die 64-Bit-Version irgendwie hervorbringt.

+0

Warum glauben Sie, dass Sie die 64-Bit-JVM überhaupt verwenden müssen? Der einzige Vorteil, der mir bekannt ist, ist eine größere zulässige Heap-Größe, und das ist nur relevant für große Eisen-Server. – skaffman

+0

Kein Grund, ich habe es gerade zufällig installiert. Der Hauptpunkt ist, dass ich wissen möchte, ob die Probleme, die ich habe, wegen der 64-Bit-JVM oder eines zugrunde liegenden Problems in meinem eigenen Code sind. Ich lehne mich jetzt dem letzteren zu. – Ibrahim

Antwort

1

Wir fanden heraus, was das Problem war. Es gab eine Schleife in einem Teil, wo ein Thread auf etwas wartete, um fertig zu werden, an dem ein anderer Thread arbeitete, außer dass es nur eine while (! Ready) {} Schleife war. Es scheint so, als würden in den 64-Bit-JVM-Threads keine Preempted-Threads auftreten, weil in der 32-Bit-JVM diese Schleife vorweggenommen würde und der andere Thread dann die Variable auf True und nicht in der 64-Bit-JVM setzen würde. Ich verstehe jetzt, dass wir wait/notify und locks verwendet haben sollten, um dies zu tun, aber zumindest zeitweilig einen sleep() hineinwerfen, der dort behoben wurde. Nicht gerade eine Race Condition, eher eine Eigenart des Threading-Modells, also akzeptiere ich keine der anderen Antworten, da sie die Frage, die ich gestellt habe, nicht beantwortet haben.

+2

Nein, Threads sind immer vorbelegt. Wahrscheinlicher ist, dass Ihr "ready" -Feld nicht flüchtig war, was bedeutet, dass die JVM den Wert zwischenspeichern kann, und da Sie sie nie im lokalen Thread ändern, sieht sie die Änderung nicht (oder sie wird sie an einem zufälligen Punkt sehen). Warten Sie also nicht auf einen Wert wie diesen! –

+0

Oh, ok. Das macht mehr Sinn. So oder so, die while-Schleife geht aus, da ich den gesamten Threading-Code repariere. Der Großteil des Synchronisationsmaterials ist entsetzlich falsch, weil ich damals kaum verstand, was synchronisiert war und in einigen Fällen falsch verstanden wurde. Warten/Benachrichtigen ist wahrscheinlich das, was ich hier machen möchte. – Ibrahim

0

Laufen Sie mit dem Java-Prozess mit der Option -d64? Wenn nicht, dann bin ich mir ziemlich sicher, dass Sie die JVM immer noch im 32-Bit-Modus ausführen, und Ihr Problem könnte mit der Umgebung oder dem Betriebssystem zusammenhängen, anstatt mit der Bissigkeit.

+0

Ich bin nicht, aber ich hatte den Eindruck, dass es standardmäßig im 64-Bit-Modus laufen würde. Tatsache ist, dass das Programm in der 32-Bit-JVM einwandfrei läuft, also ist etwas anderes nicht in Ordnung.Ich muss auch einige Details zu meinem ursprünglichen Beitrag hinzufügen, die es überzeugender machen, dass dies ein 64-Bit-Problem ist, aber es sollte wirklich nicht sein. – Ibrahim

+0

Es ist ziemlich schwer zu erkennen, ob Sie eine 32-Bit-64-Bit-JVM verwenden. Sie machen sogar gleich viel. Es ist wahrscheinlicher, dass es eine Race Condition gibt, die auf einer JVM auftaucht, aber nicht auf der anderen. –

1

Das Spiel beginnt, wo eine Person ein Spiel veranstaltet, und dann können andere beitreten, bis der Host die Spiel zu starten entscheidet. Es sendet dann eine Aufforderung an alle die Spieler, fragen, ob sie starten möchten, und wenn alle sagen ja das Spiel startet. Was passiert auf der 64-Bit-JVM ist, dass er die Nachricht sendet, aber es scheint wie die Antwort verloren gehen oder etwas, oder die Server Zählen sind nicht richtig, dass jeder hat OKed, weil das Spiel doesn‘ Ich fange tatsächlich an. Eigentlich bekommt der Host ein paar weitere Nachrichten, die die anderen Spieler nicht bekommen und bekommt eine wenig weiter in das Spiel zu starten, aber der Server scheint irgendwo stecken zu bleiben .

Das klingt wie eine Race Condition, d. H. Fehlerhafte oder fehlende Synchronisation. Da die Rennbedingungen zeitabhängig sind, kann fast alles (einschließlich der Wechsel von JVMs) dazu führen, dass sie sich manifestieren.

Ich würde aufhören, mir Sorgen über 64bit vs 32bit und versuchen, das eigentliche Problem zu diagnostizieren. Da es sich um mehrere Maschinen handelt, wird es leider sehr schwierig (was im Allgemeinen bei Rennbedingungen der Fall ist).

Der beste Weg, dies zu tun, ist wahrscheinlich, dass alle Maschinen synchronisierte Uhren mit NTP, und dann protokollieren das Senden, Empfangen und Verarbeiten von Nachrichten mit Millisekunden-Zeitstempel, so dass Sie sehen können, wo Nachrichten verloren gehen oder nicht verarbeitet werden richtig.

+0

Hmm, ich dachte, es könnte eine Race-Bedingung sein, aber ich habe nicht bemerkt, dass eine andere JVM verschiedene Timing-Eigenschaften haben könnte, die Probleme verursachen würden. Ich bin mir fast sicher, dass ich eine falsche Synchronisierung habe, also muss ich wohl einen ordentlichen Code überarbeiten. Ich habe versucht, ein zugrunde liegendes Problem zu finden, wie ich bereits erwähnt habe, aber das Debuggen von Multithread-Anwendungen in Eclipse ist eine Art von Schmerzen, und es läuft gut in einer 32-Bit-JVM. Das ist der einzige Grund, warum ich nach Problemen in der 64-Bit-JVM gefragt habe. – Ibrahim

+0

Könnte es auch sein, dass Ihre 32-Bit-Maschine Single-Core war und Ihre 64-Bit-Maschine Multi-Core war? Mehrere Kerne erhöhen tendenziell die Wahrscheinlichkeit, dass sich darunterliegende Threading-Probleme manifestieren. Ich stimme jedoch zu, dass Bissigkeit wahrscheinlich nicht das grundlegende Problem ist. – Nathan

0

Ich würde 64 vs. 32 nicht erwarten, dass alle Probleme in diesem Fall, um zu bewirken, Einfädeln ist viel wahrscheinlicher, Ihre Ursache

ein dickes Lob für die Verwendung von Raw Sockets sein, aber sie sind sehr schwierig korrekt zu erhalten. Erwägen Sie, eine Bibliothek für Ihren Netzwerkstack zu verwenden, z. B. Apache Mina, es sei denn, das Ziel des Projekts besteht natürlich darin, Ihren eigenen Socket-Code zu schreiben. Lesen Sie unbedingt die quick start guide. Es ist textbasiertes Protokoll, das sich direkt auf das bezieht, was Sie verwenden.

Randbemerkung: auf jede Methode synchronisiert kleben und mit Finalisierung sind Symptome von schlechten Dinge/code Gerüche

+0

Ja, da ist definitiv eine Menge schlechter Code drin. Ich bin mir nicht sicher, was an rohen Sockets so heikel ist. Auf jeden Fall ist das nicht das Problem hier. Ich bin mir ziemlich sicher, dass es sich um eine Race Condition handelt, aber es wird eine Weile dauern, um es zu bestätigen. Ich denke, in der Zwischenzeit werde ich einfach zu der 32-Bit-JVM zurückkehren, da sie dort funktioniert. – Ibrahim

+0

rohe Steckdosen sind in Ordnung, aber sie sind in der Regel mit Gewinden kombiniert, die leicht zu Rennen Bedingungen können. Mein Vorschlag, MINA zu verwenden, lässt Sie den Netzwerk-Stack überspringen und sich darauf konzentrieren, ein unterhaltsames Spiel zu schreiben! – basszero

Verwandte Themen