private static Field @NotNull [] getAllFields(@NotNull Class<?> aClass) {
    Field[] cached = allFields.get(aClass);
    if (cached == null) {
      try {
        Field[] declaredFields = aClass.getDeclaredFields();
        List<Field> fields = new ArrayList<>(declaredFields.length + 5);
        for (Field declaredField : declaredFields) {
          declaredField.setAccessible(true);
          Class<?> type = declaredField.getType();
          if (isTrivial(type)) continue; // unable to hold references, skip
          fields.add(declaredField);
        }
        Class<?> superclass = aClass.getSuperclass();
        if (superclass != null) {
          for (Field sup : getAllFields(superclass)) {
            if (!fields.contains(sup)) {
              fields.add(sup);
            }
          }
        }
        cached = fields.isEmpty() ? EMPTY_FIELD_ARRAY : fields.toArray(new Field[0]);
      }
      catch (IncompatibleClassChangeError | NoClassDefFoundError | SecurityException e) {
        // this exception may be thrown because there are two different versions of org.objectweb.asm.tree.ClassNode from different plugins
        //I don't see any sane way to fix it until we load all the plugins by the same classloader in tests
        cached = EMPTY_FIELD_ARRAY;
      }
      catch (@ReviseWhenPortedToJDK("9") RuntimeException e) {
        // field.setAccessible() can now throw this exception when accessing unexported module
        if (e.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
          cached = EMPTY_FIELD_ARRAY;
        }
        else {
          throw e;
        }
      }

      allFields.put(aClass, cached);
    }
    return cached;
  }
private static Field @NotNull [] getAllFields(@NotNull Class<?> aClass)