1

I have recently seen a behaviour which made me ask this on SO . I was hoping that people would be able to share their findings too.

Would a class file (bytecode) be different if the same file is compiled (unchanged) using JDK 1.8 u66 and JDK 1.8 u121? What I mean is the following:

1) I compile an application using JDK 1.8 u66 2) I make changes to 1 or 2 files and recompile using JDK 1.8 u66.

Could I expect some of the unchanged class files to have different binary content even though they haven't changed?

My reason is that when I took a hash of a file which wasn't changed as part of my steps above - they had same size on disk, but the hashcode was totally different. and I used Winmerge to compare these two versions where the size was reported as identical, but the binary contents were different. The following is what I have compared using Winmerge (blue marked item was something related to my source name so I had to mask it out) - but please observe the difference in 208 and 248.

enter image description here

Is this expected? if so, could someone please point me to that literature which explains this?

Regards,

ha9u63a7
  • 6,233
  • 16
  • 73
  • 108

1 Answers1

6

Countless reasons exist, why the same Java source file may be compiled to different bytes by different compilers, where different versions of the same compiler should indeed be seen as different compilers. Even for the exact same compiler there is no guarantee that bytes are identical.

One such reason is, that all references in the code (other than opcodes and bytecode offsets) are indirected through the Constant Pool. The order of entries in the constant pool is not specified and hence it may change leading to all references using a different offset.

See also that JVMS has a section titled Compiling for the Java Virtual Machine, which, however, starts by saying:

The numbered sections in this chapter are not normative

As a result, reasoning works only in one direction: same bytes implies same source code, but different bytes doesn't necessarily imply different source code.

JDK-8067422, as linked from one comment, gives an example where even the same compiler can produce different bytes for the same source file (perhaps due to different set of source files compiled in the same compiler invocation). As per JLS and JVMS this is legal, just inconvenient.

Stephan Herrmann
  • 7,963
  • 2
  • 27
  • 38
  • @StephanHermann Thanks - I would however, be inclined to the JDK jira because it clearly says the issue was fixed for JDK9. So as long as it's JDK8 I will have issues. – ha9u63a7 Apr 19 '18 at 10:15
  • @ha9u63ar, you may be right, but my point is: even after the issue is fixed, there's no *guarantee* for equal byte codes. – Stephan Herrmann Apr 19 '18 at 12:02
  • @StephenHerrmann I undestand that. But Is it still wrong to say that as long as the JDK is identical and if I compile same class 5 times in a row without changing any bytes - they should be identical, provided that the lambdas aren't present? or even that's wrong? – ha9u63a7 Apr 19 '18 at 12:11
  • @ha9u63ar there's no requirement in the compiler spec for that, as Stephan pointed out by quoting from the JVMS. – Nándor Előd Fekete Apr 19 '18 at 12:42
  • See also “[Do different Java Compilers (where the vendor is different) produce different bytecode](https://stackoverflow.com/a/20291342/2711488)” and “[How to use javac to create binary identical class files across different platforms?](https://stackoverflow.com/a/41976196/2711488)”… – Holger Apr 19 '18 at 15:51