Tôi có một tình huống đã tra tấn tôi trong nhiều tháng: Tôi tiếp tục nhận ngoại lệ OOM (Heap Space) và kiểm tra đống đống tôi đã tìm thấy hàng triệu đối tượng mà tôi chưa từng phân bổ nhưng có khả năng được cấp phát trong thư viện cơ bản. Sau nhiều máu, mồ hôi và nước mắt tôi đã được quản lý để bản địa hoá mã tạo ra rò rỉ bộ nhớ và tôi đã sáng tác một mẫu mã tối thiểu, đầy đủ và có thể kiểm chứng để minh họa điều này:Rò rỉ bộ nhớ xpath Java?
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.scene.web.WebEngine;
import javafx.stage.Stage;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class MVC extends Application implements ChangeListener<Worker.State>{
private final WebEngine engine = new WebEngine();
private final String url = "https://biblio.ugent.be/publication?sort=publicationstatus.desc&sort=year.desc&limit=250&start=197000";
private final XPath x = XPathFactory.newInstance().newXPath();
@Override
public void start(Stage primaryStage) throws Exception {
System.setProperty("jsse.enableSNIExtension", "false");
engine.getLoadWorker().stateProperty().addListener(this);
engine.load(url);
}
public static void main(String[] args) {
launch(args);
}
private NodeList eval(Node context, String xpath) throws XPathExpressionException{
return (NodeList)x.evaluate(xpath, context, XPathConstants.NODESET);
}
@Override
public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
if (newValue==Worker.State.SUCCEEDED) {
try {
while(true){
NodeList eval = eval(engine.getDocument(), "//span[@class='title']");
int s = eval.getLength();
}
} catch (XPathExpressionException ex) {
Logger.getLogger(MVC.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
mã nào sau đây:
- tải tài liệu bằng cách sử dụng
JavaFX
WebEngine
. - không ngừng thực hiện truy vấn xpath trên tài liệu bằng cách sử dụng gói
javax.xml
, mà không lưu trữ kết quả hoặc con trỏ đến số.
Để chạy, hãy tạo ứng dụng JavaFX, thêm tệp có tên MVC.java vào gói mặc định, nhập mã và nhấn chạy. Bất kỳ công cụ lược tả nào (tôi sử dụng VisualVM) sẽ nhanh chóng cho bạn thấy rằng chỉ trong vài phút, đống phát triển không kiểm soát được. Các đối tượng sau đây dường như được phân bổ nhưng không bao giờ phát hành:
java.util.HashMap$Node
com.sun.webkit.Disposer$WeakDisposerRecord
com.sun.webkit.dom.NamedNodeMapImpl$SelfDisposer
java.util.concurrent.LinkedBlockingQueue$Node
Hành vi này xảy ra mỗi khi tôi chạy mã, không phụ thuộc vào url Tôi tải hoặc xpath tôi thực hiện trên tài liệu.
cài đặt mà tôi thử nghiệm:
- MBP chạy OS X Yosemite (up-to-date)
- JDK 1.8.0_60
thể bất cứ ai tạo lại vấn đề này? Nó là một rò rỉ bộ nhớ thực tế? Tôi có thể làm gì không?
chỉnh sửa
Một đồng nghiệp của tôi sao chép các vấn đề trên một máy w7 với JDK 1.8.0_45, và nó sẽ xảy ra trên một máy chủ Ubuntu là tốt.
chỉnh sửa 2
Tôi đã thử nghiệm jaxen như một thay thế cho gói javax.xml, nhưng kết quả đều giống nhau, dẫn tôi để tin rằng lỗi nằm sâu bên trong webkit nắng
có thể có liên quan: http://stackoverflow.com/questions/6340802/java-xpath-apache-jaxp-implementation-performance – Warkst
tôi có thể tái sản xuất này trên Windows 7 64 bit, Java 1.8.0_60. Nó dường như là một rò rỉ bộ nhớ. Tôi đã thử thực hiện cùng một vòng lặp trên một tệp XML tùy ý mà không cần liên quan đến JavaFX và có cùng kết quả. – VGR
Cảm ơn bạn đã xem xét điều này! Tôi thậm chí đã không xem xét không sử dụng javafx nhưng bạn hoàn toàn đúng, lỗi nằm sâu hơn, và cách các tài liệu w3c được cung cấp là không quan trọng. – Warkst