【问题标题】:How to reduce slow start for picocli apps due to reflection如何减少由于反射导致的 picocli 应用程序启动缓慢
【发布时间】:2019-03-05 05:23:31
【问题描述】:

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 可能会为此提供终极解决方案。在那之前还有哪些其他选择?

【问题讨论】:

  • 出于兴趣,您能否提供一些有关原始代码的启动时间和更改后的数字?

标签: picocli


【解决方案1】:

2020 年 2 月更新:

升级到最新版本的 picocli 应该可以解决此问题。 来自picocli4.2.0 release notes

从此版本开始,子命令在命令行上匹配之前不会被实例化。这应该会缩短具有子命令的应用程序的启动时间,这些子命令在实例化时会进行大量初始化。


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

This article 显示了如何执行此操作,结果启动时间为 3 毫秒。

【讨论】:

  • 这很好,但请注意,如果您导入任何使用java.lang.SecurityManager 的内容,这将不起作用。当我尝试使用与 AWS 开发工具包进行大量交互的应用程序时,我学到了这一点。
  • @SalmonKiller 这是很好的信息,我不知道这个!您是否介意在 picocli 问题跟踪器上提出请求,提供更多详细信息,以便我们为其他用户记录这些信息?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-15
  • 2010-11-08
  • 2018-02-20
  • 1970-01-01
  • 2012-04-03
  • 2015-03-27
相关资源
最近更新 更多