我有一个Java程序,必须做以下三件事:
这大约有一百万个不同的网站。 这本来是一个相当简单的任务,因为我简单地粘贴了其他程序的一部分: testA和testB都已经单独执行了几百万个不同的页面,并且下载页面的例程也被执行了一百万或者多次浏览页面,也从来没有任何问题。 他们都在Ubuntu 10.4机器上执行。
但是,当一个接一个地执行这三个文件时,无论是哪个磁盘文件被写入崩溃。 我第一次在外置USB HD上运行它时,我必须手动断开并重新连接才能恢复运行(否则Linux将无法识别)。 下一次,在内部HD上,整个系统停机了,我不得不手动重新启动它。 写入Ram磁盘时也是如此。
问题是我不能真正隔离问题。 发生崩溃需要太长的时间(大约50小时左右,但是非常随机),所以testing需要很长时间,并且没有系统的失败日志表明它发生了什么。 机器或高清只是停止响应。
除了崩溃,一切工作正常。 文件正常创build和删除,线程不会死亡,并正确执行,两个testing工作正常。 更改内存或线程数对locking时间没有影响。 我已经检查了套接字或类似的东西没有closures,但我甚至不知道如何开始testing,我不知道如何崩溃一个系统如此灾难性的Java将成为可能。
编辑:通过挂断我的意思是,当我在外部的高清上运行它的高清将不会被Linux认可,当我在内部高清或Ram磁盘运行它的计算机将不会响应任何I / O不pipe什么都不写入磁盘,cactii日志不被logging等。例如,不能使用SSH连接。
程序运行的一个例子:
List<String> pagesToDownload = getFromDataBase(); for(i=0;i<NumThreads;i++){ launchTestThread(); }
然后,在每个线程上:
String pageName = getNextPageToDownload(); File downloadedFile = downloadPage(pageName); TestAResults testAResults = runTestA(downloadedFile); TestBResults testBResults = runTestB(downloadedFile); writeToDatabase(downloadedFile, testAResults, testBResults); downloadedFile.delete();
单独的函数runTestA , runTestB和downloadedPage可以处理更大量的文件,但是如果这样调用的话,它们不会。 而在相同的硬件上。
编辑2:我想我排除了硬件的问题。 就像硬件密集型软件一样,在过去的7天里,在同一台机器上运行,没有任何问题。 无论如何,一旦我可以得到一个未使用的机器,我会testing它的程序。
此外,testing中的所有内容都正在写入数据库,直至发生崩溃,数据正确。 在writeToDatabase方法中, downloadedFile不作为parameter passing,只是名称和大小。
最后,我做了一些内存或文件处理程序泄漏的广泛检查,没有发现任何内容,包括在工作testing中。 现在,我的钱是在文件删除一些奇怪的错误。
编辑3:我终于设法让另一台机器在哪里testing例程。 另一个硬件,但相同的Ubuntu版本(10.4 LTS)。 它也在那里崩溃,所以我真的怀疑这是一个硬件问题。 这留下了一个操作系统错误,一个JVM错误或一个编程错误(没有JNI或类似的东西在运行)。 我会尝试在其他一些环境下运行testing(在FreeBSD中设置一个testing会很容易,我可以尝试找一个Windows机器来testing)来validation。
编辑4:回答鲍勃·克罗斯关于这些文件有多大的问题,他们是典型的网页,平均约20kb。 我想删除它们,因为这个想法是扩大应用程序,使磁盘使用无法忍受。 但我会尽快尝试删除免费运行。 我正在运行那些testing的机器正在被使用,而且我正在很难得到一些闲置的硬件。
如果系统停止响应,则是操作系统中的一个错误,或者是硬件问题。 一个程序不应该能够挂起一个系统,不pipe有多怪。
在不同的系统上运行你的程序,看看它是否为你的程序提供了一个有用的诊断,而不是仅仅依靠。
上面的总结很难看清楚你在做什么,但是我要根据这一段来猜测:
但是,当一个接一个地执行这三个文件时,无论文件被写入哪个磁盘都会崩溃。 我第一次在外置USB HD上运行它时,我必须手动断开并重新连接才能恢复运行(否则Linux将无法识别)。 下一次,在内部HD上,整个系统停机了,我不得不手动重新启动它。 写入Ram磁盘时也是如此。
你如何pipe理你的结果文件相对于你正在检查的百万站点列表的列表? 具体来说,你的代码是这样的(抽象的伪代码如下):
如果是这样的话,我怀疑你有一个问题,就是你正在慢慢积累没有写到结果文件中的结果。 我怀疑他们正坐在几个caching中的一个caching中,等待将这些更改刷新到磁盘。
如果以上是你正在做的,试试这个:
这应该确保在每次testing之后,您都会将结果写入文件。 至less,你应该能够观察你的程序的过程。
编辑 :跟随编辑问题:
writeToDatabase(downloadedFile, testAResults, testBResults);
两个问题:
是否有更改写入您的数据库? 如在,他们写了一段时间,然后停止? 或者是数据库完全空?
这真的是如何编写的代码? 如果是这样,你就有可能的内存泄漏:文件引用被传递到你的writeToDatabase方法。 你确定没有任何东西挂在那个参考上?
由于泄露的文件引用和/或本地文件句柄,可能导致文件句柄太多。 这值得检查。
根据更多反馈再次编辑 :
现在,我的钱是在文件删除一些奇怪的错误。
这是一种可能性。 有些事情要考虑:
你下载的文件有多大? 你可以尝试没有删除的debugging运行? 如果你没有这个代码运行更长时间,那肯定会是一个有趣的结果。
我仍然担心你正在泄漏文件句柄。 如果你检查处理文件的数量,并find一些可处理的文件数量为1024的倍数,我会更仔细地看看删除方法中的任何东西。 当然,如果没有实施,有点难以分辨。
没有任何进一步的信息,我猜你已经填满了你的磁盘。 无法通过SSH连接是有点奇怪,但如果你不能写auth.log 。
没有具体的信息很难说。
写入文件后,IOstream是否完全closures? 你有没有设置在UNIX上的IO限制? 是否有一些并发问题,因为他们同时修改文件? 也许你也可以稍微做一些Thread.sleep(…)来避免饱和磁盘。
但事实上,我不知道这些只是我的两分钱。