0

私はこのJavaFXマス計算機を作成しています。これは本質的に特定の比率や因数などを計算するためにSwingWorkerバックグラウンドスレッドを実行するボタンで構成されています。SwingWorkerでexecute()を呼び出したときの不思議なNullPointerException

私のファクタと素因数の計算(ユーザーが入力した数値のすべての要素と素因数を見つけようとすると)は、計算が約3-5回実行された後、NullPointerExceptionになります回。ここで

は、ボタンがクリックされたときに実行するスクリプトです:

public static longCalculationThread calculationThread; 

//Called by the calculate button 
@FXML 
void callCalculation(ActionEvent event) throws IOException, InterruptedException { 

    Long number = 0L; 
    Long lowerBound = 0L; 
    Long higherBound = 0L; 

    try { 
     //Bunch of input verification logic here. The logic here also creates the variables for the thread bundle 

     //Enabling progress UI since no errors were encoundered... 
     excelPane.setVisible(false); 
     progressPane.setDisable(false); 
     progressPane.setVisible(true); 

     //Preparing threadBundle, which is just a bunch of fields out into a data holding class [not shown] 

     calculationThread = new longCalculationThread(threadBundle); 
     calculationThread.execute(); 
     System.gc(); //For the objects of the previous calculationThread 
    } 
} 

そして、ここではlongCalculationThreadが構成されている方法は次のとおりです。

package PrimusForPC; 

public class longCalculationThread extends SwingWorker<Void, Void> { 

private ArrayList<Long> longResults = new ArrayList<>(); 
private ArrayList<String> stringResults = new ArrayList<>(); 

private calculationHolder.calculationType type; 
private JFXProgressBar progressBar; 
private Text progressText; 
private GridView<String> answerGridView; 
private Pane mainPane, progressPane; 
private long mainNumber, lowerNum, upperNum; 
private boolean shouldExport; 
private ExcelWriter.spreadsheetTypes exportType; 
private int excelExportLimit; 
private JFXButton calcButton; 
private Menu selectionMenu; 

private static double acceptableAccuracy = 0.004; //The degree of accuracty for pi and phi couples 
public static final double PHI = 1.6180339887498948482045; 

public boolean shouldDie; //Called externally to kill the thread. Hasn't been implemented yet 


longCalculationThread(threadArgumentBundle bundle){ 
    progressBar = bundle.progressBar; 
    answerGridView = bundle.answerGridView; 
    type = bundle.type; 
    mainNumber = bundle.primaryNumber; 
    upperNum = bundle.upperNum; 
    lowerNum = bundle.lowerNum; 
    progressText = bundle.progressText; 
    mainPane = bundle.mainPane; 
    progressPane = bundle.progressPane; 
    exportType = bundle.exportType; 
    shouldExport = bundle.shouldExport; 
    excelExportLimit = bundle.excelExportLimit; 
    calcButton = bundle.button; 
    selectionMenu = bundle.selectionMenu; 
} 


@Override 
public Void doInBackground(){ 
    System.out.println("Thread started " + Thread.currentThread().getName()); 
    Platform.runLater(new Runnable() { 
    @Override 
    public void run() { 
     progressBar.isIndeterminate(); 
     progressBar.progressProperty().setValue(0); 
     calcButton.setDisable(true); 
     selectionMenu.setDisable(true); 
     } 
    }); 

    switch (type){ 
     case factors: 
      findfactors(); 
      break; 
     case primeFactors: 
      findPrimeFactors(); 
      break; 
     case primesUpToX: 
      findPrimesUpToX(); 
      break; 
//Bunch of other cases here...  
    } 
    try { 
     publishResults(); 
    } catch (IOException | InterruptedException ex) { 
     Logger.getLogger(longCalculationThread.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    reEndableInterface(); 
    System.gc(); 
    System.out.println("Thread ended " + Thread.currentThread().getName() + "\n"); 
    return null; 
} 


static private long getSquareRoot (long number){ 
    //For calculations square root only matters for larger numbers 
    //for numbers below 5 it doesn't really matter 
    if (number > 5){ 
     number = (long) Math.ceil(Math.sqrt(number)); 
    } 
return number; 
} 


private void findfactors(){ 
    progressText.setText("Finding factors..."); 
    long root = getSquareRoot(mainNumber); 
    double incrementValue = 1/(double)root; 
     for (long divisor = 1; divisor <= root; divisor++) { 
     setProgressBar(progressBar.getProgress() + incrementValue); 
     if (mainNumber % divisor == 0) { 
      longResults.add(divisor); 
      longResults.add((mainNumber/divisor)); 
     } 
    } 
} 


private void findPrimeFactors(){ 
    findfactors(); 
    progressText.setText("Separating prime factors from composite factors..."); 
    progressBar.progressProperty().set(0); 
    double incrementValue = 1/(double)longResults.size(); 
    ArrayList <Long> realResults = new ArrayList<>(); 
    for (long factor: longResults){ 
     if (isPrime(factor)) realResults.add(factor); 
     setProgressBar(progressBar.getProgress() + incrementValue); 
    } 

    longResults = realResults; 
} 


static boolean isPrime(long number){ 
    if (number == 1) return false; 
    if (number == 2 || number == 3 || number == 5) return true; 
    long root = getSquareRoot(number); 
    for (int divisor = 2; divisor <= root; divisor++) 
     if (number % divisor == 0) return false; 
    return true; 
} 


private void publishResults() throws IOException, InterruptedException{ 

     Platform.runLater(new Runnable() { 
      @Override 
      public void run() { 
       answerGridView.getItems().setAll(stringResults); 
       } 
      });   

//To make UI interface useable again 
private void reEndableInterface(){ 
    Platform.runLater(new Runnable() { 
      @Override 
      public void run() { 
       progressPane.setDisable(true); 
       progressPane.setVisible(false); 
       mainPane.setDisable(false); 
       mainPane.setVisible(true); 
       calcButton.setDisable(false); 
       System.out.println("Button enabled " + Thread.currentThread().getName()); 
       selectionMenu.setDisable(false); 
       } 
      }); 
} 

私はこのNullPointerExceptionがどこから来ている正確にわからないんだけど、またはなぜ私が "find factors"または "find prime factors"計算を使用しているときにのみ現れているように見えますか?ここではエラーログを見ています(残念ですが、それはずっと長く、どこを切り捨てるかわかりませんでした)。

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException 
at com.sun.javafx.text.PrismTextLayout.addTextRun(PrismTextLayout.java:755) 
at com.sun.javafx.text.GlyphLayout.addTextRun(GlyphLayout.java:140) 
at com.sun.javafx.text.GlyphLayout.breakRuns(GlyphLayout.java:312) 
at com.sun.javafx.text.PrismTextLayout.buildRuns(PrismTextLayout.java:770) 
at com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1021) 
at com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:223) 
at com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:246) 
at javafx.scene.text.Text.getLogicalBounds(Text.java:358) 
at javafx.scene.text.Text.impl_computeGeomBounds(Text.java:1168) 
at javafx.scene.Node.updateGeomBounds(Node.java:3577) 
at javafx.scene.Node.getGeomBounds(Node.java:3530) 
at javafx.scene.Node.getLocalBounds(Node.java:3478) 
at javafx.scene.Node.updateTxBounds(Node.java:3641) 
at javafx.scene.Node.getTransformedBounds(Node.java:3424) 
at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1724) 
at javafx.scene.Parent.updateCachedBounds(Parent.java:1588) 
at javafx.scene.Parent.recomputeBounds(Parent.java:1527) 
at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1380) 
at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078) 
at javafx.scene.Node.updateGeomBounds(Node.java:3577) 
at javafx.scene.Node.getGeomBounds(Node.java:3530) 
at javafx.scene.Node.getLocalBounds(Node.java:3478) 
at javafx.scene.Node.updateTxBounds(Node.java:3641) 
at javafx.scene.Node.getTransformedBounds(Node.java:3424) 
at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1724) 
at javafx.scene.Parent.updateCachedBounds(Parent.java:1588) 
at javafx.scene.Parent.recomputeBounds(Parent.java:1527) 
at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1380) 
at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078) 
at javafx.scene.Node.updateGeomBounds(Node.java:3577) 
at javafx.scene.Node.getGeomBounds(Node.java:3530) 
at javafx.scene.Node.getLocalBounds(Node.java:3478) 
at javafx.scene.Node.updateTxBounds(Node.java:3641) 
at javafx.scene.Node.getTransformedBounds(Node.java:3424) 
at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1724) 
at javafx.scene.Parent.updateCachedBounds(Parent.java:1588) 
at javafx.scene.Parent.recomputeBounds(Parent.java:1527) 
at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1380) 
at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078) 
at javafx.scene.Node.updateGeomBounds(Node.java:3577) 
at javafx.scene.Node.getGeomBounds(Node.java:3530) 
at javafx.scene.Node.getLocalBounds(Node.java:3478) 
at javafx.scene.Node.impl_intersectsBounds(Node.java:5013) 
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2931) 
at javafx.scene.Node.impl_pickNode(Node.java:4912) 
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2936) 
at javafx.scene.Node.impl_pickNode(Node.java:4912) 
at javafx.scene.Scene$MouseHandler.pickNode(Scene.java:3899) 
at javafx.scene.Scene$MouseHandler.access$1600(Scene.java:3485) 
at javafx.scene.Scene.pick(Scene.java:1942) 
at javafx.scene.Scene.access$6700(Scene.java:159) 
at javafx.scene.Scene$MouseHandler.process(Scene.java:3799) 
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) 
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) 
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275) 
at java.security.AccessController.doPrivileged(Native Method) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$355(GlassViewEventHandler.java:388) 
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) 
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387) 
at com.sun.glass.ui.View.handleMouseEvent(View.java:555) 
at com.sun.glass.ui.View.notifyMouse(View.java:937) 
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191) 
at java.lang.Thread.run(Thread.java:745) 

そして最後に、コンソールは、ちょうどスパム:無期限

java.lang.ArrayIndexOutOfBoundsException 

を。

私が言ったように、私は本当になぜこれが起こっているのかわかりません。計算が最初の数回行われると、このエラーが発生してアプリケーションがフリーズし、完全に再起動する必要があります。

+3

[javafx.concurrent.Task 'を[example](https://stackoverflow.com/a/44056730/230513)に使用してみませんか? – trashgod

+1

@trashgod:答えではないでしょうか? –

+1

おそらく、この前の質問はあなたに役立つかもしれません.. https://stackoverflow.com/questions/30863862/javafx-append-text-to-textarea-throws-exception –

答えて

0

私の質問にコメントした人々のおかげで - リンクによって問題が明らかになりました!

私はSwingWorkerを使用していました。私はUIスレッドに直接影響を与えたいと思っていました(Program.runLaterは頻繁に頻繁に呼び出されるとUIスレッドを氾濫させる可能性があるからです)。

SwingWorkersはJavaFXでその機能を使用できないことが判明したので、UIスレッドに直接影響を与えようとしていたのはそれらのエラーの原因でした。だから、私はスレッドを使用することに戻り、コメントにリンクによって提供された調整ロジックを使用しました。これにより、UIスレッドをフラッディングすることなく、ThreadでProgram.runLaterを使用することができました。

関連する問題