【发布时间】:2020-05-04 14:02:16
【问题描述】:
我正在将 1000 个 ImageView 列表加载到 TilePane。然后,经过一段时间后,我将删除 TilePane 的所有子代。但是在任务管理器中,我可以看到内存根本没有释放(消耗了 6GB RAM)。
这是代码
package application;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.TilePane;
public class Controller implements Initializable {
@FXML
private TilePane tilePane;
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
File rootPathFile = new File("C:\\Users\\Flower\\3D Objects\\New folder");
File[] fileList = rootPathFile.listFiles();
ObservableList<ImageView> btnList = FXCollections.observableArrayList();
for (File file : fileList) {
Image img = new Image(file.toURI().toString());
ImageView imgView = new ImageView(img);
imgView.setFitWidth(200);
imgView.setFitHeight(300);
btnList.add(imgView);
}
tilePane.getChildren().addAll(btnList);
new Thread(() -> {
try {
Thread.sleep(10000);
System.out.println("\nAfter adding 1000 images:");
System.out.println("Free Memory: " + Runtime.getRuntime().freeMemory());
System.out.println("Totel Memory: " + Runtime.getRuntime().totalMemory());
Thread.sleep(15000);
Platform.runLater(() -> {
try {
tilePane.getChildren().clear();
Thread.sleep(5000); // to ensure memory changes
System.out.println("\nAfter clearing children:");
System.out.println("Free Memory: " + Runtime.getRuntime().freeMemory());
System.out.println("Totel Memory: " + Runtime.getRuntime().totalMemory());
System.gc();
Thread.sleep(10000);
System.out.println("\nAfter GC() and 10 seconds sleep");
System.out.println("Free Memory: " + Runtime.getRuntime().freeMemory());
System.out.println("Totel Memory: " + Runtime.getRuntime().totalMemory());
} catch (InterruptedException e) {
e.printStackTrace();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
输出:
After adding 1000 images:
Free Memory: 1044423528
Totel Memory: 4572839936
After clearing children:
Free Memory: 1035263112
Totel Memory: 4572839936
After GC() and 10 seconds sleep
Free Memory: 1045599688
Totel Memory: 4572839936
这仅用于演示。在我的实际项目中,我在SplitPane 中有ListView 和TilePane。每当我单击ListView 中的项目(文件夹名称)时,我必须通过清除以前的子项将图像(10 到 20 个图像)加载到 TilePane。但它并没有清除内存并不断增加。
【问题讨论】:
-
hmm .. 看起来像一个错误
-
1.任务管理器只是报告分配给 Java 堆的内存量;这并不意味着堆空间都被使用了。 2. 除非确实需要,否则垃圾收集器不会释放堆中的空间。那么,
Runtime.getRuntime().freeMemory()和Runtime.getRuntime().totalMemory()会报告什么,如果调用System.gc ()会发生什么? -
@James_D 我在问题中添加了输出
-
该测试不正确(尽管问题可能仍然存在):您对
System.gc()的调用可能发生在在您调用tilePane.getChildren().clear()之前。清除子列表后,将System.out.println()和System.gc()调用移动到Platform.runLater(),看看是否会改变输出。 -
但是您对
System.gc()的调用仍会(可能)在您调用清除子列表之前发生。Platform.runLater(...)安排代码在 FX 应用程序线程上运行,因此在执行之前可能会有一个小暂停。之后的代码立即发生在该线程中。所以当你调用System.gc()时,图片仍然被UI引用,GC也无能为力。清除图像后,您只需闲逛一会儿,由于仍有大量可用内存,因此不会调用 GC,因此永远不会清理内存。
标签: javafx memory-leaks javafx-8