2015-07-01 3 views
0

Я пытался выяснить, как бороться с утечками памяти в приложении JavaFX, над которым я работаю. Я использовал следующий код, используя FX8, чтобы проверить поведение памяти:JavaFX - сбор мусора не удается очистить объекты

import javafx.application.Application; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.input.KeyEvent; 
import javafx.scene.input.KeyCode; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Rectangle; 
import javafx.stage.Stage; 

public class Main extends Application { 

    public int count = 0; 

    @Override 
    public void start(Stage stage) { 
     Group root = new Group(); 
     Scene scene = new Scene(root, 500, 500, Color.BLACK); 

     Rectangle r = new Rectangle(25,25,250,250); 
     r.setFill(Color.BLUE); 
     root.getChildren().add(r); 

     scene.addEventHandler(KeyEvent.KEY_RELEASED, event -> { 
      if (event.getCode() == KeyCode.SPACE) { 
       event.consume(); 
       count++; 
       Rectangle r2 = new Rectangle(25, 25, 250, 250); 
       r2.setFill(Color.BLUE); 
       root.getChildren().clear(); 
       root.getChildren().add(r2); 
      } 
     }); 

     stage.setTitle("JavaFX Scene Graph Demo"); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

Когда ПРОСТРАНСТВО нажата, root «s дети очищаются и новый прямоугольник крепится к root.

Проблема с этим кодом заключается в том, что при повторном нажатии на кнопку SPACE объем памяти, используемой приложением Java, увеличивается. Даже когда приложение остается бездействующим в течение некоторого времени после этого, объем памяти, используемой приложением, не уменьшается.

Мое впечатление, что объекты Rectangle должны были быть собраны мусором, и при этом объем памяти не уменьшается. Это проблема с JavaFX, или есть что-то о сборке мусора Java, о котором я не знаю?


EDIT: Использование System.gc() и YourKit

Этот @ ответ AlmasB, я добавил System.gc() вызов функции обратного вызова, таким образом, что всякий раз, когда ПРОСТРАНСТВО нажата, GC, предлагается выполнить мусор коллекция.

YourKit показывает, что мусорные сборники действительно ведутся, а на самом деле, количество Heap & используется Non-динамической памяти, как показано YourKit, стабилизируется через некоторое время, даже когда ПРОСТРАНСТВА повторно нажата.

TLDR: даже когда GC выполняет свою работу, а информация о сохранении памяти в ItKit сохраняется, расход памяти приложения продолжает расти постепенно, как сообщает Activity Monitor. Это проблема с Activity Monitor?

ответ

1

Сбор мусора в Java не предназначен для очистки после того, как каждый объект выходит из сферы действия без сильных ссылок. Когда ваш объект Rectangle больше не доступен, т. Е. Когда вы очищаете дочерние элементы корня, объект просто помечен для сбора мусора, но все еще остается в памяти. Вы можете прочитать об этом более here и более общей информации here. Так что технически говоря, в зависимости от вашей среды JVM, GC может даже не работать в течение всего срока службы вашего приложения, потому что для размещения новых объектов достаточно памяти.

Если вы все еще думаете, что есть утечка памяти, я предлагаю вам использовать подходящий инструмент для профилирования, например VisualVM, с VisualGC, прежде чем беспокоиться о том, что в JavaFX или GC может быть ошибка.

+0

Итак, если GC _is_ запускается, то память, используемая приложением, должна уменьшаться, и это должно быть отражено в диспетчере задач/мониторе активности, да? – peco

+1

Когда GC запускается, это означает, что JVM получает больше свободной памяти из своей общей памяти, а не ОС. Это будет отражено только в том случае, если сам JVM возвращает память ОС, что случается редко. Распределение собственной памяти от ОС до JVM считается дорогостоящей операцией. Следовательно, как правило, JVM будет хранить память до себя, пока ОС не понадобится память. В любом случае это имело место – AlmasB

Смежные вопросы