我有一个小朋友和我用Java编写的小游戏。它有点编码,我们正在努力重构它,但现在这不是真正的问题。我们都有64位机器,我猜之前我们都使用32位JDK,但最近我遇到了一些问题,所以我删除了所有JDK并安装了最新的64位JDK,我不知道什么时候,但我的朋友也是现在运行64位JDK。我们的游戏在32位JDK中运行良好,但是64位版本游戏无法启动。我一直试图用eclipse调试它,但这有点痛苦。
我们的游戏是网络化和多线程的,我认为我们在如何同步事物方面存在一些问题(我之前没有完全理解同步的整体思路),例如。我们已经使我们的run()方法同步,但没有任何效果,但尽管我们代码的大部分内容都很愚蠢,但仍然可以在32位JVM(Windows和Linux)上运行。
游戏启动时,一个人主持游戏,然后其他人可以加入,直到主持人决定开始游戏。然后它向所有玩家发送提示,询问他们是否想要开始,如果所有人都说是,则游戏开始。在64位JVM上发生的是它发送消息,但似乎响应正在丢失或某些东西,或者服务器没有正确计数每个人都已经确定,因为游戏实际上没有启动。实际上,主机会收到一些其他玩家无法获得的消息,并且在启动游戏时会更进一步,但服务器似乎卡在了某处。
任何想法可能是什么问题?如果有人想看一下,我们的代码就在github。如果你这样做,我会非常高兴,但我不希望任何人趟过我们丑陋的代码。谢谢!
顺便说一下,我们都运行在64位Windows Vista和JDK 1.6 u12和u14上,但我们也运行Linux,尽管我还没能在64位Linux JVM上测试它。 哦,关于为什么我很确定它是64位JVM的更多细节问题:
所以我们基本上在秋季学期开始研究这个问题,并停止了一段时间的工作。 6个月后,我们再次拿起它,错开我们可怕的代码,并开始尝试清理它。然后我们意识到我们都不能正常运行它。我试图找到一个有效的修订版本,但是在我们今年夏天开始编写它之前,我已经达到了最后一个修订版,它仍然没有用。然后我甚至检查了之前编译过的一些二进制文件(.jars),甚至我最早的修订版也没有在64位JVM上运行。然后我检查了运行Sun JDK1.6 JVM的32位Linux VM,它工作正常。因此,我很确定这是一个64位问题,因为在相同的二进制文件完美运行之前。
我还注意到Vista在连接到我自己机器上的服务器时(0:0:0:0:0:1而不是127.0.0.1),由于某种原因将Vista地址分配给我的套接字但是我修复了IPv4特定的任何内容,但它仍无效。
我实际上刚刚在我的github存储库中创建了另一个问题,这是另一个祸患的故事,所以我现在无法在另一台机器上测试我的最新版本。但重构之前的最后一次构建在具有双核的32位JVM上运行良好,因此它看起来不像竞争条件。
哦,另一件事,在Linux下在OpenJDK 6 64位下运行完全相同的问题。我猜这是64位版本以某种方式带来的竞争条件。
答案 0 :(得分:1)
游戏从一个人开始 主持游戏,然后其他人可以加入 直到主持人决定开始 游戏。然后它向所有人发送提示 球员们,问他们是否愿意 开始,如果所有人都说是游戏 开始。 64上发生了什么 位JVM是它发送消息, 但似乎回应是 迷路或什么的,或者 服务器没有正确计数 每个人都因为比赛而搞定了 实际上并没有开始。实际上, 主持人获得了更多的消息 其他玩家不会得到并得到一个 开始游戏的距离越远, 但服务器似乎陷入困境 某处。
这听起来像是一种竞争条件,即有缺陷或缺少同步。由于竞争条件与时间有关,因此几乎任何事情(包括切换JVM)都可能导致它们出现。
我不再担心64位对32位而是试图诊断实际问题。由于它涉及多台机器,不幸的是它会非常困难(通常情况下就是竞争条件)。
执行此操作的最佳方法可能是确保所有计算机都使用NTP同步时钟,然后记录具有毫秒时间戳的消息的发送,接收和处理,以便您可以查看消息丢失或未正确处理的位置
答案 1 :(得分:1)
我们发现了问题所在。在一个部分中有一个循环,其中一个线程等待某个东西准备好另一个线程正在处理,除了它只是一段时间(!ready){}循环。似乎在64位JVM线程中没有被抢占或其他东西,因为在32位JVM中,此循环将被抢占,然后另一个线程将完成并将变量设置为true,但不会在64位JVM中。我现在明白我们应该使用wait / notify和lock来做到这一点,但至少暂时抛出一个sleep()来修复它。这不是一个竞争条件,更像是一个线程模型的怪癖,所以我不接受任何其他答案,因为他们没有回答我问的问题。
答案 2 :(得分:0)
您是否使用-d64选项运行java进程?如果没有,那么我很确定你仍然在32位模式下运行JVM,你的问题可能与环境或操作系统有关,而不是与位数相关。
答案 3 :(得分:0)
我不希望64和32在这种情况下导致任何问题,线程更可能是你的原因
使用原始套接字的荣誉,但是要弄清楚它们非常棘手。考虑为您的网络堆栈使用库,例如Apache Mina,除非项目的目标是编写您自己的套接字代码。绝对阅读quick start guide。它是基于文本的协议直接映射到您正在使用的。
旁注:在每个方法上保持同步并使用finalize是坏事/代码味道的症状