1. 概要

実行されている現在のJavaメソッドの名前を知る必要がある場合があります。

この簡単な記事では、現在の実行スタックでメソッド名を取得するための簡単な方法をいくつか紹介します。

2. Java 9:Stack-Walking API

Java 9では、JVMスタックフレームを遅延効率的にトラバースするためのStack-Walking APIが導入されました。このAPIで現在実行中のメソッドを見つけるために、簡単なテストを作成できます。

public void givenJava9_whenWalkingTheStack_thenFindMethod() {
    StackWalker walker = StackWalker.getInstance();
    Optional<String> methodName = walker.walk(frames -> frames
      .findFirst()
      .map(StackWalker.StackFrame::getMethodName));

    assertTrue(methodName.isPresent());
    assertEquals("givenJava9_whenWalkingTheStack_thenFindMethod", methodName.get());
}

まず、 getInstance()factoryメソッドを使用してStackWalkerインスタンスを取得します。 次に、walk()メソッドを使用して、スタックフレームを上から下にトラバースします。

  • The 歩く() メソッドはスタックフレームのストリームを変換できます— ストリーム 何にでも
  • 指定されたストリームの最初の要素は、スタックの一番上のフレームです
  • スタックの一番上のフレームは、常に現在実行中のメソッドを表します

したがって、ストリームから最初の要素を取得すると、現在実行中のメソッドの詳細がわかります。 具体的には、 StackFrame.getMethodName()を使用してメソッド名を検索できます。

2.1. 利点

他のアプローチ(後で詳しく説明します)と比較すると、Stack-WalkingAPIにはいくつかの利点があります。

  • ダミーの匿名内部クラスインスタンスを作成する必要はありません— new Object()。getClass(){}
  • ダミーの例外を作成する必要はありません— new Throwable()
  • コストがかかる可能性があるスタックトレース全体を熱心にキャプチャする必要はありません

それどころか、 StackWalker は、スタックを1つずつ怠惰に歩くだけです。 この場合、すべてのフレームを熱心にキャプチャするスタックトレースアプローチとは対照的に、トップフレームのみをフェッチします。

つまり、Java 9以降を使用している場合は、Stack-WalkingAPIを使用してください。

3. getEnclosingMethodの使用

getEnclosingMethod() APIを使用して、実行されているメソッドの名前を見つけることができます。

public void givenObject_whenGetEnclosingMethod_thenFindMethod() {
    String methodName = new Object() {}
      .getClass()
      .getEnclosingMethod()
      .getName();
       
    assertEquals("givenObject_whenGetEnclosingMethod_thenFindMethod",
      methodName);
}

4. Throwableスタックトレースの使用

Throwable スタックトレースを使用すると、現在実行されているメソッドのスタックトレースが得られます。

public void givenThrowable_whenGetStacktrace_thenFindMethod() {
    StackTraceElement[] stackTrace = new Throwable().getStackTrace();
 
    assertEquals(
      "givenThrowable_whenGetStacktrace_thenFindMethod",
      stackTrace[0].getMethodName());
}

5. スレッドスタックトレースの使用

また、現在のスレッドのスタックトレース(JDK 1.5以降)には、通常、実行されているメソッドの名前が含まれています。

public void givenCurrentThread_whenGetStackTrace_thenFindMethod() {
    StackTraceElement[] stackTrace = Thread.currentThread()
      .getStackTrace();
 
    assertEquals(
      "givenCurrentThread_whenGetStackTrace_thenFindMethod",
      stackTrace[1].getMethodName()); 
}

ただし、このソリューションには1つの重大な欠点があることを覚えておく必要があります。 一部の仮想マシンは、1つ以上のスタックフレームをスキップする場合があります。 これは一般的ではありませんが、これが発生する可能性があることに注意する必要があります。

6. 結論

このチュートリアルでは、現在実行されているメソッドの名前を取得する方法の例をいくつか示しました。 例は、スタックトレースと getEnclosingMethod()に基づいています。

いつものように、GitHubでこの記事で提供されている例を確認できます。 また、Java 9の例は、 Java9GitHubモジュールで入手できます。