[java] 현재 실행중인 메소드의 이름 얻기

Java로 현재 실행중인 메소드의 이름을 얻는 방법이 있습니까?



답변

Thread.currentThread().getStackTrace()일반적으로 호출하는 메소드를 포함하지만 함정이 있습니다 ( Javadoc 참조 ).

일부 가상 머신은 경우에 따라 스택 추적에서 하나 이상의 스택 프레임을 생략 할 수 있습니다. 극단적 인 경우,이 스레드에 관한 스택 추적 정보가없는 가상 머신은이 메소드에서 길이가 0 인 배열을 리턴 할 수 있습니다.


답변

기술적으로 이것은 작동합니다 …

String name = new Object(){}.getClass().getEnclosingMethod().getName();

그러나 컴파일 시간 동안 새로운 익명의 내부 클래스가 만들어집니다 (예 🙂 YourClass$1.class. 따라서이 .class트릭을 배포하는 각 방법에 대한 파일 이 생성됩니다 . 또한 런타임 동안 호출 할 때마다 사용하지 않는 객체 인스턴스가 생성됩니다. 따라서 이것은 허용 가능한 디버그 트릭 일 수 있지만 상당한 오버 헤드가 있습니다.

이 트릭의 장점은 주석 및 매개 변수 이름을 포함하여 메소드의 다른 모든 정보를 검색하는 데 사용할 수있는 getEncosingMethod()리턴 java.lang.reflect.Method입니다. 이를 통해 동일한 이름을 가진 특정 메소드 (방법 과부하)를 구별 할 수 있습니다.

getEnclosingMethod()이 속임수 의 JavaDoc에 따르면 SecurityException동일한 클래스 로더를 사용하여 내부 클래스를로드해야하므로 as를 던져서는 안됩니다. 따라서 보안 관리자가 있어도 액세스 조건을 확인할 필요가 없습니다.

getEnclosingConstructor()생성자 에 사용해야 합니다. (명명 된) 메소드 외부의 블록 중에는을 getEnclosingMethod()리턴합니다 null.


답변

2009 년 1 월 : @Bombe의주의 사항 을 염두에두고
전체 코드를 작성합니다 .

/**
 * Get the method name for a depth in call stack. <br />
 * Utility function
 * @param depth depth in the call stack (0 means current method, 1 means call method, ...)
 * @return method name
 */
public static String getMethodName(final int depth)
{
  final StackTraceElement[] ste = Thread.currentThread().getStackTrace();

  //System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
  // return ste[ste.length - depth].getMethodName();  //Wrong, fails for depth = 0
  return ste[ste.length - 1 - depth].getMethodName(); //Thank you Tom Tresansky
}

이 질문에 더 많은 .

2011 년 12 월 업데이트 :

푸른 의견 :

JRE 6을 사용하고 잘못된 메소드 이름을 제공합니다.
내가 쓰면 작동ste[2 + depth].getMethodName().

  • 0입니다 getStackTrace(),
  • 1이다 getMethodName(int depth)
  • 2 메소드를 호출합니다.

virgo47답변 ( 공개됨 )은 실제로 메소드 이름을 다시 얻기 위해 적용 할 올바른 색인을 계산합니다.


답변

이 코드를 사용하여 스택 추적 인덱스의 잠재적 변동성을 완화했습니다. 이제 methodName util을 호출하면됩니다.

public class MethodNameTest {
    private static final int CLIENT_CODE_STACK_INDEX;

    static {
        // Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
        int i = 0;
        for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
            i++;
            if (ste.getClassName().equals(MethodNameTest.class.getName())) {
                break;
            }
        }
        CLIENT_CODE_STACK_INDEX = i;
    }

    public static void main(String[] args) {
        System.out.println("methodName() = " + methodName());
        System.out.println("CLIENT_CODE_STACK_INDEX = " + CLIENT_CODE_STACK_INDEX);
    }

    public static String methodName() {
        return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
    }
}

오버 엔지니어링 된 것 같지만 JDK 1.5의 고정 번호가 있었고 JDK 1.6으로 옮길 때 약간 바뀌 었다는 것이 약간 놀랐습니다. 이제는 Java 6/7에서 동일하지만 결코 알 수 없습니다. 런타임 동안 해당 인덱스의 변경을 증명하는 것은 아니지만 HotSpot이 그렇게 나쁘지 않기를 바랍니다. 🙂


답변

 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

name의 값은 foo입니다.


답변

이 두 가지 옵션 모두 Java에서 작동합니다.

new Object(){}.getClass().getEnclosingMethod().getName()

또는:

Thread.currentThread().getStackTrace()[1].getMethodName()


답변

내가 찾은 가장 빠른 방법 은 다음과 같습니다.

import java.lang.reflect.Method;

public class TraceHelper {
    // save it static to have it available on every call
    private static Method m;

    static {
        try {
            m = Throwable.class.getDeclaredMethod("getStackTraceElement",
                    int.class);
            m.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getMethodName(final int depth) {
        try {
            StackTraceElement element = (StackTraceElement) m.invoke(
                    new Throwable(), depth + 1);
            return element.getMethodName();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

원시 메소드 getStackTraceElement (int depth)에 직접 액세스합니다. 그리고 접근 가능한 메소드를 정적 변수에 저장합니다.