Как освободить потребляемую память webEngine в браузере javaFX

Я использую этот SimpleSwingBrowser. Он потребляет слишком много памяти и не освобождает эту память. Я постоянно вижу потребляемую память в диспетчере задач, и она увеличивается до 500 МБ при посещении только трех сайтов, и она постоянно увеличивается.

Поэтому я хочу освободить всю память, когда браузер переключится на следующую страницу. Означает, что вся память, потребляемая предыдущей страницей, должна быть удалена или очищена.

    import javafx.application.Platform;
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.embed.swing.JFXPanel;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.web.WebEngine;
    import javafx.scene.web.WebEvent;
    import javafx.scene.web.WebView;

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.net.MalformedURLException;
    import java.net.URL;

    import static javafx.concurrent.Worker.State.FAILED;

    public class SimpleSwingBrowser extends JFrame {

    private final JFXPanel jfxPanel = new JFXPanel();
    private WebEngine engine;

    private final JPanel panel = new JPanel(new BorderLayout());
    private final JLabel lblStatus = new JLabel();


    private final JButton btnGo = new JButton("Go");
    private final JTextField txtURL = new JTextField();
    private final JProgressBar progressBar = new JProgressBar();

    public SimpleSwingBrowser() {
        super();
        initComponents();
    }


    private void initComponents() {
        createScene();

        ActionListener al = new ActionListener() {
            @Override 
            public void actionPerformed(ActionEvent e) {
                loadURL(txtURL.getText());
            }
        };

        btnGo.addActionListener(al);
        txtURL.addActionListener(al);

        progressBar.setPreferredSize(new Dimension(150, 18));
        progressBar.setStringPainted(true);

        JPanel topBar = new JPanel(new BorderLayout(5, 0));
        topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
        topBar.add(txtURL, BorderLayout.CENTER);
        topBar.add(btnGo, BorderLayout.EAST);

        JPanel statusBar = new JPanel(new BorderLayout(5, 0));
        statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
        statusBar.add(lblStatus, BorderLayout.CENTER);
        statusBar.add(progressBar, BorderLayout.EAST);

        panel.add(topBar, BorderLayout.NORTH);
        panel.add(jfxPanel, BorderLayout.CENTER);
        panel.add(statusBar, BorderLayout.SOUTH);

        getContentPane().add(panel);

        setPreferredSize(new Dimension(1024, 600));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();

    }

    private void createScene() {

        Platform.runLater(new Runnable() {
            @Override 
            public void run() {

                WebView view = new WebView();
                engine = view.getEngine();

                engine.titleProperty().addListener(new ChangeListener<String>() {
                    @Override
                    public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override 
                            public void run() {
                                SimpleSwingBrowser.this.setTitle(newValue);
                            }
                        });
                    }
                });

                engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {
                    @Override 
                    public void handle(final WebEvent<String> event) {
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override 
                            public void run() {
                                lblStatus.setText(event.getData());
                            }
                        });
                    }
                });

                engine.locationProperty().addListener(new ChangeListener<String>() {
                    @Override
                    public void changed(ObservableValue<? extends String> ov, String oldValue, final String newValue) {
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override 
                            public void run() {
                                txtURL.setText(newValue);
                            }
                        });
                    }
                });

                engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
                    @Override
                    public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override 
                            public void run() {
                                progressBar.setValue(newValue.intValue());
                            }
                        });
                    }
                });

                engine.getLoadWorker()
                        .exceptionProperty()
                        .addListener(new ChangeListener<Throwable>() {

                            public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
                                if (engine.getLoadWorker().getState() == FAILED) {
                                    SwingUtilities.invokeLater(new Runnable() {
                                        @Override public void run() {
                                            JOptionPane.showMessageDialog(
                                                    panel,
                                                    (value != null) ?
                                                    engine.getLocation() + "\n" + value.getMessage() :
                                                    engine.getLocation() + "\nUnexpected error.",
                                                    "Loading error...",
                                                    JOptionPane.ERROR_MESSAGE);
                                        }
                                    });
                                }
                            }
                        });

                jfxPanel.setScene(new Scene(view));
            }
        });
    }

    public void loadURL(final String url) {
        Platform.runLater(new Runnable() {
            @Override 
            public void run() {
                String tmp = toURL(url);

                if (tmp == null) {
                    tmp = toURL("http://" + url);
                }

                engine.load(tmp);
            }
        });
    }

    private static String toURL(String str) {
        try {
            return new URL(str).toExternalForm();
        } catch (MalformedURLException exception) {
                return null;
        }
    }



    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                SimpleSwingBrowser browser = new SimpleSwingBrowser();
                browser.setVisible(true);
                browser.loadURL("http://oracle.com");
           }     
       });
    }
}

person rajat agarwal    schedule 12.07.2016    source источник


Ответы (1)


Это фактическая «проблема ограничения» с Java. Даже если вы вызываете System.gc (), что не рекомендуется, поскольку нет уверенности, что сборщик мусора освободит память. an-object-null">Один из способов - установить Object на null, чтобы он был помечен как очищенный.

Даже если у вас было много элементов и вы их удалили, вы можете увидеть, что потребление оперативной памяти остается прежним. Иногда Java по умолчанию использует больше памяти, чтобы ваше приложение не тормозило.

Вам нужно подождать Сборщик мусора сделает свою работу и создаст новые объекты со стратегией. Если объект оставался слишком долго("упомяните, что Java8 отличается permgen не существует"), у вас есть вероятность, что он никогда не будет получен из gc. Иногда освобождение 200 MiB памяти.

Некоторые элементы, такие как WebViewer, потребляют много оперативной памяти. Вы можете увидеть то же самое для Firefox, но он очищает его через некоторое время.

person GOXR3PLUS    schedule 12.07.2016
comment
Спасибо за Ваш ответ. - person rajat agarwal; 12.07.2016
comment
@rajat agarwal мне давно это интересно :) - person GOXR3PLUS; 12.07.2016
comment
@GoXrPlus Рад слышать об этом :). Таким образом, есть способ решить эту проблему без использования нулевого объекта. Потому что использование нулевого объекта создает много проблем. Это похоже на загрузку нового веб-движка. - person rajat agarwal; 12.07.2016