2010-07-28 6 views
6

En general, un conjunto de códigos (el código del cliente) se vincula con otro (el código API). El enlace de Java normalmente se verifica entre .java & .class en tiempo de compilación o entre .class & .class en tiempo de ejecución. Sin embargo, en este último caso la verificación es como y cuando se encuentran malas referencias (es decir, es flojo).¿Cómo puedo verificar la vinculación entre código Java compilado?

¿Hay alguna manera de forzar la verificación de todos los enlaces entre el código del cliente y el código API a la vez con el código compilado? El objetivo sería verificar que el código del cliente funcione con la versión dada de la API, incluso si se compiló con otra.

(Por supuesto, una forma sería la de descomponer y volver a compilar en contra de la API, pero ¿existe un método más directo?)

Respuesta

0

Tal vez se puede ejecutar pruebas junit en contra de la API especificada por un frasco en la ruta de clase, a continuación, simplemente cambie el contenedor para las diferentes versiones de la API y vuelva a ejecutar las pruebas. Podrías automatizar esto fácilmente.

0

Es posible analizar el código de las clases de Java por reflexividad. Vea el paquete java.reflect. Algunas herramientas de análisis usan esta funcionalidad para obtener información sobre el código compilado. El mejor ejemplo es probablemente FindBugs.

Esta API como límites, y no creo que pueda hacer lo que quiera con ella. Si se llama a una dependencia en un método, la API reflejada puede encontrar el método, sus parámetros, pero no puede darle las funciones dependientes usadas en ese método.

Creo que tal herramienta de análisis no existe en Java.

Una solución es proporcionar una vez que el código con todas sus dependencias. En desarrollo, las herramientas de administración del ciclo de vida como Maven pueden ayudarlo a administrar las dependencias de su proyecto.

1

La verificación forzada de enlaces es difícil, debido a la naturaleza del lenguaje y la implementación de la JVM.

Creo que la razón de esta pregunta es para evitar errores de vinculación en el tiempo de ejecución, y la intención de hacerlo es muy válida. Sin embargo, cuando uno mira la causa de los errores de enlace, desde el punto de vista de la JVM, entonces es más o menos difícil realizar la verificación con fuerza sin ningún impacto en el rendimiento.

Los errores de vinculación se producen en el tiempo de ejecución, cuando la JVM ejecuta bytecode correspondiente al method invocation instructions. Por lo general, en este momento se inicia el final pass of the JVM's bytecode verifier diferido, lo que podría ocasionar errores de enlace. Huelga decir que esto es costoso desde el punto de vista del rendimiento.

(Es mi suposición que) La mayoría de los proyectos (incluidos los comerciales) evitan la verificación forzada y, en cambio, dependen de los sistemas de administración de compilación y dependencia para evitar el dolor. Más comentarios en this SO question; la respuesta de elegir el marco OSGi podría ayudar.

+0

El rendimiento no es necesariamente un problema importante ya que se puede recordar el resultado. También en algunas situaciones, la cantidad de código no será necesariamente enorme. –

+1

Muy bien, bien. Es posible que desee utilizar una biblioteca de ingeniería de códigos de bytes como ASM (consulte el uso de CheckClassAdapter) o BCEL (que tiene el verificador JustIce en ella) para realizar la verificación si son suficientes o ampliarlos si es necesario. No estoy seguro si Javassist tiene alguna característica similar. –

0

Para lo que necesita, puede utilizar una herramienta como JarJarDiff [1] y obtener las diferencias entre la nueva versión y la anterior de los jar de API. Luego la tarea se transforma para verificar que no uses ninguna de las API incompatibles. Aunque no es automático, este enfoque llama su atención sobre los cambios y no solo sobre la compatibilidad binaria.

Si solo desea comprobar la compatibilidad binaria, lo más fácil es recompilar el proyecto con el nuevo JAR.Un poco más difícil (y mucho más frágil) es escanear el classpath y invocar cada método de cada clase, buscando excepciones de vinculación. Tenga en cuenta que este enfoque ingenuo no probará todos los caminos posibles y ofrece pocos beneficios.

[1] http://depfind.sourceforge.net/tasks/jarjardiff.html

0

Tomando la idea de this question y Alfresco Wiki, puede intentar -Xcomp para iniciar una JVM de prueba y precompilar las clases para comprobar si hay un error de enlace.

0

Recomendaría usar una herramienta de bytecode como asm para "visitar" el código, y hacer que su visitante sobrescriba visitMethodInsn. A continuación, utilice la reflexión sobre la clase de propietario buscando un método con el nombre y la firma indicados. También deberá consultar el código de operación de las instrucciones de invocación: será uno de invokevirtual, invokeinterface, invokespecial e invokestatic. Nota para prestar atención a la distinción entre invokevirtual e invokeinterface; una llamada a invokevirtual hará que no invoque con éxito un método de interfaz, y una llamada a invokeinterface no invocará con éxito un método que no está definido en una interfaz.

Cuestiones relacionadas