我正在编写一个Java applet,它从Web服务器下载图像并将其显示给用户。它在Java 1.6.0_3及更高版本中运行良好,但在旧版本上,它将使每20次页面查看完全崩溃一次。 Java控制台中没有错误消息,因为该过程已完全冻结。我有时候会等待将近15分钟,但它永远不会冻结。
我在每行代码后添加了一条调试消息,并确定导致崩溃的行是:InputStream data = urlConn.getInputStream()
。
urlConn是一个URLConnection对象,指向我要加载的图像。我已经尝试了我能想到的各种选项组合,但没有任何帮助。我无法在Java bug数据库或1.6.0_3的发行说明中找到任何内容。
以前有人遇到过这个问题吗?知道怎么解决吗?
答案 0 :(得分:1)
确定它是否真的是整个JVM进程被冻结或其他:
(1)获取java堆栈转储(sigquit / ctrl-break / jstack)
(2)让另一个背景线程做你能观察到的事情;它会停止吗?
(3)检查另一个进程(浏览器/等)是否可以在冻结期间联系服务器? (真正的问题是服务器连接耗尽的可能性)
它是随机每次20次提取(例如,5%的时间,有时是JVM运行中的第一次提取),还是总是在大约20次提取后?如果是后者,听起来好像没有正确关闭。
如果在Linux上你可以使用'netstat -t'或'lsof'(带某些选项或grepped只显示一些行)来查看打开的套接字;如果在每次获取之后,还有一个是打开的,并且计数永远不会下降,你没有正确地关闭它。
如果是这样,在每次尝试后调用HttpUrlConnection上的流返回和/或断开()的close()可能会有所帮助。 (对于applet可以保持打开的连接数量,可能还有更严格的限制,因此您可以比在独立应用程序中更快地进行此操作。)
它在后来的Javas中“起作用”的事实也暗示了最终化/ GC可以更有效/更有效地进行某种自动清理。最好自己干净地关闭一些东西,但你也可以尝试在早期的Javas中强制GC / runFinalization显示问题。
答案 1 :(得分:0)
我不确定您遇到的问题的原因,但我成功使用以下代码从applet中同步加载图像(从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;
}