我编写了一个小型爬虫,发现它耗尽了堆空间(尽管我当前将列表中的 URL 数量限制为 300 个)。
通过 Java Memory Analytics,我发现消费者是 char[]
(64MB 中的 45MB,或者如果我增加允许的大小,还会更多;它只是不断增长)。
分析器还为我提供了 char[]
的内容。它包含爬虫读取的 HTML 页面。
对 -Xmx[...]m
的不同设置进行更深入的分析我发现 Java 使用了几乎所有可用空间,然后得到 out of heap
当我想下载 3MB 大小的图像时。
当我给 Java 16MB 时,它使用 14MB 并失败,当我给 Java 64MB 时,它使用 59MB 并在尝试下载大图像时失败。
阅读页面是用这段代码完成的(编辑并添加.close()
):
private String readPage(Website url) throws CrawlerException {
StringBuffer sourceCodeBuffer = new StringBuffer();
try {
URLConnection con = url.getUrl().openConnection();
con.setConnectTimeout(2000);
con.setReadTimeout(2000);
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String strTemp = "";
try {
while(null != (strTemp = br.readLine())) {
sourceCodeBuffer = sourceCodeBuffer.append(strTemp);
}
} finally {
br.close();
}
} catch (IOException e) {
throw new CrawlerException();
}
return sourceCodeBuffer.toString();
}
另一个函数在 while 循环中使用返回的字符串,但据我所知,一旦该字符串被下一页覆盖,该空间就应该被释放。
public void run() {
boolean stop = false;
while (stop == false) {
try {
Website nextPage = getNextPage();
String source = visitAndReadPage(nextPage);
List<Website> links = new LinkExtractor(nextPage).extract(source);
List<Website> images = new ImageExtractor(nextPage).extract(source);
// do something with links and images, source is not used anymore
} catch (CrawlerException e) {
logger.warning("could not crawl a url");
}
}
}
下面是分析器给我的输出示例。当我想查看这些char[]
在哪里时仍然需要,但分析器无法判断。所以我想它们不再需要了,应该被垃圾收集。由于它总是略低于最大空间,Java 似乎也进行垃圾收集,但仅限于目前保持程序运行所需的垃圾收集(没有考虑可能会有大量输入) )。
另外,明确调用System.gc()
每 5 秒甚至设置后 source = null;
没有工作。
网站代码似乎只是以任何方式尽可能长地存储。
我在使用什么东西吗similar to ObjectOutputStream
这强制永久保留读取的字符串?或者Java怎么可能保留这些网站Strings
在 char[]
数组这么长?
Class Name | Shallow Heap | Retained Heap | Percentage
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
char[60750] @ 0xb02c3ee0 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>Wallpaper Kostenlos - 77.777 E-Wallpapers: Widescreen, 3D, Handy, Sexy Frauen</title><link rel="shortcut icon" href="http://img.e-wallp...| 121.512 | 121.512 | 1,06%
char[60716] @ 0xb017c9b8 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>Wallpaper Kostenlos - 77.777 E-Wallpapers: Widescreen, 3D, Handy, Sexy Frauen</title><link rel="shortcut icon" href="http://img.e-wallp...| 121.448 | 121.448 | 1,06%
char[60686] @ 0xb01f3c88 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>Wallpaper Kostenlos - 77.777 E-Wallpapers: Widescreen, 3D, Handy, Sexy Frauen</title><link rel="shortcut icon" href="http://img.e-wallp...| 121.384 | 121.384 | 1,06%
char[60670] @ 0xb015ec48 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>Wallpaper Kostenlos - 77.777 E-Wallpapers: Widescreen, 3D, Handy, Sexy Frauen</title><link rel="shortcut icon" href="http://img.e-wallp...| 121.352 | 121.352 | 1,06%
char[60655] @ 0xb01d5d08 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>Wallpaper Kostenlos - 77.777 E-Wallpapers: Widescreen, 3D, Handy, Sexy Frauen</title><link rel="shortcut icon" href="http://img.e-wallp...| 121.328 | 121.328 | 1,06%
char[60651] @ 0xb009d9c0 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>Wallpaper Kostenlos - 77.777 E-Wallpapers: Widescreen, 3D, Handy, Sexy Frauen</title><link rel="shortcut icon" href="http://img.e-wallp...| 121.320 | 121.320 | 1,06%
char[60637] @ 0xb022f418 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><title>Wallpaper Kostenlos - 77.777 E-Wallpapers: Widescreen, 3D, Handy, Sexy Frauen</title><link rel="shortcut icon" href="http://img.e-wallp...| 121.288 | 121.288 | 1,06%
编辑
在使用更多内存进行测试后,我发现 dominator tree
中出现了这样的 URL。
Class Name | Shallow Heap | Retained Heap | Percentage
crawling.Website @ 0xa8d28cb0 | 16 | 759.776 | 0,15%
|- java.net.URL @ 0xa8d289c0 https://www.google.com/recaptcha/api/image?c=03AHJ_VuuT4CmbxjAoKzWEKOqLaTCyhT-89l3WOeVjekKWW81tdZsnCvpIrQ52aLTw92rP-EUP9ThnzwBwHcRLXG6A0Bpwu11cGttRAUtarmWXhdcTVRoUMLNnJNZeuuA7LedgfTou76nl8ULyuIR3tgo7_lQ21tzzBhpaTSqwYHWyuZGfuRK3z9pgmqRqvI7gE4_4lexjYbkpd62kN... | 56 | 759.736 | 0,15%
| |- char[379486] @ 0xa8c6f4f8 <!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9"> <title>Google Accounts</title><style type="text/css"> html, body, div, h1, h2, h3, h4, h5, h6, p, img, dl, dt, dd, ol, ul, li, t... | 758.984 | 758.984 | 0,15%
| |- java.lang.String @ 0xa8d28a40 /recaptcha/api/image?c=03AHJ_VuuT4CmbxjAoKzWEKOqLaTCyhT-89l3WOeVjekKWW81tdZsnCvpIrQ52aLTw92rP-EUP9ThnzwBwHcRLXG6A0Bpwu11cGttRAUtarmWXhdcTVRoUMLNnJNZeuuA7LedgfTou76nl8ULyuIR3tgo7_lQ21tzzBhpaTSqwYHWyuZGfuRK3z9pgmqRqvI7gE4_4lexjYbkpd62kNBZ7UIDccO5bx6TqFpf-7Sl...| 24 | 624 | 0,00%
| | '- char[293] @ 0xa8d28a58 /recaptcha/api/image?c=03AHJ_VuuT4CmbxjAoKzWEKOqLaTCyhT-89l3WOeVjekKWW81tdZsnCvpIrQ52aLTw92rP-EUP9ThnzwBwHcRLXG6A0Bpwu11cGttRAUtarmWXhdcTVRoUMLNnJNZeuuA7LedgfTou76nl8ULyuIR3tgo7_lQ21tzzBhpaTSqwYHWyuZGfuRK3z9pgmqRqvI7gE4_4lexjYbkpd62kNBZ7UIDccO5bx6TqFpf-7Sl... | 600 | 600 | 0,00%
| |- java.lang.String @ 0xa8d289f8 c=03AHJ_VuuT4CmbxjAoKzWEKOqLaTCyhT-89l3WOeVjekKWW81tdZsnCvpIrQ52aLTw92rP-EUP9ThnzwBwHcRLXG6A0Bpwu11cGttRAUtarmWXhdcTVRoUMLNnJNZeuuA7LedgfTou76nl8ULyuIR3tgo7_lQ21tzzBhpaTSqwYHWyuZGfuRK3z9pgmqRqvI7gE4_4lexjYbkpd62kNBZ7UIDccO5bx6TqFpf-7Sl6YmMgFC77kWZR7vvZIPkS...| 24 | 24 | 0,00%
| |- java.lang.String @ 0xa8d28a10 www.google.com | 24 | 24 | 0,00%
| |- java.lang.String @ 0xa8d28a28 /recaptcha/api/image | 24 | 24 | 0,00%
从我的意图来看,我真的很想知道:为什么 java.net.URL
的 HTML 源代码部分是这样的? ?这是来 self 打开的 URLConnection 吗?
最佳答案
我首先会尝试在 readPage
方法末尾关闭阅读器和 URL 连接。最好将此逻辑放在 finally
子句中。
保持打开的连接将使用内存,并且根据内部情况,GC 可能无法回收它,即使您不再在代码中引用它
更新(基于评论):连接本身没有 close()
方法,当连接到它的所有读取器都关闭时,该连接将被关闭。
关于java - 网络爬虫耗尽堆空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11564851/