2010-02-17 17 views
34

Quiero que jdb (que estoy usando a través del depurador Eclipse) se rompa cuando a una variable se le asigna algún valor. No estoy interesado en establecer un punto de interrupción en una línea específica, sino de manera más general.Interrumpir cuando a una variable se le asigna algún valor

Por ejemplo, rompa cada vez x == nulo.

¿Se puede lograr esto?

+0

Lo que está buscando es algo así como [detector de cambios de propiedad] (http://docs.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html) que le permite detectar un cambio específico y captura el rastro de la pila No creo que esto esté disponible en ningún depurador aún, y será difícil de implementar si los desarrolladores originales de la biblioteca no lo convirtieron en una propiedad. – Cebence

Respuesta

5

Sí, los que son llamados puntos de observación y puntos de observación puede tener expresiones reloj.

Dependiendo de las versiones, haga esto seleccionando una variable en la vista de Esquema y haciendo clic derecho sobre ella, o en la vista de Variables, controle/haga clic en ella.

Un menú contextual tendrá opciones para Agregar inspección Expresión y Modificar inspección Expresión.

+0

He estado jugando con puntos de observación pero no parecen ser afectados a menos que defina el punto de observación cuando la variable está dentro del alcance. ¿Puedo definir un punto de observación y hacer que se active cuando la variable observada entre en el alcance? ¿Hay alguna manera de calificar los nombres de las variables observadas? – Daniel

+0

Esto no parece permitir que solo se rompa cuando se encuentra un valor específico. – mjaggard

31

Sí - Lo que necesita configurar es 'Punto de interrupción condicional' - esto le da la capacidad de detener la ejecución del programa y pasar por el depurador cuando se alcanza un cierto estado de la aplicación.

Por lo tanto, digamos que usted quiere saltar a un punto particular en la ejecución cuando se cumple una determinada condición (según la imagen adjunta), puede hacerlo de la siguiente manera:

  1. Abra el depurador en perspectiva y seleccionar los puntos de ruptura '' pestaña

  2. Añadir un nuevo punto de interrupción en el archivo de código - en el lugar apropiado donde le gustaría observar la ejecución del programa

  3. A continuación, volver a la pestaña 'puntos de ruptura', haga clic en la entrada que acaba de agregar y seleccione 'Breakpoint Properties'

  4. Establecer la condición sobre la cual debe ser activado

alt text

+5

Hola Diunk, ¿No es su sugerencia depende de la condición que se satisface en un número de línea particular? Me gustaría una solución más general que anule la necesidad de identificar los números de línea. Solo quiero saber cuándo se le asigna algo a "x", independientemente del método en el que se lleve a cabo la tarea. – Daniel

+0

Hola Daniel, Sus preguntas indican que cada vez que "x" (una variable) se establece en un determinado valor, desea que se rompa el flujo de control. La pregunta es, ¿dónde? Bueno, si lo piensas, "x" tiene que ser una instancia o variable local. En ambos contextos, usted sabría exactamente qué línea de su fuente desea observar, ¿no es así? (el colocador, o el alcance del bloque local). A partir de ese momento, llama y mira la pila de llamadas y retrocede. – Dinuk

+3

Hola Diunk, En realidad estaba tratando de resolver un problema en una biblioteca que no es mía. La variable está protegida y existe una jerarquía de tipos razonablemente grande que extiende la clase base donde está definida. El acceso podría estar en muchos lugares, por lo que quería un punto de interrupción libre de contexto. Parece que thSoft y DigitalRoss son correctos en su sugerencia. – Daniel

0

Lo sentimos, pero no hay manera de hacer lo que desee en Eclipse. Lo que necesita es un punto de observación con la expresión condicional de un punto de interrupción. No existe en Eclipse.

Su problema también es la depuración específica de una biblioteca. Probablemente haya otras maneras de lograr lo que necesita. Busque en el foro para ver cómo lo hacen los desarrolladores.

8

Puede acercarse bastante con Field Modification Watchpoints. Están limitados a colocarse en campos de objetos (no variables locales, parámetros o expresiones) y se activan cada vez que se escribe el campo, pero es lo más cercano que Eclipse tiene a lo que desea.

+0

1 Pero aviso: además de estar restringido a los campos (que parece estar bien con el requisito de OP), se disparará no exactamente cuando _cambia_ pero cuando está _ escrito_ (incluso cuando está escrito con el mismo valor anterior). – leonbloy

9

Editar: The ticket I've linked in this answer ha sido marcado verificado/reparado. Se ha integrado en la última versión de Oxygen, as detailed in the release notes.Dejaré mi respuesta original a continuación, ya que contiene mucha información útil sobre cómo JDI y JDT trabajan juntos en Eclipse.


Voy a comenzar con la respuesta final a la pregunta por lo que no tiene que leer los detalles si usted no desea. Básicamente, esto es posible pero con muchas preguntas que deben ser respondidas primero. Si desea omitir eso e ir directamente al boleto, here you go, pero le recomiendo que siga leyendo.

Eclipse usa JDI (en la parte inferior de la página) para registrar los puntos de observación con la JVM. Esto se hace a través de los métodos EventRequestManager (la implementación es proporcionada por la propia JVM, no por Eclipse) que crean puntos de observación, es decir, EventRequstManager.createModificationWatchpointRequest. Lo único que aceptan estos métodos es un Field (tenga en cuenta que esta no es la clase reflectante Field). En resumen, Eclipse no puede hacerlo directamente a través de Java. No temas, Java tampoco maneja puntos de interrupción condicionales. Esos también se implementan a través de Eclipse directamente en lugar de depender de Java. Sin embargo, hay algunas advertencias que hacen que los puntos de observación condicionales sean mucho más difíciles de implementar que los puntos de interrupción condicionales.

Consideremos los puntos de interrupción condicionales y simples. Para que funcionen, necesitas un contexto en el que puedas ejecutar el fragmento de código. Sin un contexto de ejecución para el código, no podemos evaluar la expresión/declaraciones en el fragmento porque no tenemos forma de resolver variables, valores, tipos, etc. Esto se hace usando un analizador AST que procesa el código de Java en instrucciones reales . Recuerde que puede escribir un número de declaraciones en una condición, no solo una sola expresión. El evaluador luego utiliza un contexto (específicamente, un IJavaStackFrame) para evaluar la expresión en sí misma después de analizarla.

Ahora piense en un punto de observación condicional, porque ese último punto es muy importante. ¿Cuál es el contexto de ejecución de un punto de observación? El acceso variable puede ocurrir no solo dentro de la misma clase, sino también en otras clases (piense en protected y miembros del paquete), y también en clases internas (a través de MyClass.this.myField). Esto significa que:

  1. las variables locales nunca son consistentes ya que el campo se puede acceder desde múltiples métodos,
  2. las variables miembro de la clase de la cual el acceso se invoca nunca son consistentes ya que el campo se puede acceder desde múltiples clases,
  3. las clases importadas que están disponibles en el contexto de ejecución no son consistentes para la misma razón que (2), y
  4. el acceso del campo en sí nunca es constante, ya que puede requerir cualificación con una instancia, nombre de clase, super o con algo así como MyClass.this.myField (para acceso de clase interna).

La viabilidad de tal característica es algo limitada. Sería muy difícil evaluar realmente un enunciado condicional no cambiante para un punto de observación ya que absolutamente nada en el contexto de ejecución va a ser consistente. Esto significa que el código no puede ser fácilmente analiza y se interpreta sin significado especial aplicado a piezas del código, tales como:

myField es siempre la misma como this.myField o super.myField o MyClass.myField o MyClass.this.myField, dependiendo de donde el campo es siendo accedido

Esto complica bastante las cosas, especialmente en un sistema que ya es relativamente complejo. Se puede encontrar un ejemplo del código de punto de interrupción condicional here (busque getEvaluationEngine usando Ctrl + F). Ahora tome eso y agregue el procesamiento previo en la expresión en función de un conjunto de reglas sobre dónde estamos y dónde se encuentra el campo, y hacer las cosas puede ser complicado.

AFAIK, no puede hacer algo como "si el valor anterior/nuevo es esto, suspenda", porque esa información simplemente no está disponible en la información que puede obtener en el marco de pila (y por lo tanto depurador). La expresión que se asigna al valor se ha evaluado por el tiempo en que se golpea el punto de observación, pero su resultado no está disponible para el depurador, por lo tanto, no está disponible para un evaluador en el mismo punto de observación. Debería realizarse un paso primero para realizar la tarea, luego la expresión debería evaluarse después del paso. Sería horriblemente desordenado, y honestamente, bastante hacky en eso.

En cualquier caso, si desea expresar su apoyo a esta función, puede usar this Eclipse ticket. Sin embargo, ha existido desde 2005 (8 años a partir de ahora) y tiene un apoyo limitado de la comunidad. TBH, no veo que vaya muy lejos, especialmente sin una mayor clarificación de las expectativas detrás de este tipo de solicitud de funciones y sin una importante consideración de diseño puesta en primer lugar.

+0

creo que sería una buena característica. votado por él – tgkprog

+0

Exactamente el tipo de respuesta que estaba esperando. Gracias.No estoy seguro de si voy a votar o no, estoy de acuerdo, suena muy complejo, pero no debería ser complejo, así que supongo que la próxima pregunta es dónde está el informe de errores de Java. (Pero esa es una pregunta completamente sin sentido a menos que trabaje para Oracle porque los votos de la comunidad valen menos que cero para los mantenedores de Java actuales) – mjaggard

+0

@mjaggard Peor aún es que la base de datos de errores de Oracle es privada, y solo puede acceder si pagar por un contrato de soporte de Oracle. La base de datos de errores OpenJDK está abierta. – Brian

Cuestiones relacionadas