Gráfico de dependencia del código fuente de Java

Bueno, antes que nada, esto podría ser potencialmente estúpido y loco.

Estoy tratando de construir (o usar, si ya existe uno) un marco, que toma una cantidad de archivos fuente de Java y genera la forma en que estos archivos interactúan; por ejemplo, file1.java podría importar archivo2.java; file2.java podría llamar a un estático método de file3.java. Idealmente, sería genial si esto pudiera hacerse sin compilar o ejecutar el conjunto de archivos. Conozco la API de Reflection que me permite explorar las partes de una clase, pero ¿es eso lo que estoy buscando?

Además, ¿qué tan difícil es extender esto a otros idiomas, por ejemplo, Python o Lisp (agregue cualquier otro idioma aquí)?

No estaba muy seguro de cómo construir el título de la pregunta, así que si algo como esto se ha preguntado antes, me encantaría que pudiera vincularme a esa pregunta.

preguntado el 04 de julio de 12 a las 04:07

Técnicamente, no importa archivos: el compilador simplemente usa la importación para resolver nombres de clase completos cuando se usan nombres de clase no completos. -

A través de la reflexión, puede ver los campos en una clase, los argumentos y los tipos de retorno de los métodos, pero la reflexión no le dirá nada sobre las clases que se usan. dentro de un método. -

Echa un vistazo a la fuente de OpenJDK? Creo que estás haciendo algo que el compilador ya está haciendo. -

Debería haber una variedad de herramientas UML que puedan hacer algo parecido. Mostrarían qué objetos están relacionados, no archivos, pero Java tiene un acoplamiento bastante cercano entre los dos, por lo que el gráfico de dependencia de UML lo acercará. -

@GregKopff Sí, tenía en mente la misma limitación de reflexión. -

3 Respuestas

actualmente estoy trabajando en un proyecto, la función principal es muy similar a la que mencionaste, y uso javaparser: http://code.google.com/p/javaparser/

javaparser es muy poderoso, puede ayudarnos mucho en el análisis del código fuente, pero es muy difícil obtener las dependencias completas y las interacciones de clases, incluso si uso javaparser.

Por ejemplo: si desea obtener todas las dependencias de una clase, el enfoque más directo es obtener el área de "importación" del código fuente; esto es muy fácil usando javaparser.

Pero solo la "importación" no es suficiente, si la clase - ClassA - que está analizando actualmente se llama una clase - ClassB - que está en el mismo paquete con ClassA, entonces ClassB no aparecerá en el área de importación.

Entonces, en esta situación, no podemos obtener la dependencia ClassB.

Y para la interacción de clases, si no puede obtener al 100% las dependencias correctas de una clase, entonces no puede conocer al 100% la interacción correcta entre clases.

Pero de todos modos, hasta ahora, javaparser es la herramienta de análisis de código fuente de Java más poderosa y útil que puedo encontrar.

Respondido el 20 de Septiembre de 12 a las 15:09

OK, sugeriría usar: ANTLR (antlr.org) esta vez. ANTLR es la mejor solución para analizar y procesar lenguajes de programación. - as.yin

Usted ha hecho dos preguntas e intentaré responder a la primera. Creo que está haciendo algún tipo de análisis de origen de los archivos Java para ver cómo podrían interactuar entre sí (al menos eso es lo que entendí). Básicamente, para hacer esto, debe actuar un poco como el IDE de Eclipse. Escanear el código fuente en cada archivo .java y construir estructuras de datos de palabras y construcciones reservadas de Java. Una vez que se haya analizado cada archivo .java, puede proceder a descubrir los vínculos entre ellos.

ex.

  1. Almacenar el nombre del paquete de la clase y su nombre y su alcance
  2. Almacene un HashMap de todas las variables declaradas, sus valores y su alcance
  3. Descubra los métodos en el archivo fuente y almacene sus nombres, parámetros de entrada y salida y alcance

También puede hacer mucho más y para detectar estas construcciones tendría que escribir su propio analizador (o encontrar algo en la red) y usar expresiones regulares para detectarlas. Los almacena en su programa y luego, una vez que se analizan todos los archivos fuente, puede comenzar a ver las interacciones.

ex.

El archivo fuente 1 está en el paquete xy y tiene 3 métodos públicos y 2 métodos de alcance del paquete. El archivo fuente 2 está en el paquete z y tiene 1 método público y 3 métodos privados.

Entonces puede concluir que el archivo 1 puede interactuar con el archivo 2 invocando ese 1 método público. Y puede hacer el mismo análisis para todos los archivos.

Respondido 04 Jul 12, 05:07

Esto suena interesante, pero no estoy seguro de cuán factible es. Probablemente esperaré más respuestas. - Gooner

Es 100% factible, aprendemos estas cosas en la universidad. Por lo general, el curso se conoce con el nombre de "construcción del compilador". Básicamente, está buscando codificar un analizador y analizar el código fuente y mapear cada parte de él. Luego, solo encuentra la conexión entre las asignaciones basadas en reglas. y esas reglas se definen en las especificaciones de JVM. - george_h

Si hay tiempo, podría escribirle un programa de muestra que haga lo que mencioné. Como algo realmente básico como prueba de concepto si dudas de la viabilidad de lo que estoy sugiriendo. - george_h

Sé que dijiste que preferirías no hacer la compilación, pero sería mucho más fácil revisar los archivos de clase. Entre el código de bytes y el grupo de constantes, puede obtener todo lo que necesita sin tener que recurrir esencialmente a reescribir javac. Use Apache BCEL y estará prácticamente allí. Obviamente, ninguna herramienta podrá encontrar las dependencias a las que se accede a través de la reflexión; para eso necesitaría hacer un análisis de tiempo de ejecución con un cargador de clases personalizado o algo así.

https://en.wikipedia.org/wiki/Java_class_file http://commons.apache.org/proper/commons-bcel/

contestado el 21 de mayo de 13 a las 18:05

Podría ser más fácil, pero también estaría mal. javac inserta constantes en los archivos fuente, lo que significa que puede tener A.java dependiendo de B.java, pero A.class sin referencias a B.class. - Laurence Gonsalves

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.