/**
   * Returns the class this method was called 'framesToSkip' frames up the caller hierarchy. JDK
   * used to have {@link sun.reflect.Reflection#getCallerClass(int)} until jdk 1.8 build 87. So we
   * have to resort to slow stack unwinding.
   *
   * <p>NOTE: <b>Extremely expensive! Please consider not using it. These aren't the droids you're
   * looking for!</b>
   */
  @SuppressWarnings("JavadocReference")
  @Nullable
  public static Class getCallerClass(int framesToSkip) {
    int frames = framesToSkip;

    StackTraceElement[] stackTrace = new Throwable().getStackTrace();
    String className = null;
    for (int i = 1; i <= frames; i++) {
      if (i >= stackTrace.length) {
        break;
      }
      StackTraceElement element = stackTrace[i];
      className = element.getClassName();
      if (className.equals("java.lang.reflect.Method")
          || className.equals("sun.reflect.NativeMethodAccessorImpl")
          || className.equals("sun.reflect.DelegatingMethodAccessorImpl")) {
        frames++;
        continue;
      }
      if (i == frames) {
        break;
      }
    }

    if (className == null) {
      // some plugins incorrectly expect not-null class too far up the caller chain,
      // so provide some not-null class for them
      className = ReflectionUtil.class.getName();
    }

    try {
      return Class.forName(className);
    } catch (ClassNotFoundException ignored) {
    }
    ClassLoader pluginClassLoader = PLUGIN_CLASS_LOADER_DETECTOR.fun(className);
    if (pluginClassLoader != null) {
      try {
        return Class.forName(className, false, pluginClassLoader);
      } catch (ClassNotFoundException ignored) {
      }
    }
    LOG.error(
        "Could not load class '"
            + className
            + "' using classLoader "
            + ReflectionUtil.class.getClassLoader()
            + "."
            + (stackTrace[1].getClassName().equals("com.intellij.openapi.util.IconLoader")
                ? " Use getIcon(String, Class) instead."
                : ""));
    return null;
  }