是否有可能同一个javac编译器编译同一组源文件但生成不同校验和的类文件?

时间:2011-10-14 14:42:53

标签: java compiler-construction ant maven checksum

我试图比较这个结果:(在蚂蚁中)

                       <javac 
                           target="1.5"   
                           source="1.5"
                           deprecation="on"
                           fork="yes"
                           optimize="true"
                           debug="true"
                           debuglevel="lines,vars,source">

                            <classpath>
                                <fileset dir="${project.basedir}/../lib">
                                    <include name="**/*.jar" />
                                    <include name="**/*.zip" />
                                </fileset>                        
                            </classpath>     
                        </javac>

......对此:(在maven中)

        <plugin>                
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <executions>
                <execution>
                    <id>compile</id>
                    <phase>compile</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>                
                    <configuration>
                        <target>1.5</target>
                        <source>1.5</source>
                        <debug>true</debug>
                        <debuglevel>lines,vars,source</debuglevel>
                        <showDeprecation>true</showDeprecation>
                        <optimize>true</optimize>
                        <fork>true</fork>
                        <includes>
                            ...
                        </includes>
                    </configuration>
                </execution>
            </executions>
        </plugin> 

...只发现2个生成的类文件的校验和略有不同,其余的相同。我认为多线程已经发挥了作用,但是对于任一选项产生的校验和似乎在重复尝试时是一致的。什么可以解释这个结果?

更新

我使用javap -verbose检查了一组具有不同校验和的文件,发现唯一的区别是:

const #16 = class   #108;   //  java/lang/Exception
const #17 = Method  #102.#109;  //  java/io/Writer.close:()V
const #18 = Method  #7.#109;    //  java/io/FileWriter.close:()V

而不是:

const #16 = Method  #102.#108;  //  java/io/Writer.close:()V
const #17 = Method  #7.#108;    //  java/io/FileWriter.close:()V
const #18 = class   #109;   //  java/lang/Exception

2 个答案:

答案 0 :(得分:2)

正如您所示,差异在于生成的常量池,这实际上是一个非问题,但令人不安的是您希望相同的输出具有相同的编译器和选项。我敢打赌,编译器在两种情况之间以不同顺序调用java文件,编译顺序会影响结果。

答案 1 :(得分:0)

我正在使用javac编译器,我发现它产生不同的结果二进制.class文件,具体取决于作为参数传递的源文件的顺序。在maven和ant之间我发现了差异。文件的顺序不一样。

无论如何,在两个编辑之间存在差异。我已经反汇编了代码,我发现javac(优化器?)正在从其中一个编译中删除已弃用的java jsr / ret汇编指令。

我不知道这种行为是否是“隐式”编译的结果:http://docs.oracle.com/javase/1.5.0/docs/tooldocs/solaris/javac.html#searching