Eu tenho a seguinte classe Java
public class HelloWorld {
public static void main(String []args) {
}
}
Ao compilar esse arquivo e executar um sha256 no arquivo de classe resultante, recebo
9c8d09e27ea78319ddb85fcf4f8085aa7762b0ab36dc5ba5fd000dccb63960ff HelloWorld.class
Em seguida, modifiquei a classe e adicionei uma linha em branco como esta:
public class HelloWorld {
public static void main(String []args) {
}
}
Novamente, corri um sha256 na saída esperando obter o mesmo resultado, mas, em vez disso, obtive
11f7ad3ad03eb9e0bb7bfa3b97bbe0f17d31194d8d92cc683cfbd7852e2d189f HelloWorld.class
Eu li neste artigo do TutorialsPoint que:
Uma linha contendo apenas espaço em branco, possivelmente com um comentário, é conhecida como linha em branco e o Java a ignora totalmente.
Portanto, minha pergunta é: como o Java ignora linhas em branco, por que o código de código compilado é diferente para os dois programas?
Ou seja, a diferença de que em HelloWorld.class
um 0x03
byte é substituída por um 0x04
byte.
java
compilation
javac
bytecode
KNejad
fonte
fonte
Set
s imutáveis com randomização internamente, ele poderá produzir uma ordem diferente em cada execução. Também poderia adicionar um atributo personalizado contendo o tempo de compilação. E assim por diante ...Respostas:
Basicamente, os números de linha são mantidos para depuração; portanto, se você alterar seu código-fonte da maneira que fez, seu método inicia em uma linha diferente e a classe compilada reflete a diferença.
fonte
end-of-transmission
significa o código ASCII 4 eend-of-text
o código ASCII 3-g:none
sinalizador ao compilar (que remove todas as informações de depuração, veja aqui ) e obtive o mesmo hash nos dois cenários.Você pode ver a alteração usando o
javap -v
que produzirá informações detalhadas. Como outros já mencionados, a diferença estará nos números de linha:Mais precisamente, o arquivo de classe difere na
LineNumberTable
seção:fonte
A suposição de que "Java ignora linhas em branco" está errada. Aqui está um trecho de código que se comporta de maneira diferente, dependendo do número de linhas vazias antes do método
main
:Se não houver linhas vazias antes
main
, ela será impressa"foo"
, mas com uma linha vazia antesmain
, ela será impressa"bar"
.Como o comportamento do tempo de execução é diferente, os
.class
arquivos devem ser diferentes, independentemente de qualquer registro de data e hora ou outros metadados.Isso vale para todos os idiomas que têm acesso aos quadros da pilha com números de linha, não apenas para Java.
Nota: se for compilado com
-g:none
(sem nenhuma informação de depuração), os números de linha não serão incluídos,getLineNumber()
sempre retornarão-1
e o programa sempre será impresso"bar"
, independentemente do número de quebras de linha.fonte
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
.-1
era usando a-g:none
bandeira. Existe alguma outra maneira de obter essa exceção usando o ordináriojavac
?-g
opção. Há também-g:vars
e-g:source
que impede a geração doLineNumberTable
.Além de qualquer número de linha para depuração, seu manifesto também pode armazenar a data e a hora da compilação. Naturalmente, isso será diferente toda vez que você compilar.
fonte