2011-07-14 8 views
9

Básicamente tengo una declaración de registro dentro de un método. Siempre que se llame al método, quiero llamar fácilmente el nombre del método y anexarlo a la declaración de registro. Esto se hace para minimizar el número de líneas codificadas en mi aplicación. ¿Es posible hacerlo a bajo costo?¿Puedo llamar económicamente a un método de Java para obtener el nombre del método actual?

+1

No creo que haya un buen método que pueda usarse en tiempo de ejecución para hacerlo, pero probablemente podría anotar los métodos que necesitan esta funcionalidad y luego escribir un procesador de anotación que se incorpore en su proceso de compilación. En tiempo de ejecución funcionaría de manera casi idéntica a la codificación del nombre del método, pero en realidad no tendrías que codificar nada. –

+0

posible duplicado de [Obteniendo el nombre del método de ejecución actual] (http://stackoverflow.com/questions/442747/getting-the-name-of-the-current-executing-method) – bmargulies

Respuesta

15

No, no es barato. La forma costosa y única de hacerlo es con una llamada de método StackTrace. Lo mejor es solo codificarlo.

+0

Bueno, eso está muy mal. No sé por qué Java no puede hacer esto de manera barata todavía. –

+0

AspectJ fue diseñado para tratar problemas como este – antlersoft

+0

¿Cómo usaría AspectJ para hacer algo como esto? El método más cercano que puedo encontrar es "getSourceMethod()" –

3

Si solo necesita el nombre del método y el número de línea, puede hacerlo razonablemente rápido. En mi micro de referencia que puede hacer acerca de 120.000 llamadas por segundo:

public class A { 
    private static final int N = 1000000; 

    public static void main(String[] args) { 
    A a = new A(); 
    long l = System.currentTimeMillis(); 
    for (int i = 0; i < N; i++) { 
     a.test(0); 
     a.test(1); 
     a.test(2); 
    } 
    double time = (System.currentTimeMillis() - l)/1000d; 
    System.err.println(time + " seconds"); 
    System.err.println(N/time + " calls/second"); 
    } 

    String test(int i) { 
    StackTraceElement ste = Thread.currentThread().getStackTrace()[i]; 
    return ste.getMethodName() + ":" + ste.getLineNumber(); 
    } 
} 

también vemos this answer.

+0

'String test (int i) { StackTraceElement ste = Thread.currentThread(). getStackTrace() [i]; // String aString = "bleh"; // return aString; return ste.getMethodName(); }} 'Me corrió la prueba entre hacer un código permanente y haciendo StackTrace // // Con StackTrace 30.281 segundos //33024.00845414616 llamadas/segundo // segunda pasada //17.937 segundos // 55750 llamadas/segundo // Con cadena dura //0.016 segundos //6.25E7 llamadas/segundo --- Básicamente, un aumento de 100 veces el costo en comparación con un retorno de cadena codificado – TravMan

+0

Derecha. Pero todo depende de la frecuencia con que se llame a este código. Digamos, si lo llamas solo una vez por segundo, quizás puedas pagarlo. –

+0

¿Qué tal una anotación o algo por simplemente registrar el nombre del método actual, para poder cortar y pegar lo maldito sin cambiar la estúpida cadena una y otra vez? – ggb667

2

Por qué reinventar la rueda, java.util.logging.Logger utiliza

/** 
* Gets the StackTraceElement of the first class that is not this class. 
* That should be the initial caller of a logging method. 
* @return caller of the initial logging method or null if unknown. 
*/ 
private StackTraceElement getCallerStackFrame() 
{ 
Throwable t = new Throwable(); 
StackTraceElement[] stackTrace = t.getStackTrace(); 
int index = 0; 

// skip to stackentries until this class 
while(index < stackTrace.length 
    && !stackTrace[index].getClassName().equals(getClass().getName())) 
    index++; 

// skip the stackentries of this class 
while(index < stackTrace.length 
    && stackTrace[index].getClassName().equals(getClass().getName())) 
    index++; 

    return index < stackTrace.length ? stackTrace[index] : null; 
} 

dudo que lo conseguirá más rápido que esto.

[Editar] Para obtener el nombre de métodos de llamada utilización,

StackTraceElement caller = getCallerStackFrame(); 
String name = caller != null ? caller.getMethodName() : "<unknown>" 
+0

Esto usa StackTrace y requiere que use el registrador de Java. Está bien si estás haciendo pruebas en una aplicación pequeña en casa, pero según la prueba que se muestra a continuación, StackTrace es 100 veces más lento. – TravMan

+0

@TravMan Estoy de acuerdo, él acaba de pedir un método externo que podría llamar que devolvería el nombre del método de las personas que llaman, salvo que se codificara el nombre (y la reflexión [wooo bad] aparentemente), este método sería el más rápido. Sin embargo, 100 veces no tiene marco de referencia e imagino que todo esto es discutible y estamos persiguiendo al hada de la micro-optimización. – Andrew

+0

también upvoted, nunca usó la clase Logger así – TravMan

1

consideró usted escribir mensajes de registro sensibles en su lugar? Quiero decir, mensajes que simplemente le dicen al lector que inicie sesión la "historia" sobre cómo se ejecuta el código. mensajes que realmente difieren para diferentes métodos?

log4j: some.package.Class1: method1: checkpoint #1 
    log4j: some.package.Class1: method1: checkpoint #2 
    log4j: some.package.Class2: method2: checkpoint #1 
    log4j: some.package.Class2: method2: checkpoint #2 

estado golpeando mi cabeza en el registro como la de arriba solo una o dos semanas atrás (nombres de los métodos fueron codificados). No lo sentí notablemente más útil que no registrarlo en absoluto.

Cuestiones relacionadas