static long unsafeSizeof(Class<?> clazz, Unsafe myUnsafe) {
    if (myUnsafe == null) {
      return -1;
    }
    long size;
    Field lastField = null;
    long lastFieldOffset = 0;
    do {
      Field[] fields = clazz.getDeclaredFields();
      for (Field field : fields) {
        if (!Modifier.isStatic(field.getModifiers())) {
          try {
            long offset = myUnsafe.fieldOffset(field);
            if (offset >= lastFieldOffset) {
              lastFieldOffset = offset;
              lastField = field;
            }
          } catch (UnsupportedOperationException ex) {
            // This happens on java 17 because hidden classes do not support
            // unsafe.fieldOffset.
            return -1;
          }
        }
      }
      if (lastField != null) {
        // if we have found a field in a subclass then one of them will be the last field
        // so just break without looking at super class fields.
        break;
      }
      clazz = clazz.getSuperclass();
    } while (clazz != null);

    if (lastField != null) {
      size = lastFieldOffset + sizeType(lastField.getType());
    } else {
      // class with no fields
      size = OBJECT_SIZE;
    }
    return size;
  }
Returns -1 if it was not able to compute the size; otherwise returns the size.
Since unsafe.fieldOffset(Field) will give us the offset to the first byte of that field all we
need to do is find which of the non-static declared fields has the greatest offset.
geode-core/src/main/java/org/apache/geode/internal/size/ReflectionSingleObjectSizer.java