JavaFX无限期时间轴中的内存泄漏

时间:2017-06-24 08:20:21

标签: java animation javafx memory-leaks timeline

我正在使用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,但都会产生相同的结果。

1 个答案:

答案 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);
    }

}