private void cacheFields(final Class<?> clazz, boolean includeStatics) {
    if (clazz != null && clazz.isArray()) {
      Class<?> componentType = clazz.getComponentType();
      if (componentType.isPrimitive()) {
        FIELD_CACHE.put(clazz, PRIMITIVE_ARRAY);
        STATIC_FIELD_CACHE.put(clazz, PRIMITIVE_ARRAY);
      } else {
        FIELD_CACHE.put(clazz, NON_PRIMITIVE_ARRAY);
        STATIC_FIELD_CACHE.put(clazz, NON_PRIMITIVE_ARRAY);
      }
      return;
    }

    ArrayList<Field> staticFields = new ArrayList<>();
    ArrayList<Field> nonPrimitiveFields = new ArrayList<>();

    Class<?> currentClass = clazz;
    while (currentClass != null) {
      Field[] fields = currentClass.getDeclaredFields();
      for (Field field : fields) {
        Class<?> fieldType = field.getType();
        if (!fieldType.isPrimitive()) {
          if (Modifier.isStatic(field.getModifiers())) {
            if (includeStatics) {
              field.setAccessible(true);
              staticFields.add(field);
            }
          } else {
            field.setAccessible(true);
            nonPrimitiveFields.add(field);
          }
        }
      }

      currentClass = currentClass.getSuperclass();
    }

    FIELD_CACHE.put(clazz, nonPrimitiveFields.toArray(new Field[0]));
    if (includeStatics) {
      STATIC_FIELD_CACHE.put(clazz, staticFields.toArray(new Field[0]));
    }
  }
Visit all objects reachable from a given root object, using a breadth first search. Using this
method requires some heap space - probably between 8 - 30 bytes per reachable object.

@param root object to traverse from
@param visitor a visitor to visit each node
@param includeStatics if true, then first time we see a new object type, all of its static
       fields will be visited.
geode-core/src/main/java/org/apache/geode/internal/size/ObjectTraverser.java