JavaFX8-TableView泄漏(TableMenuButton)
我有一个JavaFXTableView,它可以动态更改列属性(宽度、可见性),以实现多个“自定义设置/列预设” 每当我更改列设置时,我注意到大量未收集的内存。试图用普通java代码重现这种情况 并且能够在附加程序的情况下完成: 注意:启动程序后,一切正常!内存按预期收集。当我们单击列标题右侧的TableMenuButton(加号)时,事情似乎变得非常糟糕。它长大了 无休止的记忆错误JavaFX8-TableView泄漏(TableMenuButton),java,javafx,memory-leaks,tableview,Java,Javafx,Memory Leaks,Tableview,我有一个JavaFXTableView,它可以动态更改列属性(宽度、可见性),以实现多个“自定义设置/列预设” 每当我更改列设置时,我注意到大量未收集的内存。试图用普通java代码重现这种情况 并且能够在附加程序的情况下完成: 注意:启动程序后,一切正常!内存按预期收集。当我们单击列标题右侧的TableMenuButton(加号)时,事情似乎变得非常糟糕。它长大了 无休止的记忆错误 公共类TableViewMenuButtonLeak扩展应用程序{ 公共静态void main(字符串[]arg
公共类TableViewMenuButtonLeak扩展应用程序{
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
公众假期开始(阶段){
//**设置表**
最终的TableView表格=新的TableView();
//按下“桌面菜单”按钮时,一切都变得疯狂
table.setTableMenuButtonVisible(true);
//生成一组列
对于(int i=0;i<4;i++){
TableColumn column1=新的TableColumn(“列”+i);
列1.setCellValueFactory(新属性ValueFactory(“列”+i));
table.getColumns().add(column1);
}
//**永远更改表格设置**
可运行r=()->{
while(true){
Platform.runLater(()->{
table.getColumns().stream().forEach((c)->c.setPrefWidth(Math.random()*300));
table.getColumns().stream().forEach((c)->c.setVisible(Math.random()>0.5?true:false));
});
试一试{
睡眠(1);
}捕获(中断异常e){}
}
};
螺纹t=新螺纹(r);
t、 setDaemon(true);
t、 start();
//**表演材料**
stage.setTitle(!!!!点击表格右侧的“TableMenuButton”(加号)!!!);
场景=新场景(表);
舞台布景宽度(600);
舞台设置高度(600);
舞台场景;
stage.show();
}
公共静态类记录{
私人财产专栏1;
私人财产专栏2;
公共记录(字符串列1、字符串列2){
this.column1=新的SimpleStringProperty(column1);
this.column2=新的SimpleStringProperty(column2);
}
公共字符串getColumn1(){
返回column1.get();
}
public StringProperty column1Property(){
返回列1;
}
公共字符串getColumn2(){
返回column2.get();
}
public StringProperty column2Property(){
返回列2;
}
}
}
分析heapdump可以发现有数千个
“StackPane”、“ContextMenuContent$MenuLabel”和“ContextMenuContent$MenuItemContainer”实例
我的问题是:
- 这是已知的bug吗?(至少我没有找到泄漏描述 与此相符,但我当然可能会错过)
- 你有过同样的经历吗
- 有人知道这个问题的解决方法吗
public class TableViewMenuButtonLeak extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
// ** SETUP TABLE **
final TableView<Record> table = new TableView<>();
// things go crazy when the table menu button was pressed
table.setTableMenuButtonVisible(true);
//generate a bunch of columns
for(int i = 0; i < 4; i++) {
TableColumn<Record, String> column1 = new TableColumn<>("column"+i);
column1.setCellValueFactory(new PropertyValueFactory<Record, String>("column"+i));
table.getColumns().add(column1);
}
// ** CHANGE TABLE SETTINGS FOREVER **
Runnable r = () -> {
while(true) {
Platform.runLater(() -> {
table.getColumns().stream().forEach((c) -> c.setPrefWidth(Math.random() * 300));
table.getColumns().stream().forEach((c) -> c.setVisible(Math.random() > 0.5 ? true : false));
});
try {
Thread.sleep(1);
} catch (InterruptedException e) {}
}
};
Thread t = new Thread(r);
t.setDaemon(true);
t.start();
// ** SHOW STUFF **
stage.setTitle("!!!! Do click onto the \"TableMenuButton\" on the right side of the table (PLUS sign) !!!");
Scene scene = new Scene(table);
stage.setWidth(600);
stage.setHeight(600);
stage.setScene(scene);
stage.show();
}
public static class Record {
private final StringProperty column1;
private final StringProperty column2;
public Record(String column1, String column2) {
this.column1 = new SimpleStringProperty(column1);
this.column2 = new SimpleStringProperty(column2);
}
public String getColumn1() {
return column1.get();
}
public StringProperty column1Property() {
return column1;
}
public String getColumn2() {
return column2.get();
}
public StringProperty column2Property() {
return column2;
}
}
}