JavaFX version: 8
JDK: 1.8
OS: Windows 10

開発中のアプリケーションでメモリリークが起きているため、以下のコードで検証をしました。

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

class CustomNode extends Pane {

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("Do finalize!!!");
    }
}

public class Main extends Application {

    private Button aButton = null;
    private Button bButton = null;
    private Pane container = new Pane();

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));

        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();

        aButton = (Button)root.lookup("#AButton");
        bButton = (Button)root.lookup("#BButton");
        aButton.setOnAction(event -> {
            System.out.println("AOnPushed");
            for (int i = 0; i < 10000; i++) {
                CustomNode node = new CustomNode();
                container.getChildren().add(node);
            }
        });
        bButton.setOnAction(event -> {
            System.out.println("BOnPushed");
            container.getChildren().removeAll();
        });
    }

    public static void main(String[] args) {
        launch(args);
    }
}
  1. Aボタンを押すと、コンテナに生成したNodeオブジェクトを追加する。
  2. Bボタンを押すと、コンテナを空にする。
  3. VisualVM等でGCを実行する。

2.の段階で、コンテナからNodeオブジェクトは破棄されるため、Nodeオブジェクトを参照する要素がなくなる。 -> GCの対象になる。というのが期待する動作です。しかし、実際にはコンテナを空にしてもNodeオブジェクトは破棄されません。
このコードで何故メモリリークが発生してしまうのでしょうか?

追記

package sample;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;


class CustomNode {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("Do finalize!!!");
    }

}

public class Main extends Application {

    private Button aButton = null;
    private Button bButton = null;
    private ObservableList<CustomNode> container = FXCollections.observableArrayList();
    // private List<CustomNode> container = new ArrayList<>();

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));

        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();

        aButton = (Button)root.lookup("#AButton");
        bButton = (Button)root.lookup("#BButton");
        aButton.setOnAction(event -> {
            System.out.println("AOnPushed");
            for (int i = 0; i < 10000; i++) {
                CustomNode node = new CustomNode();
                container.add(node);
            }
        });
        bButton.setOnAction(event -> {
            System.out.println("BOnPushed");
            // container.clear(); // clear()だとリークしなかった
            container.removeAll();
        });
    }

    public static void main(String[] args) {
        launch(args);
    }
}

ObservableList<>を使うだけで同様の現象になったのでNodeクラス自体は関係なさそうです。