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

Sha*_*ing 5 java eclipse apache-commons-cli

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

我将该commons-cli-1.3.1文件夹添加到libEclipse项目根目录中的文件夹中.

我把它添加到我的导入中:

import org.apache.commons.cli.*;
Run Code Online (Sandbox Code Playgroud)

这是我的首要问题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();
    }
Run Code Online (Sandbox Code Playgroud)

它编译时没有错误,但是当它运行时,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
Run Code Online (Sandbox Code Playgroud)

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

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

Ale*_*mak 6

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

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

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

你应该怎么做?

  1. 您可以尝试按照上面的建议降级到1.2(这对我有帮助)
  2. 查看您的类路径并搜索另一个版本的commons-cli

你的异常信息到底意味着什么? 这意味着运行时的某些代码会尝试调用一些它无权调用的方法.例如,这可能是尝试调用私有方法.通常这是在编译期间捕获的.

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

希望很清楚.


hot*_*zst 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");
Run Code Online (Sandbox Code Playgroud)

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

public void printHelp(Options options) {
    HelpFormatter formatter = new HelpFormatter();
    formatter.printHelp( "OpenPatrician", options );
}
Run Code Online (Sandbox Code Playgroud)

当然还有参数的解析:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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