2010-07-28 7 views
6

D'une manière générale, un ensemble de code (le code client) est lié à un autre (le code API). La liaison Java est généralement vérifiée entre .java & .class au moment de la compilation ou entre .class & .class au moment de l'exécution. Cependant, dans ce dernier cas, la vérification se fait au fur et à mesure que de mauvaises références sont rencontrées (c'est-à-dire que c'est paresseux).Comment puis-je vérifier la liaison entre le code Java compilé?

Existe-t-il un moyen de forcer la vérification de tous les liens entre le code client et le code API à la fois avec le code compilé? Le but serait de vérifier que le code client fonctionnera avec la version donnée de l'API - même si elle a été compilée avec une autre.

(Bien sûr, une façon serait de décompiler et recompiler contre l'API, mais est-il une méthode plus directe?)

Répondre

0

Peut-être que vous pouvez exécuter des tests JUnit contre l'API spécifiée par un pot dans le classpath, puis changez simplement le pot pour différentes versions de l'API et recommencez les tests. Vous seriez capable d'automatiser cela facilement.

0

Il est possible d'analyser le code à partir de classes Java par réflexivité. Voir le paquet java.reflect. Certains outils d'analyse utilisent cette fonctionnalité pour obtenir des informations sur le code compilé. Le meilleur exemple est probablement FindBugs. Cette API a des limites, et je ne pense pas que vous puissiez faire ce que vous voulez avec. Si une dépendance est appelée dans une méthode, l'API reflect peut trouver la méthode, ses paramètres, mais ne peut pas vous fournir les fonctions dépendantes utilisées dans cette méthode. Je pense donc qu'un tel outil d'analyse n'existe pas en Java.

Une solution consiste à fournir une fois le code avec toutes ses dépendances. En développement, les outils de gestion du cycle de vie tels que Maven peuvent vous aider à gérer les dépendances de votre projet.

1

La vérification de la force des liens est difficile, en raison de la nature du langage et de l'implémentation de la JVM. Je crois que la justification de cette question est d'empêcher les erreurs de liaison au moment de l'exécution, et l'intention de le faire est très valable. Cependant, quand on regarde la cause des erreurs de couplage, du point de vue de la JVM, il est plus ou moins difficile d'effectuer une vérification avec force sans aucun impact sur les performances.

Les erreurs de liaison sont levées au moment de l'exécution, lorsque la JVM exécute le bytecode correspondant au method invocation instructions. C'est généralement à ce moment que le final pass of the JVM's bytecode verifier différé est lancé, ce qui peut entraîner des erreurs de liaison. Inutile de dire que c'est cher du point de vue de la performance.

(C'est mon hypothèse que) La plupart des projets (y compris les projets commerciaux) évitent ainsi la vérification forcée, et s'appuient plutôt sur des systèmes de gestion de construction et de dépendance pour éviter la douleur. Plus de commentaires dans this SO question; la réponse du choix du framework OSGi pourrait aider.

+0

Les performances ne sont pas nécessairement un problème majeur car le résultat peut être mémorisé. Dans certaines situations, la quantité de code ne sera pas nécessairement énorme. –

+1

Très bien, bien. Vous pouvez alors utiliser une bibliothèque d'ingénierie bytecode comme ASM (reportez-vous à l'utilisation de CheckClassAdapter) ou BCEL (qui contient le vérificateur JustIce) pour vérifier si elles sont suffisantes ou les étendre si nécessaire. Je ne suis pas sûr si Javassist a une caractéristique similaire. –

0

Pour ce dont vous avez besoin, vous pouvez utiliser un outil comme JarJarDiff [1] et obtenir les différences entre la nouvelle et l'ancienne version des jar API. Ensuite, la tâche est transformée pour vérifier que vous n'utilisez aucune des API incompatibles. Bien que non automatique, cette approche attire votre attention sur les changements et pas seulement sur la compatibilité binaire.

Si vous souhaitez simplement vérifier la compatibilité binaire, le plus simple est de recompiler le projet par rapport au nouveau fichier JAR.Un peu plus difficile (et beaucoup plus fragile) consiste à analyser le chemin de classe et invoquer chaque méthode de chaque classe, à la recherche d'exceptions de liaison. Notez que cette approche naïve ne testera pas tous les chemins possibles et offre peu d'avantages.

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

0

Prendre l'idée de this question et Alfresco Wiki, vous pouvez essayer -Xcomp de démarrer une machine virtuelle Java de test et précompiler les classes pour vérifier s'il y a une erreur de lien.

0

Je recommanderais d'utiliser un outil de type bytecode tel que asm pour «visiter» le code et demander à votre visiteur de surcharger visitMethodInsn. Ensuite, utilisez la réflexion sur la classe propriétaire à la recherche d'une méthode avec le nom et la signature indiqués. Vous aurez également besoin de regarder l'opcode de l'instruction d'invocation - il sera l'un des invokevirtual, invokeinterface, invokespecial et invokestatic. Note pour faire attention à la distinction entre invokevirtual et invokeinterface; un appel à invokevirtual non invoquer avec succès une méthode d'interface, et un appel à invokeinterface non appelez avec succès une méthode qui n'est pas définie sur une interface.