调用CommandLineParser#parser时使用org.apache.commons.cli的java.lang.IllegalAccessError

时间:2015-10-04 01:36:27

标签: java eclipse apache-commons-cli

我正在尝试使用Apache Commons CLI库来解析Eclipse项目中的命令行选项,大致遵循Usage Scenarios

中的示例

我将commons-cli-1.3.1文件夹添加到Eclipse项目根目录中的lib文件夹中。

我将此添加到我的导入中:

import org.apache.commons.cli.*;

这是我main的顶部:

    Options options = new Options();
    CommandLineParser parser = new DefaultParser();
    CommandLine cmd = null;
    try {
        cmd = parser.parse( options, args);
    } catch ( ParseException e1 ) {
        System.err.println( "Unable to parse command-line options: "+e1.getMessage() );
        e1.printStackTrace();
    }

它编译时没有错误,但是当它运行时,parser.parse调用会生成此错误:

Exception in thread "main" java.lang.IllegalAccessError: tried to access method org.apache.commons.cli.Options.getOptionGroups()Ljava/util/Collection; from class org.apache.commons.cli.DefaultParser

此时我没有使用任何类加载器。

这个错误是什么意思?如何解决错误并解析参数?

2 个答案:

答案 0 :(得分:6)

这很可能是一个依赖问题。

当您在一个版本的库中再次编译代码(在您的情况下为1.3.1)时会发生这种情况,然后在类路径中使用该库的旧版本运行。

当我依赖commons-cli-1.3.1时,我今天遇到了这个问题,但是我的classpath中有commons-cli-1.2(因为我使用了yarn jar来启动我的应用程序)

你应该做什么?

  1. 您可以尝试按照上面的建议降级到1.2(这对我有帮助)
  2. 查看您的类路径并搜索另一个版本的commons-cli
  3. 您的异常消息真正意味着什么? 这意味着运行时的某些代码会尝试调用一些它无权调用的方法。例如,这可能是尝试调用私有方法。通常这是在编译期间捕获的。

    但是,例如,如果你的代码试图调用某个在1.3.1中公开但在1.2中是私有的函数。如果您再次编译1.3.1但尝试在类路径中使用1.2启动,则会出现这种错误。

    希望很清楚。

答案 1 :(得分:0)

我使用commons-cli来处理游戏OpenPatrician的命令行参数。基本上它有三个部分。允许的命令行参数的定义:

Options opts = new Options();
opts.addOption(HELP_OPTION, "help", false, "Display help");
opts.addOption(OptionBuilder.withLongOpt(VERSION_OPTION)
        .withDescription("Version of this application")
        .create());
opts.addOption(FULLSCREEN_MODE, "fullscreen", false, "fullscreen mode");
opts.addOption(OptionBuilder.withArgName(WINDOWED_MODE)
        .withLongOpt("windowed")
        .hasOptionalArgs(1)
        .withArgName("widthxheight")
        .withDescription("Windowed mode with optional definition of window size like: 1280x780")
        .create());
opts.addOption(GAME_LOCALE, "lang", true, "Specify the locale to use");
opts.addOption(CLIENT_OPTION, "client", false, "Start application in client mode. Currently unused. Either client or server must be specified");
opts.addOption(SERVER_OPTION, "server", false, "Start application in server mode. Currently unused. Either client or server must be specified");

提供包含所有可能参数的帮助消息:

public void printHelp(Options options) {
    HelpFormatter formatter = new HelpFormatter();
    formatter.printHelp( "OpenPatrician", options );
}

当然解析参数:

public CommandLine parseCommandLine(Options options, String[] args) {
    try {
        // parse the command line arguments
        CommandLineParser parser = new PosixParser();
        return parser.parse( options, args );
    }
    catch( ParseException exp ) {
        printHelp(options);
        throw new IllegalArgumentException("Parsing of command line arguments failed", exp);
    }
}

请注意,我在这里使用的是PosixPaser,而不是默认的解析器。所以这可能会有不同的行为。