java - instalar - Comprensión de la búsqueda de fuentes de depuración de Eclipse con código cargado y compilado dinámicamente
windowbuilder eclipse (2)
Información de fondo:
Tengo este marco de Java que está destinado a ejecutar scripts externos. Para hacer esto, uso una combinación de un cargador de clases y el compilador java del sistema para compilar .java
"script" .java
que NO existen en la ruta de compilación de mi proyecto. Todo esto funciona, compilador de magia negra y todo.
La complicación inherente con el código cargado externamente es la dificultad para depurar. He abordado esto utilizando la función de depuración remota del tiempo de ejecución de Java.
Por lo tanto, tengo una configuración de depuración que se adjunta a mi archivo ejecutable, que tiene el directorio con los scripts de java externos en la ruta de búsqueda de origen. Esto realmente funcionó por un tiempo. En realidad, nunca funcionó correctamente, solo tuve scripts accidentalmente en mi ruta de compilación. Lo suficientemente confuso que puedo poner puntos de interrupción en los scripts, y el depurador realmente PARECE allí (número de línea consistente, -verbose:class
registro de -verbose:class
y todo). Sin embargo, entender cómo eclipse encuentra los archivos fuente es algo que podría ayudar. La mayoría de la documentación de eclipse se compone de manuales de usuario, después de todo.
Lo que sospeché fue que accidentalmente había duplicado ciertos archivos de script y, por lo tanto, confundí la búsqueda de origen con un archivo de origen desincronizado. Este no es el caso, ya que he eliminado los archivos duplicados y eclipse todavía no puede encontrar la fuente.
Lo que he intentado
- El doble, el triple, el cuádruple verificaron las rutas de búsqueda de origen asegurando que incluye cada directorio relevante
- subcarpetas de búsqueda habilitadas / deshabilitadas
- duplicados de búsqueda habilitados / inhabilitados
- utilizando una ruta absoluta al directorio en lugar de una ruta de espacio de trabajo relativa
Solución
La única solución aquí es agregar los archivos de script a la ruta de compilación del proyecto, lo cual es inaceptable para mí.
Lo que estoy haciendo ahora
Estoy avanzando lentamente por el repositorio de base de proyectos de código abierto Eclipse en busca de la respuesta. Eclipse, como resultado, es un proyecto bastante grande.
Pregunta
¿Puede alguien proporcionar una representación algorítmica precisa de cómo funciona la búsqueda de fuentes de Eclipse?
Sabiendo esto, posiblemente podría encontrar una manera de forzar al depurador de Eclipse a usar el camino correcto usando la reflexión. Por lo que sé, no hay ninguna limitación técnica que impida que el código compilado dinámicamente sea depurado. Lo sé porque mis puntos de interrupción están suspendiendo mis hilos como espero que lo hagan, el código fuente no parece querer cargar :(
Investigación relacionada: parece que esto podría estar relacionado con la forma en que se define la clase con una ubicación de CodeSource nula , pero aparentemente lo correcto a la hora de compilar dinámicamente el código en la memoria es dar el argumento nulo ... la pregunta sigue siendo cómo / Por qué esto es importante para el depurador del eclipse.
Actualización 4/22 3:30: Así que CodeSource
solución CodeSource
vinculada anteriormente. Ahora, estoy viendo que mi clase se está cargando desde la ubicación de ruta de archivo correcta con el conmutador -verbose:class
, pero la búsqueda de fuente sigue fallando. Los puntos de interrupción aún se capturan correctamente, pero me saludan con la Source not found
familiar que Source not found
letras rojas.
Actualizado 5/6 3:15: Perseguí la solución javap
discutida en la respuesta de Andrew. Resulta que, el atributo de archivo de origen en mi código de bytes .class coincide exactamente con un archivo que existiría en mi ruta de búsqueda de origen. Esto me confunde, porque esto sugiere que la jerarquía de carpetas influye en la búsqueda de fuentes. Sin embargo, he creado jerarquías de paquetes "fantasmas" que representan los paquetes "verdaderos" (como se definen en la parte superior de mis archivos .java) y muevo mis archivos de origen a esas carpetas, pero la búsqueda de origen sigue fallando cuando agrego esas rutas a mi ruta de búsqueda de origen. Cualquier información adicional sobre qué factores adicionales juegan en la búsqueda de fuentes sería enorme.
He tenido un problema similar pero menos complejo. Fue causado por el uso de dos compiladores diferentes. Usted escribió que usa el compilador java del sistema en su caso, asegúrese de que su Eclipse use el mismo JDK y que el compilador del sistema incluya información de depuración en las clases compiladas usando los parámetros -g: vars.
Tengo un poco de experiencia en esta área, después de haber trabajado en la depuración de scripts geniales compilados dinámicamente a través del JDT. Nunca conseguí que esto funcionara perfectamente, y creo que es principalmente una limitación del JDT, que nunca fue diseñado para manejar código compilado dinámicamente.
TLDR: Supongo que sus scripts compilados dinámicamente tienen un atributo de archivo de origen incorrecto en el código de byte. Este atributo se establece en el archivo de clase por el compilador. Ver https://en.wikipedia.org/wiki/Java_class_file
Creo que su confusión es que el depurador se detiene correctamente en los puntos de interrupción que estableció en los scripts, pero el IDE no puede cargar la fuente. Esto es confuso, por supuesto, pero hay una buena explicación para esto.
Los puntos de interrupción son realmente manejados por la máquina virtual y la máquina virtual los rastrea a través de un nombre completo y un número de línea. Esto permite que los puntos de interrupción se alcancen independientemente de qué cargador de clases cargue el archivo de clases, pero puede generar cierta confusión si se cargan múltiples archivos de clases a través de diferentes cargadores de clases con el mismo nombre calificado, pero con un código fuente diferente. Este algoritmo para determinar cuándo detener la máquina virtual no tiene nada que ver con buscar realmente el código fuente cuando la máquina virtual se detiene.
La búsqueda de código fuente es manejada por el IDE. Dado que incluso en el mundo compilado estáticamente, el nombre del archivo fuente puede no coincidir con el nombre de la clase (clases internas, clases anónimas, etc.). El nombre de la clase no se puede usar para buscar el archivo fuente.
Aquí hay una simplificación de lo que hace el IDE cuando se detiene en un punto de interrupción:
- Encuentra el archivo de clase en ese punto de ruptura
- Obtener el atributo fuente
- Encuentre un archivo de origen en la ruta de búsqueda de origen que coincida con el nombre del atributo de origen
- Utilice algunas heurísticas si se encuentran varios archivos de origen del mismo nombre (creo que esta sería la clasificación en la pestaña de búsqueda de origen)
- Devuelve el archivo fuente más apropiado.
(Advertencia, creo que el atributo de origen es solo el nombre simple del archivo de origen (es decir, sin directorio), así que creo que el IDE convierte el nombre del paquete a una estructura de directorio como parte de la búsqueda, pero podría estar equivocado al respecto ese).
Por lo tanto, la búsqueda fallará si su script compilado dinámicamente no tiene un atributo fuente adecuado. Puede verificar esta teoría mirando el código de byte. Tendrá que compilar de alguna manera un script y guardar los bits en el disco. Entonces puedes ejecutar javap -v myScript
en él. Apostaría que este es el problema. He visto esto suceder antes en otros lenguajes compilados dinámicamente.