2012-03-29 5 views
6

Momentan sind wir dabei, unser gesamtes Build-System für ein großes Projekt (etwa 2000 Quelldateien) neu zu schreiben, und es wurde von einem binären Vergleich der Dateien gesprochen, um sicherzustellen, dass alles korrekt ist folgende Frage: Ist die Ausgabe von javac garantiert, dass sie bei Kompilationen gleich ist oder könnte sie sich ändern?Ist die von javac generierte Klassendatei immer gleich?

Another question implizierten, dass der Konstanten-Pool eine andere Reihenfolge haben könnte, aber unter der Annahme, die wir für die Reihenfolge der Dateien gehen in den javac Anruf wird es noch ein Potential für Unterschiede zu steuern, sind in der Lage? Wir verwenden Ant und Maven als Teil des Builds, wenn dies auch die Dinge beeinflussen könnte.

+2

Nicht garantiert. In der Praxis wäre es wahrscheinlich identisch, wenn Sie den identischen Compiler und die JAR-Struktur zur Kompilierung verwenden, aber selbst geringfügige Änderungen an der JAR-Reihenfolge usw. könnten den Applecart stören. –

+0

Würden Ihre Tests nicht die * funktionale * Äquivalenz gewährleisten, worüber Sie eigentlich besorgt sind? Auf jeden Fall, warum nicht einfach versuchen und sehen, was passiert? Wenn Sie feststellen, dass der Inhalt neu geordnet wurde, müssen Sie eine Byte-Code-Analyse durchführen, um festzustellen, ob sie trotzdem Byte-Code-äquivalent sind. –

+0

Wundern Sie sich wirklich, warum sollten Sie einen binären Vergleich der gebauten Klassen machen müssen? –

Antwort

3

Der Bytecode ist absolut nicht garantiert identisch zu sein; Zum einen dürfen Compiler Optimierungen durchführen, die keine garantierten Verhaltensweisen beeinflussen. Die Java-Sprachspezifikation erwähnt sogar an einigen Stellen Optimierungen, die ein Compiler durchführen könnte; beispielsweise der Zeichenfolge Verkettungsoperator + stellt sie fest, dass:

Eine Implementierung zu vermeiden, in einem Schritt Umwandlung und Verkettung auszuführen erstellen und dann Verwerfen eines Zwischen String Objekt kann wählen. Um die Leistung der wiederholten Zeichenfolgenverkettung zu erhöhen, kann ein Java-Compiler die StringBuffer-Klasse oder eine ähnliche Technik verwenden, um die Anzahl der zwischen String Objekte zu reduzieren, die durch Auswertung eines Ausdrucks erstellt werden.

[link]

0

Ich bin kein Experte für den Compiler, aber ich neige dazu, den anderen Antworten zu glauben, dass der binäre Vergleich nicht 100% zuverlässig ist.

Ich würde eine andere Alternative in Betracht ziehen: Sie sollten in der Lage sein, die Artefakte Ihres Build-Systems zu überprüfen (.jars & .wars, etc.) und sicherzustellen, dass jeder den erwarteten Inhalt und sogar die Größe jeder Datei haben ist in einer ziemlich engen Toleranz.

Wenn Ihr Build-Skript Quelle erzeugt und kompiliert, dann sollten Sie Vergleiche mit der generierten Quelle durchführen können, die würde 100% stabil von Build zu Build sein. (Oder zumindest vorhersehbar).

Hoffe, das hilft!

0

Die einzige Möglichkeit, die Dateien, dann tun die schwere Arbeit, herauszufinden, Unterschiede aufgrund der ständigen Pool, um Änderungen zu gewährleisten Gleichwertigkeit einer der verschiedenen Klassendatei-Parser zu erhalten ist, zu analysieren, usw. Das Hauptproblem besteht darin, dass die Neuordnung des Konstantenpools numerische Werte ändert, die auf die Konstanten verweisen, von denen sich einige in Tabellenelementen befinden, von denen sich einige in Bytecodes befinden. Doable, aber definitiv nicht-trivial und vermutlich nicht praktisch, es sei denn, Sie haben bereits das meiste des Rahmens aus irgendeinem anderen Grund (wie Bytecodeänderung).

Verwandte Themen