我正在使用JavaFX设计秒表。代码运行良好。除了巨大的累积内存泄漏随着时间的推移。每当我增加Timeline
的{{1}}时,泄漏就会增加。我目前使用的是4GB内存的Ubuntu 16.04,泄漏速度为300MB / min,速度为30fps。那是5MBps。我可以理解,这可能是由于重复绘制framerate
而发生的,但为什么会累积? JVM不应该解决这个问题吗?
Main.java:
Scene
ClockUI.java:
package UI;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("StopWatch");
primaryStage.setScene(new Scene(getPane(), 400, 400));
primaryStage.show();
}
private BorderPane getPane(){
BorderPane pane = new BorderPane();
ClockUI clockUI = new ClockUI();
clockUI.setMinSize(200,200);
pane.setCenter(clockUI);
ButtonBar buttonBar = new ButtonBar();
Button startButton = new Button("Start");
startButton.setOnAction(e->clockUI.startClock());
Button pauseButton = new Button("Stop");
pauseButton.setOnAction(e->clockUI.stopClock());
Button resetButton = new Button("Reset");
resetButton.setOnAction(e->clockUI.resetClock());
buttonBar.getButtons().addAll(startButton, pauseButton, resetButton);
pane.setBottom(buttonBar);
return pane;
}
public static void main(String[] args) {
System.setProperty("prism.lcdtext","false");
launch(args);
}
}
信息:我尝试过各种其他方法,例如使用package UI;
import javafx.animation.*;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.transform.Rotate;
import javafx.util.Duration;
/**
* Created by subhranil on 23/6/17.
*/
public class ClockUI extends StackPane {
private final Rotate hourRotate;
private final Rotate minuteRotate;
private final Rotate secondRotate;
private final Timeline hourTimeline;
private final Timeline minuteTimeline;
private final Timeline secondTimeline;
private final ParallelTransition clockTransition;
public ClockUI() {
super();
Line hourHand = getHand(80, Color.WHITE);
hourRotate = getRotate(hourHand);
hourTimeline = createRotateTimeline(Duration.hours(12), hourRotate);
Line minuteHand = getHand(100, Color.WHITE);
minuteRotate = getRotate(minuteHand);
minuteTimeline = createRotateTimeline(Duration.minutes(60), minuteRotate);
Line secondHand = getHand(90, Color.WHITE);
secondRotate = getRotate(secondHand);
secondTimeline = createRotateTimeline(Duration.seconds(60), secondRotate);
clockTransition = new ParallelTransition(hourTimeline, minuteTimeline, secondTimeline);
Circle back = new Circle(120);
back.centerXProperty().bind(widthProperty().divide(2));
back.centerYProperty().bind(heightProperty().divide(2));
back.setStyle("-fx-fill: #555555");
setStyle("-fx-background-color: #333333;");
getChildren().addAll(back, hourHand, minuteHand, secondHand);
}
private Timeline createRotateTimeline(Duration duration, Rotate rotate) {
Timeline timeline = new Timeline(30);
timeline.getKeyFrames().add(new KeyFrame(duration, new KeyValue(rotate.angleProperty(), 360)));
timeline.setCycleCount(Animation.INDEFINITE);
return timeline;
}
public void startClock() {
if (clockTransition.getStatus() != Animation.Status.RUNNING) {
clockTransition.play();
}
}
public void stopClock() {
if (clockTransition.getStatus() == Animation.Status.RUNNING) {
clockTransition.pause();
}
}
public void resetClock() {
stopClock();
clockTransition.stop();
}
private Rotate getRotate(Line line){
Rotate r = new Rotate(0);
r.pivotXProperty().bind(line.startXProperty());
r.pivotYProperty().bind(line.startYProperty());
line.getTransforms().add(r);
return r;
}
private Line getHand(int size, Paint color) {
Line hand = new Line();
hand.startXProperty().bind(widthProperty().divide(2));
hand.startYProperty().bind(heightProperty().divide(2));
hand.endXProperty().bind(widthProperty().divide(2));
hand.endYProperty().bind(heightProperty().divide(2).subtract(size));
hand.setStroke(color);
hand.setStrokeWidth(3);
return hand;
}
}
和ExecutorService
运行Task
,但都会产生相同的结果。
答案 0 :(得分:0)
试试这个,看看你是否遇到同样的问题。
ClockGUI
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.transform.*;
/**
*
* @author Sedrick
*/
public class ClockGUI {
Circle clockFace;
Line second;
Line minute;
Line hour;
Rotate secondRotation;
Rotate minuteRotation;
Rotate hourRotation;
AnchorPane currentClockFace;
public ClockGUI()
{
currentClockFace = new AnchorPane();
currentClockFace.setPrefSize(100, 100);
clockFace = new Circle(100 / 2, 100 / 2, 100 / 2);
clockFace.setStroke(Color.BLACK);
clockFace.setFill(Color.TRANSPARENT);
second = new Line(100 / 2, 100 / 2, 100 / 2, 100 / 2 - 40);
secondRotation = new Rotate();
secondRotation.pivotXProperty().bind(second.startXProperty());
secondRotation.pivotYProperty().bind(second.startYProperty());
second.getTransforms().add(secondRotation);
minute = new Line(100 / 2, 100 / 2, 100 / 2, 100 / 2 - 30);
minuteRotation = new Rotate();
minuteRotation.pivotXProperty().bind(minute.startXProperty());
minuteRotation.pivotYProperty().bind(minute.startYProperty());
minute.getTransforms().add(minuteRotation);
hour = new Line(100 / 2, 100 / 2, 100 / 2, 100 / 2 - 20);
hourRotation = new Rotate();
hourRotation.pivotXProperty().bind(hour.startXProperty());
hourRotation.pivotYProperty().bind(hour.startYProperty());
hour.getTransforms().add(hourRotation);
currentClockFace.getChildren().addAll(clockFace, second, minute, hour);
}
public AnchorPane getCurrentClock()
{
return currentClockFace;
}
public void rotateSecondLine()
{
secondRotation.setAngle(secondRotation.getAngle() + 6);
}
public double getRotateSecondLine()
{
return secondRotation.getAngle();
}
public void setRotateSecond(double degree)
{
secondRotation.setAngle(degree);
}
public void rotateMinuteLine()
{
minuteRotation.setAngle(minuteRotation.getAngle() + 6);
}
public double getRotateMinuteLine()
{
return minuteRotation.getAngle();
}
public void setRotateMinute(double degree)
{
minuteRotation.setAngle(degree);
}
public void rotateHourLine()
{
hourRotation.setAngle(hourRotation.getAngle() + 6);
}
public double getRotateHourLine()
{
return hourRotation.getAngle();
}
public void setRotateHour(double degree)
{
hourRotation.setAngle(degree);
}
}
主要
import javafx.animation.*;
import javafx.application.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
import javafx.util.*;
/**
*
* @author Sedrick
*/
public class JavaFXApplication54 extends Application {
@Override
public void start(Stage primaryStage)
{
VBox root = new VBox();
ClockGUI cgui = new ClockGUI();
StackPane stackpane = new StackPane();
stackpane.getChildren().add(cgui.getCurrentClock());
root.getChildren().add(stackpane);
Button btn = new Button("Rotate seconds");
btn.setOnAction((event) -> {
cgui.rotateSecondLine();
});
Button btn2 = new Button("Rotate minutes");
btn2.setOnAction((event) -> {
cgui.rotateMinuteLine();
});
Button btn3 = new Button("Rotate hours");
btn3.setOnAction((event) -> {
cgui.rotateHourLine();
});
root.getChildren().addAll(btn, btn2, btn3);
Scene scene = new Scene(root, 300, 250);
Timeline timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.getKeyFrames().add(
new KeyFrame(Duration.seconds(1),
new EventHandler() {
// KeyFrame event handler
@Override
public void handle(Event event)
{
System.out.println(cgui.getRotateSecondLine());
cgui.rotateSecondLine();
if (cgui.getRotateSecondLine() >= 360) {
cgui.setRotateSecond(0);
cgui.rotateMinuteLine();
}
if (cgui.getRotateMinuteLine() >= 360) {
cgui.setRotateMinute(0);
cgui.rotateHourLine();
}
if (cgui.getRotateHourLine() >= 360) {
cgui.setRotateHour(0);
}
}
}
));
timeline.playFromStart();
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}