public static void processException(Throwable t) {
    StartupAbortedException se = null;

    if (t instanceof StartupAbortedException) {
      se = (StartupAbortedException) t;
    } else if (t.getCause() instanceof StartupAbortedException) {
      se = (StartupAbortedException) t.getCause();
    } else if (!IdeaApplication.isLoaded()) {
      se = new StartupAbortedException(t);
    }

    if (se != null) {
      if (se.logError()) {
        try {
          if (Logger.isInitialized() && !(t instanceof ProcessCanceledException)) {
            getLogger().error(t);
          }
        } catch (Throwable ignore) {
        }

        Main.showMessage("Start Failed", t);
      }

      System.exit(se.exitCode());
    }

    if (!(t instanceof ProcessCanceledException)) {
      getLogger().error(t);
    }
  }
  /** Called via reflection */
  @SuppressWarnings({"UnusedDeclaration", "HardCodedStringLiteral"})
  protected static void start(
      final String mainClass, final String methodName, final String[] args) {
    startupStart = System.nanoTime();

    Main.setFlags(args);

    if (!Main.isHeadless()) {
      UIUtil.initDefaultLAF();
    }

    ThreadGroup threadGroup =
        new ThreadGroup("Idea Thread Group") {
          @Override
          public void uncaughtException(Thread t, Throwable e) {
            processException(e);
          }
        };

    Runnable runnable =
        new Runnable() {
          @Override
          public void run() {
            try {
              ClassUtilCore.clearJarURLCache();

              Class<?> aClass = Class.forName(mainClass);
              Method method =
                  aClass.getDeclaredMethod(methodName, ArrayUtil.EMPTY_STRING_ARRAY.getClass());
              method.setAccessible(true);
              Object[] argsArray = {args};
              method.invoke(null, argsArray);
            } catch (Throwable t) {
              throw new StartupAbortedException(t);
            }
          }
        };

    new Thread(threadGroup, runnable, "Idea Main Thread").start();
  }
  public static void handleComponentError(
      Throwable t, @Nullable String componentClassName, @Nullable ComponentConfig config) {
    if (t instanceof StartupAbortedException) {
      throw (StartupAbortedException) t;
    }

    PluginId pluginId = null;
    if (config != null) {
      pluginId = config.getPluginId();
    }
    if (pluginId == null || CORE_PLUGIN_ID.equals(pluginId.getIdString())) {
      if (componentClassName != null) {
        pluginId = getPluginByClassName(componentClassName);
      }
    }
    if (pluginId == null || CORE_PLUGIN_ID.equals(pluginId.getIdString())) {
      if (t instanceof PicoPluginExtensionInitializationException) {
        pluginId = ((PicoPluginExtensionInitializationException) t).getPluginId();
      }
    }

    if (pluginId != null && !CORE_PLUGIN_ID.equals(pluginId.getIdString())) {
      getLogger().warn(t);

      disablePlugin(pluginId.getIdString());

      StringWriter message = new StringWriter();
      message
          .append("Plugin '")
          .append(pluginId.getIdString())
          .append("' failed to initialize and will be disabled. ");
      message
          .append(" Please restart ")
          .append(ApplicationNamesInfo.getInstance().getFullProductName())
          .append('.');
      message.append("\n\n");
      t.printStackTrace(new PrintWriter(message));
      Main.showMessage("Plugin Error", message.toString(), false);

      throw new StartupAbortedException(t).exitCode(Main.PLUGIN_ERROR).logError(false);
    } else {
      throw new StartupAbortedException("Fatal error initializing '" + componentClassName + "'", t);
    }
  }