【问题标题】:Ant Javac Task Deletes MethodAnt Javac 任务删除方法
【发布时间】:2013-04-17 23:00:48
【问题描述】:

我在 Java 项目中遇到了一些非常奇怪的行为。情况是javac 似乎在编译期间从类中删除了一个方法。

这个类看起来像这样:

public class MessedUp extends X {
    //a bunch of variables here
    //a bunch of methods here

    public void thisDisappears(String arg){

    }

    //a bunch more methods here

}

还有一个类实例化并调用了这个方法:

public class WontCompile {

    public void doSomething(){
        MessedUp mu = new MessedUp();
        mu.thisDisappears("something");
    }
}

第一个类编译得很好,但第二个没有。 javac 输出如下内容:

[javac] C:\mypath\WontCompile.java:251: error: cannot find symbol
[javac]                     mu.thisDisappears("something");
[javac]                       ^
[javac]   symbol:   method thisDisappears(String)
[javac]   location: variable mu of type MessedUp

我知道代码很好,因为我已经在 Eclipse 中使用它几年了(我在尝试使用 Eclipse 生成的 ant 文件时正在追踪这个问题)。但是,有时 Eclipse 会突出显示对 thisDisappears 的调用,说它不存在,并提供创建它。如果接受这个提议,那么 Eclipse 会抱怨有两个同名的方法。经过一些明显导致重建或其他事情的处理后,错误消失了。

在被驱动了一段时间后,我决定检查 MessedUp.java 的实际类文件。使用Java Decompiler GUI,我发现thisDisappears 不在类文件中!

下面是我的 ant 文件:

<project basedir="." default="build" name="MyProject">
    <property name="LIB_HOME" value="C:\dev\LibSuite-9.3.1"/>
    <property environment="env"/>
    <property name="debuglevel" value="source,lines,vars"/>
    <property name="target" value="1.7"/>
    <property name="source" value="1.7"/>
    <path id="MyProject.classpath">
        <pathelement location="bin"/>
        <pathelement location="lib/edu.mit.jwi_2.1.4.jar"/>
        <pathelement location="lib/edu.sussex.nlp.jws.beta.11.jar"/>
        <pathelement location="lib/jaws-bin.jar"/>
        <pathelement location="lib/junit-4.11.jar"/>
        <!--External Jars-->
        <pathelement location="${LIB_HOME}/share/java/abc.jar"/>
        <pathelement location="${LIB_HOME}/share/java/def-9.3.1.jar"/>
    </path>
    <target name="init">
        <mkdir dir="bin"/>
        <copy includeemptydirs="false" todir="bin">
            <fileset dir="main/src">
                <exclude name="**/*.launch"/>
                <exclude name="**/*.java"/>
            </fileset>
        </copy>
        <copy includeemptydirs="false" todir="bin">
            <fileset dir="main/test">
                <exclude name="**/*.launch"/>
                <exclude name="**/*.java"/>
            </fileset>
        </copy>
    </target>
    <target name="clean">
        <delete dir="bin"/>
    </target>

    <target depends="init" name="build">
        <echo message="${ant.project.name}: ${ant.file}"/>
        <javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
            <classpath refid="MyProject.classpath"/>
            <src path="main/src"/>
            <src path="main/test"/>
            <compilerarg value="-Xlint"/>
        </javac>
    </target>

    <!--Test the app-->
    <target depends="build" name="regression">
        <junit>
            <classpath refid="MyProject.classpath"/>
            <test name="uni.my.app.TestSuite"/>
        </junit>
    </target>

    <!--Run the app-->
    <target depends="build" name="run">
        <java classname="uni.my.app.Application">
            <classpath refid="MyProject.classpath"/>
            <arg value="sentences.txt"/>
        </java>
    </target>
</project>

不幸的是,我无法整理出一个最小的破坏示例。我正在编写的代码还没有向公众发布,所以我还不能全部分享。它引用了几个 jars(没有冲突的命名空间),其中一些带有本地方法。我不知道类和罐子的确切组合会导致错误。我在使用 jdk 1.6.0_25 和 1.7.21 时遇到了同样的问题。

有人对如何解决这个问题有任何经验或想法吗?

【问题讨论】:

    标签: java eclipse compiler-errors javac


    【解决方案1】:

    这是一个猜测。

    Ant 在 eclipse 之外运行,因此它所做的任何更改都不会反映在 eclipse 的大量缓存的世界视图中。据我所知,eclipse 的更改也不会反映在 ant 使用的文件中。

    我会先清理项目,然后构建项目,然后刷新项目。我会看看你是否在 Eclipse 中遇到了这个问题。然后我会运行 ant(如果必须的话),再次刷新,然后看看问题是否存在。

    任何时候你在 eclipse 或 ant 中做任何事情,在你使用其他程序之前,刷新 eclipse 项目。

    告诉我们进展如何。

    附言相信 java 编译器不会删除任何方法。我同意你发生了一些奇怪的事情,但不是这样。

    【讨论】:

    • 感谢您的建议。这并没有直接解决它,但让我找到了问题(我稍后会发布)。
    【解决方案2】:

    问题在于,无论出于何种原因,另一个用户已将项目转换为 VCS,并且所有类文件与其对应的源文件位于同一文件夹中。在我的机器上,Eclipse 将二进制文件放入 bin 文件夹中,所以我不知道为什么将它们与源代码放在其他用户的机器上。

    Eclipse 生成的init 目标用于复制代码使用的资源。它从源目录复制除javalaunch 文件之外的任何内容。但是,由于类文件位于源目录中,因此它也将它们复制了过来。然后,当build 目标被执行时,它并没有费心去编译任何东西,因为似乎已经存在新的类文件(但它们实际上只是旧代码的新副本)。

    解决方案是 1) 从源文件夹中删除所有类文件,以及 2) 将**/*.class 的排除规则添加到资源复制代码中,以取得良好的效果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-08
      • 1970-01-01
      相关资源
      最近更新 更多