JavaRush /Java Blog /Random-JA /スタックトレースとそれが食べられるもの
Alukard
レベル 37
London

スタックトレースとそれが食べられるもの

Random-JA グループに公開済み
この記事では、Java 現象 StackTrace (コール スタック トレーシングとも呼ばれる) がどのように機能するかを学び、理解します。この情報は、Java 構文レベル 9 の初めにこの概念に出会った初心者向けに構成されています。IdeaEclipse など、IDE で作業しているときに、皆さんも少なくとも 1 度は同様のエラーに遭遇したことがあると思います。
Exception in thread "main" java.lang.ArithmeticException
	at com.example.task01.Test.division(Test.java:10)
	at com.example.task01.Test.main(Test.java:6)
ご想像のとおり、これが私たちの追跡です。ただし、慌てる必要はありません。この例を詳しく説明します。StackTraceまず、その名前が示すように機能するという事実を理解する必要がありますСтэк。この時点で、もう少し詳しく説明します。 スタックコレクションの仕組み 第 8 レベルでは、すでにコレクションに慣れており、コレクションが 3 つのグループSet(セット、Listリスト、Map辞書 (またはマップ)) に分類されていることがわかります。JavaRush によると(c)。 私たちも Stackそのグループの一員ですList。その動作原理は、Last In First Outの略であるLIFOとして説明できます。つまり、これは積み上げられた本のようなリストです。最初に入力した要素を取得するには、その後リストに追加したすべての要素を最初に抽出する必要があります。上の図に示されているように、たとえば、インデックスによってリストから任意の要素を取得できる通常のリストとは異なります。 またしても補強です。要素の取得は、端からのみ可能です。追加される最初の要素は先頭 (または、より便利な場合は最後) に追加されます。 これらは私たちのオブジェクトが持つ メソッドです- 要素をスタックの一番上に追加します。オブジェクト- スタックの最上位にある要素を返し、プロセス内で要素を削除します。オブジェクト- スタックの最上位にある要素を返しますが、削除はしません。int - スタック上の要素を検索します。見つかった場合は、スタックの先頭からのオフセットが返されます。それ以外の場合は -1 が返されます。boolean - スタックが空かどうかを確認します。スタックが空の場合は true を返します。スタックに要素が含まれている場合は false を返します。では、なぜ動作原理に基づいて構築されたものが必要なのでしょうか? このような単純なプログラムの実行中に発生したエラーの例を以下に見てみましょう。 StackArrayListСтэкаStackpush()pop()peek()search()empty()JavaStackTraceStack
public class Test {

    public static void main(String[] args) {
        System.out.println(convertStringToInt(null));
    }

    public static int convertStringToInt(String s) {
        int x = Integer.parseInt(s);
        return x;
    }
}
2 つのメソッドを持つクラスがありますTest。誰もがよく知っているmainこのconvertStringToIntロジックは、外部 (つまりメソッドmain) から受け取った文字列を type の整数に変換して返すというものですint。ご覧のとおり、数値を含む文字列の代わりにパラメータを意図的に渡していますnull。私たちのメソッドはこのパラメータを正しく処理できず、エラーが発生しましたNumberFormatException。ご存知のとおり、プログラムはメソッドから作業を開始し、この時点で作業の現在の値を番号1の下に置く名前でmain新しいプログラムを作成します。その後、メソッドとプログラムに戻ります。先ほど作成した番号2に位置のパラメータを入力します。次に、クラス内にある目に見えないメソッドが呼び出されます。これはすでに要素番号3になります。このメソッドには別の内部呼び出しが追加されます。番号4に要素をチェックしてnullをチェックすると、エラーが発生します。プログラムは、エラーが発生するまでの遷移のチェーン全体を示すエラーを表示する必要があります。ここで、トランジションのデータを使用して以前に作成したものが役に立ちます。 СтэкStackTraceconvertStringToIntStackTraceparseIntIntegerStackTraceStackTraceStackTrace
Exception in thread "main" java.lang.NumberFormatException: null
	at java.base/java.lang.Integer.parseInt(Integer.java:614)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at com.example.task01.Test.convertStringToInt(Solution.java:10)
	at com.example.task01.Test.main(Solution.java:6)
エラーが発生する前、プログラムはメソッドの奥深くまで進みましたが、エラーが発生するとすぐに、すべてが逆の順序で起こり始めます。問題を説明する行が出力され (例の 1 番)、最後に追加された値 (先頭) が取得され、Стэк4 番目の値がコンソールに出力されます (例の 2 番)。問題はコードの 614 行目のクラスで発生し、この行、つまり同じクラスのIntegerメソッド (例では 3 番) の 770 行目を呼び出していることがわかります。この行は、追加すると 3 番になり、このクラス メソッドとなります。まだ私たちには見えませんが、プログラムの 10 行目 (例では 4 行目、追加時は 2 番目) にあるメソッドによってすでに呼び出されており、今度は6 行目 (5 行目) で呼び出されています。この例では 1 つ目、追加する場合は 1 つ目)。したがって、呼び出されたメソッドを段階的に保存することで、正確にエラーにつながった情報の並列出力に戻ることができました。しかし、これはエラーを処理するだけでなく、アプリケーションのプロセスに関する多くの興味深い情報を取得できるようになります。レベル 9 のメイン講義へのコメントでよく使われる別の例を見てみましょう。コードがあるので、プログラムのプロセスを視覚化した画像をすぐに添付します。 parseIntСтэкIntegerconvertStringToIntmainСтекmainStackTrace
public class Test {
    public static void main(String[] args) {
        method1();
        method2();
    }
    public static void method1() {
        //не вызывает ничего
    }
    public static void method2() {
        method3();
        method4();
    }
    public static void method3() {
        //не вызывает ничего
    }
    public static void method4() {
        method5();
    }
    public static void method5() {
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
        for (StackTraceElement element:stackTraceElements) {
            System.out.println(element.getMethodName());
        }
    }
}
スタックトレースとそれを使って食べるもの - 2 ここで、プログラムは完璧に仕事を終えて終了します。これはコンソール出力に表示される内容です。
getStackTrace
method5
method4
method2
main

Process finished with exit code 0
この結論はどのようにして得られたのでしょうか?また、20 行目から始まる 5 番目の方法では何が起こったのでしょうか? 申し訳ありませんが、コメントからユーザーKirillによる最も人気のある説明 (省略) を講義に追加するのがせいぜいです。作成行に戻ってStackTrace、要素ごとに分析してみましょう。
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement[]- 配列の型を示します (初期レベルでは、int[]、String[] などの配列についてすでに学習しましたが、ここでも同じです)。 stackTraceElements- 一般的な命名規則を考慮して、配列の名前は何でも構いません。これは作業には影響しません。 Thread.currentThread()- 追跡したいメソッドが実行されている現在のスレッドへのリンクを取得します (今のところ、これは重要ではありません。Java コア クエストのレベル 16 でスレッドをより詳細に分析します) getStackTrace()- 呼び出されたすべてのСтэкメソッドを取得します (これは の通常のゲッターですStackTrace) 次に、作成された配列が何に役立つかを見てみましょう。配列には実行されたメソッドに関する情報が格納されることがわかりました。(c) このために、21 行目で、forと呼ばれる変更されたサイクルを起動forEachし (ちなみに、このサイクルをまだ学習していない人は、それについて読むことをお勧めします)、配列からコンソールにデータを出力します。つまり、コンストラクションを使用した作業中にどのメソッドが実行されたかに関する情報ですelement.getMethodName()注意してください、ご覧のとおり、配列のゼロ要素はそれぞれそれ自体であることが判明しましたgetStackTrace()。データ配列を受け取った時点では、それが実行された最後のメソッドであったため、最終的に先頭に来てСтэка、私たちの構築を覚えているからです。「後入れ先出し」は、配列のゼロ要素の下にすぐに最初に追加されます。他に得られるものは次のとおりですStackTraceElement。 String getClassName()- クラスの名前を返します。文字列getMethodName()- メソッドの名前を返します。文字列getFileName()- ファイル名を返します (1 つのファイルに多数のクラスが存在する可能性があります)。文字列getModuleName()- モジュール名を返します (null の場合もあります)。文字列getModuleVersion()- モジュールのバージョンを返します (null の場合もあります)。int getLineNumber()- メソッドが呼び出されたファイル内の行番号を返します。 一般的な動作原理は理解できたので、IdeStackTraceでさまざまな方法を自分で試してみることをお勧めします。すべてを完全にマスターできていなくても、学習を続ければ、この問題で私が得た結果と同じようにパズルが解けるはずです。皆さんの成功を祈っています!Ps この素材が気に入った場合は、「いいね!」でサポートしてください。それはあなたにとって難しいことではありません、私は満足しています。ありがとう、レベル 41 でお会いしましょう ;)
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION