J'ai la classe Java suivante
public class HelloWorld {
public static void main(String []args) {
}
}
Lorsque je compile ce fichier et exécute un sha256 sur le fichier de classe résultant, j'obtiens
9c8d09e27ea78319ddb85fcf4f8085aa7762b0ab36dc5ba5fd000dccb63960ff HelloWorld.class
Ensuite, j'ai modifié la classe et ajouté une ligne vierge comme celle-ci:
public class HelloWorld {
public static void main(String []args) {
}
}
Encore une fois, j'ai exécuté un sha256 sur la sortie en espérant obtenir le même résultat, mais à la place, j'ai
11f7ad3ad03eb9e0bb7bfa3b97bbe0f17d31194d8d92cc683cfbd7852e2d189f HelloWorld.class
J'ai lu sur cet article TutorialsPoint que:
Une ligne contenant uniquement des espaces blancs, éventuellement avec un commentaire, est connue comme une ligne vierge et Java l'ignore totalement.
Donc ma question est, puisque Java ignore les lignes vides, pourquoi le bytecode compilé est-il différent pour les deux programmes?
A savoir la différence en ce que dans HelloWorld.class
un 0x03
octet est remplacée par un 0x04
octet.
java
compilation
javac
bytecode
KNejad
la source
la source
Set
s immuables avec randomisation en interne, il pourrait produire un ordre différent à chaque exécution. Il pourrait également ajouter un attribut personnalisé contenant le temps de compilation. Et ainsi de suite…Réponses:
Fondamentalement, les numéros de ligne sont conservés pour le débogage, donc si vous modifiez votre code source comme vous l'avez fait, votre méthode démarre sur une ligne différente et la classe compilée reflète la différence.
la source
end-of-transmission
représente le code ASCII 4 etend-of-text
représente le code ASCII 3-g:none
indicateur lors de la compilation (ce qui supprime toutes les informations de débogage, voir ici ) et j'ai obtenu le même hachage dans les deux scénarios.Vous pouvez voir le changement en utilisant
javap -v
qui produira des informations détaillées. Comme d'autres déjà mentionnés, la différence sera dans les numéros de ligne:Plus précisément, le fichier de classe diffère dans la
LineNumberTable
section:la source
L'hypothèse que "Java ignore les lignes vierges" est fausse. Voici un extrait de code qui se comporte différemment selon le nombre de lignes vides avant la méthode
main
:S'il n'y a pas de lignes vides avant
main
, il s'imprime"foo"
, mais avec une ligne vide avantmain
, il s'imprime"bar"
.Étant donné que le comportement d'exécution est différent, les
.class
fichiers doivent être différents, quels que soient les horodatages ou autres métadonnées.Cela vaut pour chaque langue qui a accès aux cadres de pile avec des numéros de ligne, pas seulement pour Java.
Remarque: s'il est compilé avec
-g:none
(sans aucune information de débogage), les numéros de ligne ne seront pas inclus, serontgetLineNumber()
toujours renvoyés-1
et le programme s'imprimera toujours"bar"
, quel que soit le nombre de sauts de ligne.la source
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
.-1
était d'utiliser le-g:none
drapeau. Existe-t-il un autre moyen d'obtenir cette exception en utilisant l'ordinairejavac
?-g
option. Il y a aussi-g:vars
et-g:source
qui empêche la génération duLineNumberTable
.En plus des détails du numéro de ligne pour le débogage, votre manifeste peut également stocker l'heure et la date de génération. Ce sera naturellement différent à chaque compilation.
la source