Java 9のStackWalker APIで特定のスタックフレームをスキップする方法
Java 9で導入されたStackWalker APIは、任意の時点における現在のスレッドのスタックトレースのスナップショットを取得し、それを順番に辿る(ウォークする)ためのメソッドを提供します。
Thread::getStackTrace()と比較したStackWalkerクラスの主な利点は以下のとおりです。
- 特定のクラスやスタックフレームをフィルタリング・スキップできる
- 宣言クラスのClassオブジェクト自体を直接取得できる
- 完全なスタックトレースを一括で取得するのではなく、短いスタックトレースかフルスタックトレースかを選択できる
以下の例では、java.util.stream.Stream.skip()メソッドを使用して、指定した数のスタックフレームをスキップしています。
コード例
import java.lang.StackWalker.*;
import java.util.Optional;
import java.util.List;
import java.util.stream.Collectors;
import java.lang.StackWalker.StackFrame;
public class StackWalkerSkipTest {
public static void main(String args[]) {
new StackWalkerSkipTest().stackWalk();
}
private class StackWalker4 {
public void stackWalk4() {
List<StackFrame> framesAfterSkip = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk((s) ->
s.skip(2).collect(Collectors.toList()));
System.out.println("Frames after skip : \n" + framesAfterSkip.toString());
}
}
public void stackWalk() {
new StackWalker1().stackWalk1();
}
private class StackWalker1 {
public void stackWalk1() {
new StackWalker2().stackWalk2();
}
}
private class StackWalker2 {
public void stackWalk2() {
new StackWalker3().stackWalk3();
}
}
private class StackWalker3 {
public void stackWalk3() {
new StackWalker4().stackWalk4();
}
}
}
実行結果
Frames after skip : [StackWalkerSkipTest$StackWalker2.stackWalk2(StackWalkerSkipTest.java:29), StackWalkerSkipTest$StackWalker1.stackWalk1(StackWalkerSkipTest.java:24), StackWalkerSkipTest.stackWalk(StackWalkerSkipTest.java:19), StackWalkerSkipTest.main(StackWalkerSkipTest.java:9)]
動作のポイント
この例では、内部クラスがmain → stackWalk → stackWalk1 → stackWalk2 → stackWalk3 → stackWalk4の順に呼び出されています。walk()メソッド内でs.skip(2)を実行すると、先頭の2フレーム(stackWalk4とstackWalk3)が除外され、stackWalk2以降のフレームのみがCollectors.toList()によってリストとして収集されます。実行結果を見ると、その通りになっていることが確認できます。
このようにStackWalkerはStream APIと組み合わせることで、不要なフレームの除去や条件に合致するフレームの抽出など、柔軟なスタックトレース操作が可能です。デバッグ、ロギング、セキュリティチェックなど、呼び出し元の情報が必要となる場面で特に役立ちます。
-
Javaで他のパッケージのクラスを使用する3つの方法
Javaで他のパッケージのクラスを利用する方法 Javaでは、関連するクラスをパッケージにまとめることでコードを整理できます。ここでは、payrollパッケージ内に定義されたBossクラスを例に、別のパッケージにあるクラスを利用する方法を解説します。 package payroll; public class Boss { public void payEmployee(Employee e) { e.mailCheck(); } } 上記のコードは、BossクラスとEmployeeクラスが同じpayrollパッケージに存在する場合の例です。しかし、もしEmpl
-
JavaでJSONをパース(解析)する方法|org.json・Gson・JsonPathの使い方を解説
このチュートリアルでは、JavaでJSONを解析(パース)する方法を、複数のライブラリの使い方とあわせて解説します。 JSONとは「JavaScript Object Notation」の略称で、JavaScriptのサブセットをベースとした軽量なデータ形式です。 データ交換フォーマットとして広く普及しており、Webプログラミングにおいて不可欠な技術となっています。本記事では、org.jsonライブラリを使ったJSONのパース方法を中心に紹介します。 まず基本をおさらいしましょう。JSONオブジェクトは「キーと値のペア」から構成される順序のない集合です。一方、JSON配列は値が順序付けて格納さ