2012-06-01 8 views
13

Escribo parte de una aplicación web PHP (que se utilizará en un concurso de búsqueda de errores de la escuela secundaria) donde el usuario debe encontrar errores en un programa Java determinado. Como parte de esto, cuando se ejecuta el programa Java, queremos resaltar las líneas del origen del programa Java donde se ejecutó el código. Para hacer esto, todo lo que necesitamos son los números de línea de la fuente que se han ejecutado, es decir, la ruta del código (¿o se llama cobertura de código?). Destacaremos las líneas en el archivo fuente usando los números de línea.Números de línea de registro del código java ejecutado

Utilizaremos el shell-exec() de PHP para ejecutar el programa Java y la herramienta para obtener la ruta del código (lo que sea que sea). ¿Cuál es la forma más fácil de obtener los números de línea de la ruta del código?

Muchas gracias!

Aquí está una imagen que describa lo que nos gustaría

enter image description here

Respuesta

0

usted podría conseguir un LineNumber si se compila el programa con la opción -g, hacer un printStackTrace(), capturar la salida de rastreo y extraer el número de lienzo desde allí.

4

PHP interperts el código, lo que significa que se ejecuta sobre la fuente cada vez que ejecuta el programa. Esto tiene la ventaja de explotar cuando se lee el código (lo que hace que las impresiones del número de línea sean triviales); sin embargo, a menudo es costoso en otras formas, ya que no se puede optimizar en profundidad (o hacer ninguna comprobación de error previa al tiempo de ejecución).

Java compiles its code into a JVM assembly language called "bytecode." Esto significa que lo que se está ejecutando generalmente no tiene acceso (o incluso usa) el código fuente. Dicho eso, hay técnicas. Una clase Java compilada tiene la capacidad de agregar "datos adicionales" y uno de esos "elementos de datos adicionales" es a line number table, que es un índice que permite que alguien ejecute el ensamblado para "buscar" el número de línea ya que el compilador lo registró.

En general, esto funciona bien, con las consideraciones que: compiladores a menudo no se marcan cada instrucción, el código fuente puede no estar disponible, la optimización puede hacer que ciertos trozos interiores de código no funciona de manera que facilite apuntando a la entrada código de texto.

cómo las herramientas de cobertura de código "arreglar" esto es que por lo general se insertan en el código (en el plano de montaje) un gran número de comandos que actúan efectivamente como declaraciones de registro en un formato que permite la herramienta para determinar cuál es el camino a través de la el código fue realmente seguido. Esto se correlaciona a través de la tabla de números de línea de la mejor manera posible y luego se usa para resaltar las líneas dentro del archivo fuente original.

Si quiere algo con una resolución más fina (algo que pueda procesar qué parte de una línea se ejecutó), entonces necesita profundizar más. Eventualmente, incluso podría considerar escribir su propio compilador (o extensión del compilador) que almacenará su propia tabla de números de líneas personalizadas que supera las deficiencias de las soluciones actuales.

Trucos como arrojar excepciones (como Shiven ha mencionado) y analizar el número de línea funcionan; sin embargo, contaminan su código con el procesamiento de excepción impar para los elementos que realmente no son excepcionales, solo para "obtener el número de línea". Debido al desorden del código y al rendimiento de las excepciones en el tiempo de ejecución generalmente más pobre, tiendo a evitar tales soluciones (pero funcionan).

De todos modos, con suerte esto le dará una visión de por qué no siempre funciona exactamente de la misma manera que PHP.

+0

Si realmente desea hacerse elegante con los números de línea _sin excepciones_ lanzando, puede escribir su propio 'ClassLoader' que podría proporcionarle una facilidad para obtener la tabla de números de línea; sin embargo, es posible que también necesite escribir su propia extensión en 'Thread' para tener una interfaz utilizable con la instrucción actual de bytecode de JVM. Es factible, ya que el lanzamiento de excepciones ya lo hace por usted, pero es mucho trabajo para algo que generalmente no es necesario con un registro estructurado de manera diferente. –

+0

¡Gracias por esto! Entiendo la diferencia entre los lenguajes compilados e interpretados y sé que obtener los números de línea para Java ejecutado (o cualquier lenguaje compilado) no es exactamente trivial. He decidido ir con Cobertura para generar el informe. Nunca he usado una herramienta de cobertura de código antes, así que esto me tomará un tiempo descifrar. Vea el comentario debajo de esta publicación. La ayuda sería muy apreciada. ¡Muchas gracias! – DanB91

1

Eche un vistazo a Cobertura. Calcula la cobertura y cosas así, y si aún no lo hace, debería ser relativamente fácil agregar el número de línea que se recopila. Hay un intento de hackeo para hacer eso, pero es tan lento que no podrá usarlo en producción https://bitbucket.org/jowu/myriapod/wiki/Home

+0

He estado echando un vistazo a la cobertura y parece hacer lo que quiero que haga. Los números de línea que queremos están en un archivo xml para que podamos analizarlo. Pero me es muy difícil hacer que ejecute el programa Java a través de la línea de comandos. Entonces, ¿la orden de generar la ruta del código para instrumentar, ejecutar y luego informar? Intento esto y genera la ruta del código, pero muestra que el programa nunca se ejecutó (todas las líneas son rojas). ¿Cuáles son los pasos para generar esto? – DanB91

+0

Solo puedo indicarle la documentación de cobertura para esto: http://cobertura.sourceforge.net/introduction.html. Puede que tenga que volver a compilar/reconstruir su proyecto cada vez que intente instrumentarlo y falla, pero más allá de eso, nunca tuve problemas para lograr este trabajo y su pregunta no contiene suficiente información para ayudarme a descubrir qué podría estar faltando. . – Jochen

0

Nunca he visto o visto algo así, pero parece ser un problema interesante. Mi idea sería usar the java debugger (jdb) para ejecutar el código, en lugar de solo el comando java.

Puede recorrer el código línea por línea (a través del comando step en jdb) y cada vez que se ejecuta una línea, su número de línea es escupido. Esto requeriría un poco de ayuda del lado de PHP (tendría que analizar el número de línea y ejecutar el siguiente paso) pero los números de línea están ahí. Aquí hay un resultado de muestra de un programa java muy básico.

Java (TestClass.java)

public class TestClass { 
    public static void main(String[] args) { 
     System.out.println("foo"); 
     System.out.println("bar"); 
    } 
} 

jdb (jdb TestClass después de ejecutar javac TestClass.java)

Initializing jdb ... 
> stop at TestClass:3 
Deferring breakpoint TestClass:3. 
It will be set after the class is loaded. 
> run 
run TestClass 
Set uncaught java.lang.Throwable 
Set deferred uncaught java.lang.Throwable 
> 
VM Started: Set deferred breakpoint TestClass:3 

Breakpoint hit: "thread=main", TestClass.main(), line=3 bci=0 
3   System.out.println("foo"); 

main[1] step 
> foo 

Step completed: "thread=main", TestClass.main(), line=4 bci=8 
4   System.out.println("bar"); 

main[1] step 
> bar 

Step completed: "thread=main", TestClass.main(), line=5 bci=16 
5  } 

main[1] step 
> 
The application exited 
0

Try refiriéndose a este enlace JVMDI

Puede intente acceder los valores del contador del programa y luego mapearlo en la líneaNumberTable. O Creo que JVMDI tiene un método que puede acceder al número de línea del código de ejecución. No estoy seguro de esto último, consulte el enlace de arriba y espero que ayude.

Cuestiones relacionadas