views:

344

answers:

8

I have an app that was compiled with the built-in Eclipse "Compile" task. Then I decided to move the build procedure into Ant's javac, and the result ended being smaller files.

Later I discovered that adjusting the debuglevel to "vars,lines,source" I could embed the same debug information that Eclipse did, and in a lot of cases files stayed exactly the same size but the internal layout was different. And as a consequence, I couldn't use md5sum signatures to determine if they were exactly the same version.

Besides debug information, what can be the reason that 2 supposedly equal files get a different internal layout or size?

And how can you compare compiled .class files?

A: 

Most importantly, the stack slots for local variables can be arranged arbitrarily without changing the semantics of the code. So basically, you cannot compare compiled class files without parsing and normalizing them - quite a lot of effort.

Why do you want to do that anyway?

Michael Borgwardt
Interesting. Just out of curiosity and for the sake of learning. I know that it's something that I shouldn't really rely on.
Camilo Díaz
A: 

Is Eclipse doing some instrumentation to assist with running in the debugger?

Chris Nava
I'm not sure it's doing that. How can I verify it?
Camilo Díaz
A: 

Ultimately the configurations being used are probably making the difference. Assuming they are using the same versions of Java, there are a host of options that are available for the compile configuration (JDK compliance, class file compatibility and a host of debugging information options).

Robin
+2  A: 

THere is no required order for things such as the order of the constant pool entries (essentially all of the symbol info) as well as the attributes for each field/method/class. Different compilers are free to write out in whatever order they want.

You can compared compiled classes, but you would need to dig into the class file structure and parse it. There are libraries out there for doing that, like BCEL or ASM, but I am not 100% sure they will help you with what you want to do.

TofuBeer
+1  A: 

as Michale B said, it can be arbitrary.

I work on systems that are using file sizes as security. If the .class files change in size, the class won't be given certain permissions.

Normally that would be easy to get around, but we have fairly complete control over the environment, so it's actually pretty functional.

Anyway, any time the classes that are watched are recompiled, it seems, we have to recalculate the size.

Another thing--a special key number is generated when the file is compiled. I don't know much about this, but it often prevents classes from working together. I believe the procedure is, compile class A and save it (call it a1). compile class a again (a2). Compile class b against class a2. Try to run b against a1. I believe that in this case it will fail at runtime.

If you could learn more about that key number, it might give you the info you are after.

Bill K
A: 

For the comparisson you can decompile your class files and play with the sources generated. See this.

german1981
+1  A: 

The ASM Eclipse plugin has a bytecode comparer in it. You select two classes, right click, and do Compare With / Each Other Bytecode.

Alex Miller
+1  A: 

An important thing to note is that Eclipse does not use javac. Eclipse has its own compiler, the JDT, and so differences in the resulting .class files do not surprise me. I'd expect them to not be verbatim, because they are different compilers.

Due to their differences, there exists code that compiles with javac but not JDT, and vice versa. Typically I have seen the differences in the two become apparent in cases of heavy use of generics

Joshua McKinnon