2

我有一个行为非常不稳定的 JavaFx 程序。

如果我在文本字段上按 enter,JVM 就会崩溃。这是从这个stackoverflow 问题中获得的一个简单的 UI 程序。这个看起来很无辜的程序有什么问题?

我正在跑步Lubuntu 12.10JDK 1.7.0_09-b05

import com.sun.glass.events.KeyEvent;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;

public class MissingDataDemo extends Application {
        private static final String[] SAMPLE_TEXT = "Lorem ipsum MISSING dolor sit amet MISSING consectetur adipisicing elit sed do eiusmod tempor incididunt MISSING ut labore et dolore magna aliqua"
                        .split(" ");

        @Override
        public void start(Stage primaryStage) {
                VBox textContainer = new VBox(10);
                textContainer
                                .setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");

                primaryStage.setScene(new Scene(textContainer, 300, 600));
                primaryStage.show();

                TextLoader textLoader = new TextLoader(SAMPLE_TEXT, textContainer);
                textLoader.loadText();
        }

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

class TextLoader {
        private final String[] lines;
        private final Pane container;

        TextLoader(final String[] lines, final Pane container) {
                this.lines = lines;
                this.container = container;
        }

        public void loadText() {
                for (String nextText : lines) {
                        final Label nextLabel = new Label();

                        if ("MISSING".equals(nextText)) {
                                nextLabel.setStyle("-fx-background-color: palegreen;");

                                MissingTextPrompt prompt = new MissingTextPrompt(container
                                                .getScene().getWindow());

                                nextText = prompt.getResult();
                        }

                        nextLabel.setText(nextText);

                        container.getChildren().add(nextLabel);
                }
        }

        class MissingTextPrompt {
                private final String result;

                MissingTextPrompt(Window owner) {
                        final Stage dialog = new Stage();

                        dialog.setTitle("Enter Missing Text");
                        dialog.initOwner(owner);
                        dialog.initStyle(StageStyle.UTILITY);
                        dialog.initModality(Modality.WINDOW_MODAL);
                        dialog.setX(owner.getX() + owner.getWidth());
                        dialog.setY(owner.getY());

                        final TextField textField = new TextField();
                        final Button submitButton = new Button("Submit");
                        submitButton.setDefaultButton(true);

                        submitButton.setOnAction(new EventHandler<ActionEvent>() {
                                @Override
                                public void handle(ActionEvent t) {
                                        dialog.close();
                                }
                        });

                        textField.setMinHeight(TextField.USE_PREF_SIZE);

                        final VBox layout = new VBox(10);
                        layout.setAlignment(Pos.CENTER_RIGHT);
                        layout.setStyle("-fx-background-color: azure; -fx-padding: 10;");
                        layout.getChildren().setAll(textField, submitButton);

                        dialog.setScene(new Scene(layout));
                        dialog.showAndWait();

                        result = textField.getText();
                }

                private String getResult() {
                        return result;
                }
        }
}

转储的某些部分 -

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0xb6cfa39f, pid=14093, tid=1803479872
#
# JRE version: 7.0_09-b05
# Java VM: Java HotSpot(TM) Server VM (23.5-b02 mixed mode linux-x86 )
# Problematic frame:
# V  [libjvm.so+0x42539f]  jni_invoke_nonstatic(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)+0x2f
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

完整的转储可在此处获得。

编辑1:

使用最新版本的 Oracle 运行它Java 1.7.0_25-b15也会崩溃。

编辑2:

运行它OpenJDK 7u9-2.3.4-0ubuntu1.12.10.1不会崩溃,但会出现以下错误 -

Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:403)
    at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:47)
    at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:115)
    at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.NullPointerException
    at com.sun.glass.ui.gtk.GtkApplication.enterNestedEventLoopImpl(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication._enterNestedEventLoop(GtkApplication.java:137)
    at com.sun.glass.ui.Application.enterNestedEventLoop(Application.java:383)
    at com.sun.glass.ui.EventLoop.enter(EventLoop.java:83)
    at com.sun.javafx.tk.quantum.QuantumToolkit.enterNestedEventLoop(QuantumToolkit.java:520)
    at javafx.stage.Stage.showAndWait(Stage.java:397)
    at com.mango.proengin.ui.user.TextLoader$MissingTextPrompt.<init>(MissingDataDemo.java:96)
    at com.mango.proengin.ui.user.TextLoader.loadText(MissingDataDemo.java:52)
    at com.mango.proengin.ui.user.MissingDataDemo.start(MissingDataDemo.java:28)
    at com.sun.javafx.application.LauncherImpl$5.run(LauncherImpl.java:319)
    at com.sun.javafx.application.PlatformImpl$5.run(PlatformImpl.java:206)
    at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:173)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:82)
    ... 1 more
4

1 回答 1

3

在我看来,本机 UI 代码中存在潜在的线程错误 - 在带有最新 JDK 的 Windows 7 x64 上,它运行时没有问题(目前无法访问 Linux 机器进行测试。)

在从平台线程中调用 UI 代码之前,我已经看到过类似的奇怪行为,但据我所知,这并没有在这里发生。话虽如此,尽管您不必这样做(因为无论如何它都在平台线程上),但我有时发现无论如何包装有问题的代码Platform.runLater()可以解决问题 - 或者至少可以解决它:

        submitButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        dialog.close();
                    }
                });
            }
        });

这可能只是以 GTK 喜欢的方式改变线程,尽管它并不理想。无论哪种方式,都值得尽可能地简化示例(虽然您仍然可靠地得到错误)并报告错误。

于 2013-08-29T14:24:28.970 回答