HtmlUnit似乎不会关闭webclient中的窗口,从而造成内存泄漏。我正在尝试使用HtmlUnit获取一个页面并将其传递给JSoup进行解析。我知道JSoup可以连接到一个页面,但我需要使用这种方法,因为我需要在解析它们之前在某些站点上保持登录会话。
以下是代码:
import java.io.IOException;
import java.net.MalformedURLException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class HtmlUnitLeakTest {
public static void main(String args[]) throws FailingHttpStatusCodeException, MalformedURLException, IOException{
WebClient webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setPrintContentOnFailingStatusCode(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
for(int i = 0; i < 500; i++){
HtmlPage page = webClient.getPage("http://www.stackoverflow.com");
Document doc = Jsoup.parse(page.asXml());
webClient.closeAllWindows();
System.out.println(i);
if((i % 5 == 0)){
System.out.println(i);
}
}
}
}
随着运行,内存不断攀升,在我的调试屏幕中,我可以看到所有窗口仍在webclient下引用而未关闭。
我已经看到这个代码就是关闭这些窗口:
List<WebWindow> windows = webclient.getWebWindows();
for (WebWindow ww : windows) {
ww.getJobManager().removeAllJobs();
ww.getJobManager().shutdown();
}
webclient.closeAllWindows();
但是它没有,我继续有内存泄漏。
有人遇到过这个问题吗?
干杯
版本信息:
HtmlUnit 2.15
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
答案 0 :(得分:1)
我有一段与你的代码非常相似的代码,过去两天我一直在试着解决这个问题。我尝试了他们在网上提到的所有内容,我找不到解决方案 - 我开始搞乱代码,突然间,泄漏停止了。 我正在使用内存分析器工具,我的程序得到了它使用2gb ram(我在jvm参数中设置为java堆)的点,然后它在20分钟后崩溃。现在它已运行1小时,内存使用量稳定在10mb。
我做了什么? 我已将webClient初始化放在for循环中:
public class HtmlUnitLeakTest {
public static void main(String args[]) throws FailingHttpStatusCodeException, MalformedURLException, IOException{
for(int i = 0; i < 500; i++){
try{
WebClient webClient = initializeClient();
HtmlPage page = webClient.getPage("http://www.stackoverflow.com");
Document doc = Jsoup.parse(page.asXml());
webClient.closeAllWindows();
System.out.println(i);
if((i % 5 == 0)){
System.out.println(i);
}
}finally {
webClient.getCurrentWindow().getJobManager().removeAllJobs();
webClient.close();
System.gc();
}
}
}
private static WebClient initilizeCilent(){
final WebClient webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setPrintContentOnFailingStatusCode(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
return webClient;
}
}
我知道这是一种理论上错误的做法,但我迫不及待地想让它发挥作用,现在确实如此! 如果您已经使用更好(正确)的方法解决了问题,那么我也想知道这一点!
答案 1 :(得分:0)
/**
* Returns an immutable list of open web windows (whether they are top level windows or not).
* This is a snapshot; future changes are not reflected by this list.
*
* @return an immutable list of open web windows (whether they are top level windows or not)
* @see #getWebWindowByName(String)
* @see #getTopLevelWindows()
*/
public List<WebWindow> getWebWindows() {
return Collections.unmodifiableList(new ArrayList<>(windows_));
}
答案 2 :(得分:0)
有onunload
onunload
脚本导致JS引擎线程在关闭后再次运行,然后它继续运行。
所以我建议升级到更近期(现在是2.27)。
此外,您可能会在关闭之前通过所有窗口并删除final List<WebWindow> windows = webClient.getWebWindows();
for (final WebWindow window : windows) {
...
}
webClient.closeAllWindows();
处理程序。
Intent intent = new Intent(context,AnotherActivity.class);
context.startActivity(intent);