0

我正在编写一个 Java 小程序,它从 Web 服务器下载图像并将它们显示给用户。它在 Java 1.6.0_3 及更高版本中运行良好,但在旧版本中,它大约每 20 次页面浏览就会使进程完全崩溃一次。Java 控制台中没有错误消息,因为该进程已完全冻结。有时我已经等了将近 15 分钟,但它永远不会解冻。

我在每一行代码之后添加了一条调试消息,并确定导致崩溃的行是:InputStream data = urlConn.getInputStream().

urlConn 是指向我要加载的图像的 URLConnection 对象。我已经尝试了我能想到的所有选项组合,但没有任何帮助。我无法在 Java 错误数据库或 1.6.0_3 的发行说明中找到任何内容。

有没有人遇到过这个问题?知道如何解决吗?

4

2 回答 2

1

要确定它是否真的是冻结的整个 JVM 进程,或者其他什么:

(1) 得到一个java堆栈转储(sigquit/ctrl-break/jstack)

(2) 让另一个后台线程做一些你可以观察到的事情;它停止了吗?

(3)检查其他进程(浏览器/等)是否可以在冻结期间联系服务器?(有可能真正的问题是服务器连接耗尽)

是每 20 次获取随机一次(例如,5% 的时间,有时是 JVM 运行中的第一次获取),还是总是在大约 20 次获取之后?如果是后者,听起来好像有些东西没有正确关闭。

如果在 Linux 上,您可以使用“netstat -t”或“lsof”(带有某些选项或 grepped 以仅显示某些行)来查看打开的套接字;如果每次取回后,又打开了一个,并且计数从未下降,则说明您没有正确关闭事物。

如果是这样,在每次尝试后在返回的流上调用 close() 和/或在 HttpUrlConnection 上调用 disconnect() 可能会有所帮助。(applet 可以打开的连接数量也可能有更严格的限制,因此您比在独立应用程序中更快地达到这一点。)

它在后来的 Java 中“工作”的事实也表明,某种自动清理可能会通过 finalization/GC 更有效/更定期地发生。最好自己彻底关闭,但您也可以尝试在早期的 Java 中强制执行 GC/runFinalization 来显示问题。

于 2009-07-03T02:59:40.540 回答
0

我不确定您所面临问题的原因,但我成功使用以下代码从小程序中同步加载图像(从 jar 文件或服务器加载):

public Image loadImage(String imageName) {

    // get the image
    Image image = getImage(getCodeBase(), imageName);

    // wait for it to fully load
    MediaTracker tracker = new MediaTracker(this);
    tracker.addImage(image, 0);
    boolean interrupted = false;
    try {
        tracker.waitForID(0);
    } catch (InterruptedException e) {
        interrupted = true;
    }

    int status = tracker.statusID(thisImageTrackerID, false);
    if (status != MediaTracker.COMPLETE) {
        throw new RuntimeException("Failed to load " + imageName + ", interrupted:" + interrupted + ", status:" + status);
    }

    return image;
}
于 2009-07-07T13:24:10.447 回答