private synchronized @NotNull List<EditorActionHandler> getHandlerChain() {
    List<EditorActionHandler> cachedChain = myCachedChain.get();
    if (cachedChain != null && cachedChain != UPDATE_MARKER) {
      return cachedChain;
    }

    myCachedChain.set(UPDATE_MARKER);
    List<EditorActionHandlerBean> handlerBeans = getRegisteredHandlers(myAction);
    List<EditorActionHandler> chain = new ArrayList<>(handlerBeans.size());
    chain.add(myBaseHandler);
    Application container = ApplicationManager.getApplication();
    for (EditorActionHandlerBean bean : handlerBeans) {
      EditorActionHandler handler;
      EditorActionHandler param = chain.isEmpty() ? null : chain.get(chain.size() - 1);
      try {
        Class<EditorActionHandler> beanImplementationClass = container.loadClass(bean.implementationClass, bean.pluginDescriptor);
        Constructor<EditorActionHandler> constructor;
        try {
          constructor = beanImplementationClass.getDeclaredConstructor(EditorActionHandler.class);
        }
        catch (NoSuchMethodException ignore) {
          constructor = null;
        }

        if (constructor == null) {
          constructor = beanImplementationClass.getDeclaredConstructor();
          constructor.setAccessible(true);
          handler = constructor.newInstance();
        }
        else {
          constructor.setAccessible(true);
          handler = constructor.newInstance(param);
        }
      }
      catch (Exception e) {
        if (ExceptionUtil.causedBy(e, ExtensionNotApplicableException.class)) continue;
        Logger.getInstance(EditorActionHandlerBean.class).error(new PluginException(e, bean.pluginDescriptor.getPluginId()));
        continue;
      }

      handler.setWorksInInjected(myWorksInInjected);
      chain.add(handler);
    }

    if (LOG.isDebugEnabled()) {
      LOG.debug("Updated DynamicEditorActionHandler chain for " + myAction.getClass() + ": " + chain,
                LOG.isTraceEnabled() ? new Throwable() : null);
    }

    // We want to avoid deadlock with ActionManagerImpl, so 'clearCache' method isn't synchronized.
    // That's why we may cache the result only if ActionManagerImpl hasn't invalidated registered handlers
    // while we were calculating it.
    myCachedChain.compareAndSet(UPDATE_MARKER, chain);
    return chain;
  }
private synchronized @NotNull List<EditorActionHandler> getHandlerChain()