1

Picocli 必须自省命令树。这样做需要为每个命令加载域对象类,这会减慢 jvm 启动速度。

有哪些选择可以避免这种启动滞后?我提出的一种解决方案在https://github.com/remkop/picocli/issues/482中进行了描述:

我正在使用反射将任何类加载推迟到选择命令之后。这样,只有命令类本身被加载,最后是实现用户请求的单个命令的类:

abstract class BaseCommand implements Runnable {

    interface CommandExecutor {
        Object doExecute() throws Exception;
    }

    // find the CommandExecutor declared at the BaseCommand subclass.
    protected Object executeReflectively() throws Exception {
        Class<?> innerClass = getExecutorInnerClass();
        Constructor<?> ctor = innerClass.getDeclaredConstructor(getClass());
        CommandExecutor exec = (CommandExecutor) ctor.newInstance(this);
        return exec.doExecute();
    }

    private Class<?> getExecutorInnerClass() throws ClassNotFoundException {
        return getClass().getClassLoader().loadClass(getClass().getName() + "$Executor");
    }

    public void run() {
        try {
             executeReflectively();
       } catch(...){
          /// usual stuff
       }
    }
}

一个具体的表扬类:

@Command(...) 
final class CopyProfile extends BaseCommand {
    @Option String source;
    @Option String dest;

    // class must NOT be static and must be called "Executor"
    public class Executor implements CommandExecutor {
        @Override
        public Object doExecute() throws Exception {
           // you can basically wrap your original run() with this boilerplate
           // all the CopyProfile's field are in scope!
          FileUtils.copy(source, dest);
        }
    }
}

似乎https://github.com/remkop/picocli/issues/500可能会为此提供最终解决方案。在那之前还有什么其他选择?

4

1 回答 1

0

2020 年 2 月更新:

升级到最新版本的 picocli 应该可以解决此问题。从 picocli 4.2.0 发行说明

从这个版本开始,子命令在命令行上匹配之前不会被实例化。这应该可以改善应用程序的启动时间,这些应用程序在实例化时会进行大量初始化。


不需要任何代码更改的替代方法是使用 GraalVM 将基于 picocli 的应用程序编译为本机映像。

本文展示了如何执行此操作,生成的启动时间为 3 毫秒。

在 GraalVM 上运行的基于 picocli 的示例应用程序

于 2018-10-04T23:59:24.710 回答