這幾天遇到了一個問題,不幸開發的一個cs架構的工具,客戶端開啟后,內存一直在緩慢增長最終導致進程卡死,花了4天時間,終於爬出來了。。。
客戶端通過timer定時器每30秒查詢一次數據庫以及一些業務邏輯操作,然后刷新界面的表格數據。
但是每次調用方法后,都會導致內存的增長,然后我將方法內部的變量在使用完之后手動設置為null 而且最后調用了gc 但是都沒有什么效果,
最終還是會導致內存溢出,進程卡死。(估計是釋放的速度,趕不上增長的速度。。。)
之后對定時部分的代碼逐段進行了排查,最后發現是由於 我之前在對tableview進行實時刷新時導致的
代碼如下:
1 if (tableKeywordCompetePrice.getItems().get(tableKeywordCompetePrice.getItems().size() - 1).getKeyword() == null)
2
3 {
4 tableKeywordCompetePrice.getItems().remove(tableKeywordCompetePrice.getItems().size() - 1);
5 }
6 else
7 {
8 tableKeywordCompetePrice.getItems().add(new KeywordCompetePriceInfo());
9 tableKeywordCompetePrice.getItems().get(tableKeywordCompetePrice.getItems().size() - 1).getCheckBox().setVisible(false);
10 }
其中 tableKeywordCompetePrice 就是 一個 tableview 對象。
因為當 list 中元素屬性變化時候, table 不能實時刷新。(因為此時修改事件並不受監聽,list 不認為自己有變化,隨之 table 也就不會刷新),所以我就采用了直接改變list大小來進行刷新。
tableview實時刷新有2種方式:
第一種是我上面采用的方式直接修改list的大小,簡單粗暴。(但是沒想到給自己挖了一個大坑。。。。0.0)
第二種就是 與 JavaFx UI 層進行交互的類屬性,應當定義為對應的 xxxProperty 包裝類 (如 StringProperty , IntegerProperty 等 )。
然后,在對 table cellValueFactory 定義時,就可以直接返回 xxxProperty 對象 (因為 StringProperty 本身就是 ObservableValue 的子類) ,這個麻煩的一點就是要挨個對需要監聽的字段都增加這段代碼。
例如:
1 private final StringProperty device = new SimpleStringProperty();
2
3 public StringProperty deviceProperty() {
4 return device;
5 }
6 // 原有的 set 方法,並不受字段類型變化而改變,仍然返回同樣的類型,只是方法體需要修改一下
7 public void setDevice(String status) {
8 this.device.set(status);
9 }
10
11 // 原有的 get 方法,並不受字段類型變化而改變,仍然返回同樣的類型,只是方法體需要修改一下
12 public String getDevice(){
13 return device.get();
14 }
展示實體類修改成上述代碼后,就可以自動監聽到device列對象屬性的變化,從而進行實時刷新。
修改成這樣后,內存基本很穩定。。。想哭。。。
目前對於為什么修改list大小會導致內存一直增長還是沒想~明~白。
希望還有人用javafx tableview組件的時候能看到我這篇文章,免得也掉進坑中~~~~0.0。

