2010-07-28 6 views
6

Im Allgemeinen wird ein Code (der Client-Code) mit einem anderen (dem API-Code) verknüpft. Java-Verlinkung wird typischerweise zwischen .java & .class zur Kompilierungszeit oder zwischen .class & .class zur Laufzeit verifiziert. Im letzteren Fall wird jedoch überprüft, ob und wann schlechte Referenzen auftreten (d. H., Es ist faul).Wie kann ich die Verknüpfung zwischen kompiliertem Java-Code überprüfen?

Gibt es eine Möglichkeit, die Verifizierung von alle Links zwischen dem Client-Code und dem API-Code auf einmal mit kompiliertem Code zu erzwingen? Der Zweck wäre, zu verifizieren, dass der Client-Code mit der angegebenen Version der API funktioniert - obwohl sie gegen eine andere kompiliert wurde.

(Natürlich ein Weg wäre, gegen die API zu dekompilieren und neu kompilieren, aber gibt es eine direktere Methode?)

Antwort

0

Vielleicht können Sie JUnit-Tests gegen die API von einem Glas in der ClassPath angegeben laufen, dann schalte einfach das jar für verschiedene api-Versionen aus und führe die Tests erneut aus. Sie könnten dies leicht automatisieren.

0

Es ist möglich, Code aus Java-Klassen durch Reflexivität zu analysieren. Sehen Sie das Paket . Einige Analysetools verwenden diese Funktionalität, um Informationen über den kompilierten Code zu erhalten. Das beste Beispiel ist wahrscheinlich FindBugs.

Diese API als Grenzen, und ich glaube nicht, dass Sie damit tun können, was Sie wollen. Wenn eine Abhängigkeit in einer Methode aufgerufen wird, kann die reflect-API die Methode und ihre Parameter finden, kann jedoch nicht die abhängigen Funktionen angeben, die in dieser Methode verwendet werden.

Also ich denke, ein solches Analyse-Tool existiert nicht in Java.

Eine Lösung besteht darin, einmal den Code mit all seinen Abhängigkeiten bereitzustellen. In der Entwicklung können Lifecycle-Management-Tools wie Maven Ihnen helfen, die Abhängigkeiten Ihres Projekts zu verwalten.

1

Die Überprüfung der Links ist aufgrund der Art der Sprache und der Implementierung der JVM schwierig.

Ich glaube, das Grundprinzip für diese Frage ist, Verbindungsfehler zur Laufzeit zu verhindern, und die Absicht, dies zu tun, ist sehr gültig. Wenn man jedoch aus der Sicht der JVM die Ursache von Verknüpfungsfehlern betrachtet, ist es mehr oder weniger schwierig, eine Überprüfung ohne Leistungseinbußen durchzuführen.

Verbindungsfehler werden zur Laufzeit ausgelöst, wenn die JVM den Bytecode entsprechend method invocation instructions ausführt. Es ist in der Regel zu diesem Zeitpunkt, dass die zurückgestellte final pass of the JVM's bytecode verifier angeklickt wird, was zu Kopplungsfehlern führen könnte. Es ist unnötig zu sagen, dass dies unter dem Gesichtspunkt der Leistung teuer ist.

(Es ist meine Annahme, dass) Die meisten Projekte (einschließlich der kommerziellen) vermeiden daher erzwungene Verifikation, und stattdessen verlassen sich auf Build-und Abhängigkeits-Management-Systeme, um die Schmerzen zu vermeiden. Weitere Kommentare in this SO question; Die Antwort auf das OSGi-Framework könnte hilfreich sein.

+0

Leistung ist nicht unbedingt ein Hauptproblem, da das Ergebnis in Erinnerung bleiben kann. Auch in einigen Situationen wird die Menge an Code nicht unbedingt groß sein. –

+1

In Ordnung, gut. Sie könnten dann eine Bytecode-Engineering-Bibliothek wie ASM (siehe die Verwendung von CheckClassAdapter) oder BCEL (die den JustIce-Verifier enthält) verwenden, um die Verifizierung durchzuführen, falls sie ausreichend sind, oder sie bei Bedarf zu erweitern. Ich bin mir nicht sicher, ob Javassist eine ähnliche Funktion hat. –

0

Für was Sie brauchen, können Sie ein Werkzeug wie JarJarDiff [1] verwenden und die Unterschiede zwischen der neuen und der alten Version der API-Gläser erhalten. Anschließend wird die Aufgabe so geändert, dass überprüft wird, ob Sie eines der inkompatiblen APIs verwenden. Dieser Ansatz ist zwar nicht automatisch, macht Sie jedoch auf die Änderungen und nicht nur auf die Binärkompatibilität aufmerksam.

Wenn Sie nur die Binärkompatibilität überprüfen möchten, ist es am einfachsten, das Projekt gegen das neue JAR neu zu kompilieren.Etwas schwieriger (und viel spröder) ist es, den Klassenpfad zu durchsuchen und jede Methode jeder Klasse aufzurufen, um nach Verbindungsausnahmen zu suchen. Beachten Sie, dass dieser naive Ansatz nicht alle möglichen Pfade prüft und wenig Nutzen bietet.

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

0

nimmt die Idee von this question und Alfresco Wiki, können Sie -Xcomp versuchen, eine Test JVM zu starten und die Klassen vorkompilieren zu prüfen, ob ein Verbindungsfehler ist.

0

Ich würde empfehlen, ein Bytecode-Tool wie ASM zu verwenden, um den Code zu "besuchen", und Ihren Besucher überschreiben visitMethodInsn. Verwenden Sie dann die Reflektion für die Besitzerklasse, um nach einer Methode mit dem angegebenen Namen und der angegebenen Signatur zu suchen. Sie müssen auch den Opcode der Aufrufanweisung betrachten - er wird entweder invokevirtual, invokeinterface, invokespecial oder invokestatic sein. Beachten Sie die Unterscheidung zwischen invokevirtual und invokeinterface; Ein Aufruf von invokevirtual ruft nicht erfolgreich eine Schnittstellenmethode auf, und ein Aufruf von invokeinterface wird nicht erfolgreich eine Methode aufrufen, die nicht auf einer Schnittstelle definiert ist.