KNe*_*jad 206 java bytecode compilation javac
我有以下Java类
public class HelloWorld {
public static void main(String []args) {
}
}
Run Code Online (Sandbox Code Playgroud)
当我编译这个文件并在生成的类文件上运行sha256时,我得到了
9c8d09e27ea78319ddb85fcf4f8085aa7762b0ab36dc5ba5fd000dccb63960ff HelloWorld.class
Run Code Online (Sandbox Code Playgroud)
接下来我修改了类并添加了一个如下所示的空白行:
public class HelloWorld {
public static void main(String []args) {
}
}
Run Code Online (Sandbox Code Playgroud)
我再次在输出上运行sha256,期望得到相同的结果,但我得到了
11f7ad3ad03eb9e0bb7bfa3b97bbe0f17d31194d8d92cc683cfbd7852e2d189f HelloWorld.class
Run Code Online (Sandbox Code Playgroud)
我已阅读此TutorialsPoint文章:
只包含空格的行(可能带有注释)称为空行,Java完全忽略它.
所以我的问题是,由于Java忽略空行,为什么两个程序的编译字节码都不同?
即在该差HelloWorld.class
一个0x03
字节是由替换0x04
字节.
Fed*_*oca 328
基本上,行号保留用于调试,因此如果您按照您的方式更改源代码,则您的方法从不同的行开始,编译的类反映了差异.
Kar*_*cki 114
您可以通过使用javap -v
哪个输出详细信息来查看更改.像其他已经提到的那样,差异在于行号:
$ javap -v HelloWorld.class > with-line.txt
$ javap -v HelloWorld.class > no-line.txt
$ diff -C 1 no-line.txt with-line.txt
*** no-line.txt 2018-10-03 11:43:32.719400000 +0100
--- with-line.txt 2018-10-03 11:43:04.378500000 +0100
***************
*** 2,4 ****
Last modified 03-Oct-2018; size 373 bytes
! MD5 checksum 058baea07fb787bdd81c3fb3f9c586bc
Compiled from "HelloWorld.java"
--- 2,4 ----
Last modified 03-Oct-2018; size 373 bytes
! MD5 checksum 435dbce605c21f84dda48de1a76e961f
Compiled from "HelloWorld.java"
***************
*** 50,52 ****
LineNumberTable:
! line 3: 0
LocalVariableTable:
--- 50,52 ----
LineNumberTable:
! line 4: 0
LocalVariableTable:
Run Code Online (Sandbox Code Playgroud)
更确切地说,类文件在以下LineNumberTable
部分中有所不同:
LineNumberTable属性是Code属性(第4.7.3节)的attributes表中的可选variable-length属性.调试器可以使用它来确定代码数组的哪个部分对应于原始源文件中的给定行号.
如果Code属性的attributes表中存在多个LineNumberTable属性,则它们可以按任何顺序出现.
在Code属性的attributes表中,每行源文件可能有多个LineNumberTable属性.也就是说,LineNumberTable属性可以一起表示源文件的给定行,并且不需要与源行一对一.
And*_*kin 53
"Java忽略空行"的假设是错误的.这是一个代码片段,根据方法之前的空行数,行为有所不同main
:
class NewlineDependent {
public static void main(String[] args) {
int i = Thread.currentThread().getStackTrace()[1].getLineNumber();
System.out.println((new String[]{"foo", "bar"})[((i % 2) + 2) % 2]);
}
}
Run Code Online (Sandbox Code Playgroud)
如果之前没有空行main
,则会打印"foo"
,但之前有一个空行main
,则会打印出来"bar"
.
由于运行时行为不同,因此无论时间戳或其他元数据如何,.class
文件都必须不同.
这适用于可以访问具有行号的堆栈帧的每种语言,而不仅仅是Java.
注意:如果使用-g:none
(没有任何调试信息)进行编译,则不会包含行号,getLineNumber()
始终返回-1
,并且"bar"
无论换行符的数量如何,程序始终都会打印.
Gra*_*ham 13
除了用于调试的任何行号详细信息外,您的清单还可以存储构建时间和日期.每次编译时,这自然会有所不同.
归档时间: |
|
查看次数: |
14266 次 |
最近记录: |