Hi,
I have a strange problem..
When printing a single character to StyleClassedTextArea every 50ms, memory usage keeps growing
until application is very slow and not responding. In the examples below, I'm using a thread to update the textarea but in my real application the character comes from serial port at the same rate (50ms).
This bug does not happen if using richtextfx-fat-0.8.2.jar, only when using richtextfx-fat-0.9.0.jar and up.
Whats strange about it is that when printing more than just a single character at one time, for example - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" or when printing single character with new-line "a\n" than there is no memory leak and everything seems to be OK.
See the code "Memory leak" for the example where there is a memory leak.
See the commented code "NO Memory leak 1" and "NO Memory leak 2" for examples where there is no memory leak.
Any help/suggestions how to solve this will be highly appreciated :)
THANKS
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ObservableBooleanValue;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import org.fxmisc.flowless.VirtualizedScrollPane;
import org.fxmisc.richtext.StyleClassedTextArea;
import org.fxmisc.undo.UndoManager;
import org.reactfx.value.Val;
import java.util.concurrent.atomic.AtomicBoolean;
public class Main extends Application {
private Thread memoryMonitorThread;
private AtomicBoolean runMemoryMonitorThread = new AtomicBoolean(true);
private AtomicBoolean runCharPrintThread = new AtomicBoolean(true);
@Override
public void start(Stage primaryStage) throws Exception{
AnchorPane root = new AnchorPane();
StyleClassedTextArea textArea = new StyleClassedTextArea();
VirtualizedScrollPane scrollPane = new VirtualizedScrollPane<>(textArea);
textArea.setUndoManager(getNoOpUndoManager());
AnchorPane.setBottomAnchor(scrollPane, 0.0);
AnchorPane.setTopAnchor(scrollPane, 0.0);
AnchorPane.setLeftAnchor(scrollPane, 0.0);
AnchorPane.setRightAnchor(scrollPane, 0.0);
root.getChildren().add(scrollPane);
primaryStage.setTitle("Memory Leak");
primaryStage.setScene(new Scene(root, 800, 400));
primaryStage.show();
new Thread(()-> {
while(runCharPrintThread.get()) {
sleep(50);
Platform.runLater(() -> {
textArea.appendText("a");
});
sleep(50);
Platform.runLater(() -> {
textArea.deleteText(textArea.getLength() - 1, textArea.getLength());
});
}
}).start();
// ////////////////////// NO Memory leak 2 /////////////////////////
// new Thread(()-> {
// while(runCharPrintThread.get()) {
// try {
// Thread.sleep(50);
// } catch (InterruptedException e) {
// }
// Platform.runLater(() -> {
// textArea.appendText("a\n");
// scrollPane.scrollYBy(Double.MAX_VALUE);
// });
// }
// }).start();
// ////////////////////////////////////////////////////////////
startMemoryUsageMonitorThread();
primaryStage.setOnCloseRequest(t -> {
runMemoryMonitorThread.set(false);
memoryMonitorThread.interrupt();
runCharPrintThread.set(false);
});
}
private void sleep(long mills) {
try {
Thread.sleep(mills);
} catch (InterruptedException e) {
}
}
private void startMemoryUsageMonitorThread() {
memoryMonitorThread = new Thread(()-> {
while(runMemoryMonitorThread.get()) {
long memory = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024);
System.out.println("Used Memory: " + memory + "MB");
try { Thread.sleep(10000);
} catch (InterruptedException e) {
}
}
});
memoryMonitorThread.start();
}
private UndoManager getNoOpUndoManager() {
return new UndoManager() {
private final Val<Boolean> alwaysFalse = Val.constant(false);
@Override public boolean undo() { return false; }
@Override public boolean redo() { return false; }
@Override public Val<Boolean> undoAvailableProperty() { return alwaysFalse; }
@Override public boolean isUndoAvailable() { return false; }
@Override public Val<Boolean> redoAvailableProperty() { return alwaysFalse; }
@Override public boolean isRedoAvailable() { return false; }
@Override public boolean isPerformingAction() { return false; }
@Override public boolean isAtMarkedPosition() { return false; }
// not sure whether these may throw NPEs at some point
@Override public Val nextUndoProperty() { return null; }
@Override public Val nextRedoProperty() { return null; }
@Override public ObservableBooleanValue performingActionProperty() { return null; }
@Override public UndoPosition getCurrentPosition() { return null; }
@Override public ObservableBooleanValue atMarkedPositionProperty() { return null; }
// ignore these
@Override public void preventMerge() { }
@Override public void forgetHistory() { }
@Override public void close() { }
};
}
public static void main(String[] args) {
launch(args);
}
}
Hi,
I have a strange problem..
When printing a single character to StyleClassedTextArea every 50ms, memory usage keeps growing
until application is very slow and not responding. In the examples below, I'm using a thread to update the textarea but in my real application the character comes from serial port at the same rate (50ms).
This bug does not happen if using richtextfx-fat-0.8.2.jar, only when using richtextfx-fat-0.9.0.jar and up.
Whats strange about it is that when printing more than just a single character at one time, for example - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" or when printing single character with new-line "a\n" than there is no memory leak and everything seems to be OK.
See the code "Memory leak" for the example where there is a memory leak.
See the commented code "NO Memory leak 1" and "NO Memory leak 2" for examples where there is no memory leak.
Any help/suggestions how to solve this will be highly appreciated :)
THANKS