maven中javac编译命令错误的解决方法

时间:2012-02-29 20:09:34

标签: java maven javac

我遇到了Java编译器中的一个错误,其中提交用于编译的文件的顺序可能导致代码无法编译。我已经深入研究了代码,以找出可以重现问题的最少量代码,从而产生three source files(每个1个类)。

public interface ActionSpec {
    public abstract int run(String param);
}


public enum Actions implements ActionSpec {
    SKIP {
        public int run(String d) {
            return 0;
        }
    };
}

public class Program {

    public static void main(String[] args) {
        Actions.SKIP.run("hello");
    }
}

通过以特定顺序使用javac参数可以重现该问题。简而言之,为了成功,必须始终在使用它的Program类之前编译Actions类,否则javac无法以理智的方式处理它:

# this case fails
echo "Trying order: javac Program.java Actions.java ActionSpec.java"
rm *class
javac -verbose Program.java Actions.java ActionSpec.java

# this case fails
#rm *class
#javac Program.java Actions.java ActionSpec.java

# this case fails
#rm *class
#javac ActionSpec.java Program.java Actions.java

# this case succeeds
#rm *class
#javac ActionSpec.java Actions.java Program.java

# this case succeeds
#rm *class
#javac Actions.java ActionSpec.java Program.java

# this case succeeds
#rm *class
#javac Actions.java Program.java ActionSpec.java

编译错误发生时始终是相同的 - 即使它们都实现了具有该run方法的接口,也无法找到Actions枚举实例上的run方法。

Program.java:6: cannot find symbol
symbol  : method run(java.lang.String)
location: class problem.Actions
        Actions.SKIP.run("hello");

该错误似乎与this one reported on Oracle's site有关。 我在mac os x 10.7.2 x86_64上使用javac 1.6.0_29,但也在Linux上重现了它。

当我使用Maven构建时,这个问题变得明显,并且似乎没有对编译顺序的任何控制。所以我正在寻找一种解决方法,要么强制maven以这样的顺序编译文件以避免这种编译器错误,要么摆弄编译器标志(或类似的东西)以避免它。问题出现在工作站和持续集成环境中,所以它必须全面工作。有什么建议吗?

编辑:只是尝试了以下解决方法,尽管只是将有问题的枚举分配给具有其实现的接口类型的变量,但令人惊讶的是导致错误消失。

public class Program {

    public static void main(String[] args) {
        ActionSpec a = Actions.SKIP;
        a.run("hello");
    }
}

仍然对其他人的意见感兴趣。

5 个答案:

答案 0 :(得分:5)

我玩了一遍,发现添加了简单的演员:

public static void main(String[] args) {
    ((ActionSpec)Actions.SKIP).run("hello");
}

解决了这个问题。将此枚举作为方法参数作为接口传递也可以实现技巧

答案 1 :(得分:4)

这是http://bugs.sun.com/view_bug.do?bug_id=6724345

中报告的错误

如果您仍在使用Java 6编译器,则建议的解决方法应该可行。该错误已在Java 7中修复。

答案 2 :(得分:0)

我将如何做到这一点:

  • ActionSpec界面移至另一个Maven项目。我们通常在他们自己的项目中有接口和公共域类,例如foo-service-specs
  • 将其他类保留在实施项目中,例如foo-service-impl
  • foo-service-specs。{/ li>中包含foo-service-impl项目作为依赖项

通过这样做,您可以确保编译顺序正常工作,并且它也可以用于持续集成。

答案 3 :(得分:0)

尝试多次执行编译器插件。使用default-compile作为第一个执行ID,将新配置添加到Maven的默认编译器执行中。使用默认执行中的<includes/> config元素首先编译枚举。对于第二次执行,您使用<includes><excludes>的组合,其中<includes>将是您的所有代码,排除将是已编译的枚举。

我认为这适用于您的示例程序但我没有测试它。我之前用Maven 3测试了类似的东西,它运行良好。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <source>1.6</source>
        <target>1.6</target>
    </configuration>
    <executions>
        <execution>
           <id>default-compile</id>
           <goals><goal>compile</goal></goals>
           <configuration>
              <includes>
                  <include>**/Actions.*</include>
              </includes>
           </configuration>
        </execution>
        <execution>
           <id>second</id>
           <goals><goal>compile</goal></goals>
           <configuration>
              <includes>
                  <include>**/*</include>
              </includes>
              <excludes>
                  <exclude>**/Actions.*</exclude>
              </excludes>
           </configuration>
        </execution>
    </executions>
</plugin>

答案 4 :(得分:0)

我们遇到了同样的问题。 maven compiler插件的多次执行对我们有用......