Dinámicamente obtener el número de línea actual

Hay una manera en Java, de forma dinámica, obtener el número de línea actual a través de la reflexión o de algunos impresionantes de la API? Al igual que cuando se producen excepciones, el número de línea que se imprime en el seguimiento de la pila como este:

at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:348)

Ahora hay una forma de impresión o de registro, como en el siguiente código?

log.error("Error in: " + this.getClass.getName() + "at line #"+ this.getClass.getActualLine());

Usted puede preguntar, ¿por qué no me basta con imprimir el número de línea? Bien porque el código puede obtener borrado o añadido antes de que el registro específico.error() llamada al método.

  • No PatternLayout de registro de la API es muy útil para esto?
  • Se podría crear una new Throwable y acceso a la pila de elementos traza. Consulte stackoverflow.com/questions/115008/…
  • usted no necesita un Throwable: Thread.getStackTrace() es suficiente.
  • hmmm, este devuelve -1 para el número de línea para mí …
  • tal vez su clase fue compilado sin información de depuración? Según el JavaDoc que sucede cuando «esa información no está disponible».
  • El Arrojadiza appraoch trabaja en el mismo lugar, sólo Thread.currentThread().getStackTrace() no …
  • Ah consiguió – los elementos de las matrices son diferentes ….

InformationsquelleAutor VSZM | 2013-07-04

5 Kommentare

  1. 10

    Era capaz de usar el Hilo.currentThread().getStackTrace() método para crear un conjunto de funciones que trabajan juntos para producir el número de línea de código que llama el primer método, así:

    /** @return The line number of the code that ran this method
     * @author Brian_Entei */
    public static int getLineNumber() {
        return ___8drrd3148796d_Xaf();
    }
    
    /** This methods name is ridiculous on purpose to prevent any other method
     * names in the stack trace from potentially matching this one.
     * 
     * @return The line number of the code that called the method that called
     *         this method(Should only be called by getLineNumber()).
     * @author Brian_Entei */
    private static int ___8drrd3148796d_Xaf() {
        boolean thisOne = false;
        int thisOneCountDown = 1;
        StackTraceElement[] elements = Thread.currentThread().getStackTrace();
        for(StackTraceElement element : elements) {
            String methodName = element.getMethodName();
            int lineNum = element.getLineNumber();
            if(thisOne && (thisOneCountDown == 0)) {
                return lineNum;
            } else if(thisOne) {
                thisOneCountDown--;
            }
            if(methodName.equals("___8drrd3148796d_Xaf")) {
                thisOne = true;
            }
        }
        return -1;
    }

    Espero que esto ayude! Pongo estas en una clase de utilidad para que los que están fuera del camino, pero todavía se puede acceder fácilmente. El segundo método es privado para evitar que cualquier otro método que no sea el primer método de llamada, de manera que siempre funciona correctamente.

    • Bueno, Este debería ser aceptada respuesta.
    • Parece que es ahora, woah. Me alegro de que funciona para los chicos.
  2. 41

    Puede crear un Arrojadiza y el uso de sus StackTraceElements:

      System.err.println(new Throwable().getStackTrace()[0].getLineNumber());

    Como @Joachim dijo, también puede utilizar Hilo.getStackTrace(), por ejemplo, como

      System.err.println(Thread.currentThread().getStackTrace()[1].getLineNumber());

    Ser conscientes de que el segundo método devuelve un poco diferente de la matriz – es necesario utilizar el elemento de array con índice 1 para obtener el actual número de línea, ya que incluye la llamada a getStackTrace() a sí mismo como el primer elemento.

    Nota también de los comentarios acerca de la Tala y el rendimiento de @Joaquín de la respuesta.

    • Se pueden obtener diferentes resultados en algunos de los Jvm. Al menos en la JVM de IBM para AIX la pila incluida la arrojadiza constructores. Ver getStackTrace del javadoc: The zeroth element of the array (assuming the array's length is non-zero) represents the top of the stack, which is the last method invocation in the sequence. Typically, this is the point at which this throwable was created and thrown. – normalmente, no se garantiza. Así Brian_Entei la solución es más resistente.
  3. 16

    Primero de todo: Si nada, a continuación, el registro de patrón (o layouter, o cualquiera que sea tu registro de llamadas del marco de trabajo que parte) debe hacer esto. El registrador de llamada en tu código debe sólo escribir el negocio real de la información. Información sobre el donde debe ser añadida por el registrador.

    Siguiente: conseguir que tipo de operación es costosa (en términos de tiempo), ya que Java no está optimizado para este. En tiempo de ejecución, la JVM necesidad de inspeccionar su estado, cargar o analizar la información de depuración y encontrar el número de línea correspondiente a una determinada instrucción. Es por eso que este tipo de información es por lo general sólo da cuando se produce una excepción (en cuyo caso ya tenemos un problema y saber que el tiempo empleado será generalmente la pena).

    Y por último pero no menos importante: si por alguna razón necesita que la información sobre su cuenta, puede utilizar Hilo.getStackTrace() e inspeccionar el segundo StackTraceElement en él.

  4. 2

    También se puede obtener el Excepción del número de la línea utilizando la siguiente fragmento de código. Utilice el siguiente util método en su util clase.

     public static int getExceptionLineNumber(Exception e, String methodNameExp) 
     {
        StackTraceElement ele = Arrays.stream(e.getStackTrace()).filter(o -> o.getMethodName().equals(methodNameExp)).findAny().orElse(null);
        if(ele != null){
            return ele.getLineNumber();
        }
        return -1;
     }

    De bloque catch puede llamar como la siguiente :

    catch (Exception e){
            logger.info("Exception line number "+ Util.getExceptionLineNumber(e, new Object(){}.getClass().getEnclosingMethod().getName()));
        }

    Espero que esto funcione! 🙂

  5. 2

    A partir de JDK9 puede utilizar el StackWalker.
    Esto me dio alrededor de un 50% de aumento de velocidad sobre el uso de getStackTrace().

    int get_line_number() {
        List<StackFrame> stack = StackWalker.getInstance(StackWalker.Option.SHOW_HIDDEN_FRAMES).walk((s) -> s.skip(1).collect(Collectors.toList()));
        return stack.get(0).getLineNumber();
    }

    Mi stream se podría hacer mejor, pero no tengo experiencia con ella, y en realidad no me gusta arroyos en general, así que siéntete libre de editar mi post para mejorar esta parte.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea