简体   繁体   English

.java中的注释更改.class文件的ByteCode

[英]Comments in .java change ByteCode of .class file

My understanding is that the Java compiler does not include comments in bytecode in the output .class file. 我的理解是Java编译器在输出.class文件中的字节码中不包含注释。

However I have the code: 但是我有代码:

InputStream stream = getClassLoader().getResourceAsStream(classAsPath);
byte[] classBytes = IOUtils.toByteArray(stream);

I run it for my java class, add a comment to the java code, and re-run it. 我为我的java类运行它,为java代码添加注释,然后重新运行它。 I see that classBytes is different just from the added comment 我看到classBytes与添加的注释不同

Comments are not included in the classfile. 注释不包含在类文件中。 However, the compiler does by default include some metadata for debugging purposes, which includes line numbers. 但是,编译器默认包含一些用于调试目的的元数据,其中包括行号。 If your comments span a line or more, that will obviously change the line numbers of everything, and hence the resulting classfile will change. 如果您的注释跨越一行或更多,这显然会更改所有内容的行号,因此生成的类文件将更改。

You can pass -g:none to javac to avoid including line numbers and other optional metadata. 您可以将-g:none传递给javac以避免包含行号和其他可选元数据。

There is no guaranty that the same source code produces exactly the same byte code. 没有保证相同的源代码产生完全相同的字节代码。 The standard does not mandate how certain language constructs are mapped to byte code constructs and certain “best practices” have changed over time or differ between compiler implementations. 该标准没有强制要求某些语言结构如何映射到字节代码结构,并且某些“最佳实践”随着时间的推移而发生了变化,或者在编译器实现之间有所不同。 Some aspects, eg the order of the methods within a class file are considered entirely irrelevant and may be the result of some implementation specific aspects of the compiler instead of a deliberate decision. 某些方面,例如类文件中方法的顺序被认为是完全不相关的,并且可能是编译器的某些实现特定方面的结果,而不是故意的决定。

Usually, using exactly the same compiler implementation and version will reproduce the same byte code, as the compiler's program code is deterministic, but that doesn't have to be, eg some hash map implementations have a randomization feature, also compilers might utilize parallel processing which may add indeterminism to aspects considered irrelevant to the result. 通常,使用完全相同的编译器实现和版本将重现相同的字节代码,因为编译器的程序代码是确定性的,但不必如此,例如一些哈希映射实现具有随机化功能,编译器也可以使用并行处理这可能会增加与结果无关的方面的不确定性。

Given that even exactly the same source code is not guaranteed to produce identical bytecode, it should not surprise that even small, actually irrelevant changes may cause differences in the bytecode, as even if nothing else changes they may have an impact on timing or hash codes. 鉴于即使完全相同的源代码也不能保证生成相同的字节码,即使很小的,实际上无关的更改也可能导致字节码的差异,因为即使没有其他更改,它们也可能对时序或哈希码产生影响。 。

As said by others, inserting a comment line may change the line numbers in debug attributes which are included by default, so that's a simple reason to get different byte code. 正如其他人所说,插入注释行可能会更改默认包含的调试属性中的行号,因此这是获取不同字节代码的简单原因。 But it is important to understand that your assumption to always get identical byte code is fundamentally flawed. 但重要的是要理解你总是得到相同的字节码的假设是根本上有缺陷的。

Note that a similar wrong assumption has already led to a major design flaw in the Java API. 请注意,类似的错误假设已经导致Java API中的主要设计缺陷。 The default serialVersionUID is calculated by hashing class data which are actually irrelevant to the compatibility of serialized data. 默认的serialVersionUID是通过散列类数据计算的,这些数据实际上与序列化数据的兼容性无关。 As the documentation of Serializable states: 正如Serializable的文档所述:

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. 如果可序列化类未显式声明serialVersionUID,则序列化运行时将基于类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述。 However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. 但是, 强烈建议所有可序列化类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类细节高度敏感,这些细节可能因编译器实现而异,因此在反序列化期间可能导致意外的InvalidClassExceptions

Don't repeat this mistake. 不要重复这个错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM