java.lang.StackOverflowErrorの原因


回答:


59

メソッドの忌まわしい呼び出しがないか確認してください。主に、メソッドの再帰呼び出しがある場合に発生します。簡単な例は

public static void main(String... args) {
    Main main = new Main();

    main.testMethod(1);
}

public void testMethod(int i) {
    testMethod(i);

    System.out.println(i);
}

ここでSystem.out.println(i); testMethodが呼び出されると、スタックに繰り返しプッシュされます。


1
私はあなたが正しいと思います。しかし、それの解決策は何ですか。私たちはそれを拒否するメソッドを作っているので、それが必要であることを意味します。方法を変えたくない。では、このエラーをどのように解決できますか?
Ajay Sharma 2016年

1
または、無限ループに入っています!
yalematta 2016年

@yalematta、再帰メソッドには終了する条件が必要です。したがって、再帰メソッドが適切に実装され、何らかの条件に応じて終了するかどうかを確認してください。
アヤズアリフォフ2016

@AjaySharmaJVMに割り当てた使用可能なメモリ境界に収まるようにシステムを設計する必要があります。システムが次のエラーで正常に動作しない場合は、コードベースを確認する必要があります。
Thota Srinath 2017

23

JVMに対する(オプションの)引数の1つは、スタックサイズです。-Xssです。デフォルト値が何であるかはわかりませんが、スタック上のものの合計量がその値を超えると、そのエラーが発生します。

一般に、無限再帰がこの原因ですが、それが表示された場合、スタックトレースには5フレーム以上が含まれます。

-Xss引数を追加する(または1の値を増やす)ことで、これがなくなるかどうかを確認してください。


10

実際にjava.lang.StackOverflowErrorを引き起こすのは、通常、意図しない再帰です。私にとっては、オーバーライドされたメソッドのスーパーメソッドを呼び出すつもりだったことがよくあります。この場合のように:

public class Vehicle {
    public void accelerate(float acceleration, float maxVelocity) {
        // set the acceleration
    }
}

public class SpaceShip extends Vehicle {
    @Override
    public void accelerate(float acceleration, float maxVelocity) {
        // update the flux capacitor and call super.accelerate
        // oops meant to call super.accelerate(acceleration, maxVelocity);
        // but accidentally wrote this instead. A StackOverflow is in our future.
        this.accelerate(acceleration, maxVelocity); 
    }
}

まず、関数を呼び出すときに舞台裏で何が起こるかを知ることは役に立ちます。メソッドが呼び出された場所の引数とアドレスがスタックにプッシュされ(http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_managementを参照)、呼び出されたメソッドが引数にアクセスできるようになります。呼び出されたメソッドが完了すると、呼び出し後も実行を続行できます。ただし、this.accelerate(acceleration、maxVelocity)を再帰的に呼び出しているため(メソッドがそれ自体を呼び出す場合、再帰は大まかになります。詳細については、http://en.wikipedia.org/wiki/Recursion_(computer_science)を参照してください)無限再帰と呼ばれる状況にあり、引数と戻りアドレスを呼び出しスタックに積み上げ続けます。コールスタックのサイズは有限であるため、最終的にスペースが不足します。コールスタックのスペースが不足すると、オーバーフローと呼ばれます。これは、現在よりも多くのスタックスペースを使用しようとしており、データが文字通りスタックをオーバーフローしているためです。Javaプログラミング言語では、これによりランタイム例外java.lang.StackOverflowが発生し、プログラムがすぐに停止します。

上記の例はやや単純化されています(ただし、私が認めたい以上に起こります)。同じことがよりラウンドアバウトで発生する可能性があり、追跡が少し難しくなります。ただし、一般的に、StackOverflowは、一度発生すると、通常は非常に簡単に解決できます。

理論的には、再帰なしでスタックオーバーフローが発生する可能性もありますが、実際には、かなりまれなイベントのように見えます。


8

とは java.lang.StackOverflowError

このエラーjava.lang.StackOverflowErrorは、深い再帰が原因で、つまりプログラム/スクリプトの再帰が深すぎるために、アプリケーションのスタックが使い果たされたことを示すためにスローされます。

詳細

StackOverflowError拡張VirtualMachineErrorJVMがされているかのリソースが不足していると、さらに操作することができないことを示しているクラスを。VirtualMachineError伸びているErrorクラスは、アプリケーションがキャッチしてはならないこれらの深刻な問題を示すために使用されます。throwこれらのエラーは予期されていなかった異常な状態であるため、メソッドはその句でそのようなエラーを宣言しない場合があります。

Minimal, Complete, and Verifiable Example

package demo;

public class StackOverflowErrorExample {

    public static void main(String[] args) 
    {
        StackOverflowErrorExample.recursivePrint(1);
    }

    public static void recursivePrint(int num) {
        System.out.println("Number: " + num);

        if(num == 0)
            return;
        else
            recursivePrint(++num);
    }

}

コンソール出力

Number: 1
Number: 2
.
.
.
Number: 8645
Number: 8646
Number: 8647Exception in thread "main" java.lang.StackOverflowError
    at java.io.FileOutputStream.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
    at java.io.BufferedOutputStream.flush(Unknown Source)
    at java.io.PrintStream.write(Unknown Source)
    at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
    at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source)
    at java.io.OutputStreamWriter.flushBuffer(Unknown Source)
    at java.io.PrintStream.newLine(Unknown Source)
    at java.io.PrintStream.println(Unknown Source)
    at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:11)
    at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)
    .
    .
    .
    at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)

説明

Javaアプリケーションによって関数呼び出しが呼び出されると、スタックフレーム呼び出しスタックに割り当てられます。にstack frameは、呼び出されたメソッドのパラメーター、そのローカルパラメーター、およびメソッドの戻りアドレスが含まれます。戻りアドレスは、呼び出されたメソッドが戻った後もプログラムの実行を続行する実行ポイントを示します。新しいスタックフレーム用のスペースがない場合、StackOverflowErrorはJava仮想マシン(JVM)によってスローされます。

Javaアプリケーションのスタックを使い果たす可能性がある最も一般的なケースは、再帰です。再帰では、メソッドは実行中にそれ自体を呼び出します。Recursion最も強力な汎用プログラミング手法の1つですが、StackOverflowError回避するために注意して使用する必要があります。

参考文献


4

Javaアプリケーションによって関数呼び出しが呼び出されると、スタックフレームが呼び出しスタックに割り当てられます。スタックフレームには、呼び出されたメソッドのパラメーター、そのローカルパラメーター、およびメソッドの戻りアドレスが含まれています。

戻りアドレスは、呼び出されたメソッドが戻った後もプログラムの実行を続行する実行ポイントを示します。新しいスタックフレーム用のスペースがない場合、StackOverflowErrorJava仮想マシン(JVM)によってスローされます。

Javaアプリケーションのスタックを使い果たす可能性がある最も一般的なケースは、再帰です。

ご覧ください

StackOverflowErrorを解決する方法


2

hibernateを使用してプログラムを作成しました。このプログラムでは、データメンバーとして相互のオブジェクトを持つ2つのPOJOクラスを作成しました。mainメソッドでそれらをデータベースに保存しようとすると、このエラーも発生しました。

これは、両方のクラスが相互に参照しているために発生し、このエラーの原因となるループが作成されます。

したがって、そのような種類の関係がプログラムに存在するかどうかを確認してください。


2

データを解析する際のHibernateユーザー向けのソリューション:

両側@OneToMany@ManyToOnejsonにマップされたオブジェクトのリストをjacksonを使用して解析していたため、このエラーが発生し、無限ループが発生しました。

同じ状況にある場合は@JsonManagedReference@JsonBackReference注釈を使用してこれを解決できます。

APIからの定義:

  • JsonManagedReference(https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html):

    注釈付きプロパティがフィールド間の双方向リンクの一部であることを示すために使用される注釈。そして、その役割は「親」(または「転送」)リンクであること。プロパティの値タイプ(クラス)には、JsonBackReferenceアノテーションが付けられた単一の互換性のあるプロパティが必要です。リンケージは、このアノテーションが付けられたプロパティが通常どおり処理されるように処理されます(通常どおりシリアル化され、逆シリアル化のための特別な処理はありません)。特別な処理が必要なのはマッチングバックリファレンスです

  • JsonBackReference:(https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html):

    関連するプロパティがフィールド間の双方向リンクの一部であることを示すために使用される注釈。そして、その役割は「子」(または「戻る」)リンクであること。プロパティの値の型はBeanである必要があります。コレクション、マップ、配列、または列挙型にすることはできません。リンケージは、このアノテーションが付けられたプロパティがシリアル化されないように処理されます。逆シリアル化中、その値は「マネージド」(フォワード)リンクを持つインスタンスに設定されます。

例:

Owner.java:

@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;

Car.java:

@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;

別の解決策は@JsonIgnore、フィールドにnullを設定するだけのを使用することです。


1

スタックオーバーフローの例外は、スレッドスタックが最大制限に達するまでサイズが大きくなり続けると発生する可能性があります。

スタックサイズ(XssおよびXmso)オプションの調整...

次のリンクを参照することをお勧めします。http: //www-01.ibm.com/support/docview.wss?uid = swg21162896リンクに 示されているように、StackOverflowErrorには多くの原因が考えられます。


リンクのみの回答は一般的に受け入れられません。リンクが壊れて、答えが完全に無効になります。リンクだけでなく、コンテキスト、コード、回答の説明を提供してください。
ジェイ

0

私の場合、2つの活動があります。2番目のアクティビティでは、onCreateメソッドにスーパーを置くのを忘れました。

super.onCreate(savedInstanceState);

を上げることができる方法であったとしてもStackOverflowError、私はそれが質問に答えているとは思いません。適切な答えは、再帰を多用する以外にこの例外を取得する他の方法をリストするか、手動でスローする以外にそのような例外を取得する他の方法は絶対にないと言うべきだと思います。
JojOatXGME 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.