@Override
  public void close() throws IOException {
    if (open.compareAndSet(true, false)) {
      onClose.run();

      Throwable thrown = null;
      do {
        for (Closeable resource : resources) {
          try {
            resource.close();
          } catch (Throwable e) {
            if (thrown == null) {
              thrown = e;
            } else {
              thrown.addSuppressed(e);
            }
          } finally {
            // ensure the resource is removed even if it doesn't remove itself when closed
            resources.remove(resource);
          }
        }

        // It's possible for a thread registering a resource to register that resource after open
        // has been set to false and even after we've looped through and closed all the resources.
        // Since registering must be incremented *before* checking the state of open, however,
        // when we reach this point in that situation either the register call is still in progress
        // (registering > 0) or the new resource has been successfully added (resources not empty).
        // In either case, we just need to repeat the loop until there are no more register calls
        // in progress (no new calls can start and no resources left to close.
      } while (registering.get() > 0 || !resources.isEmpty());
      if (thrown != null) {
        throwIfInstanceOf(thrown, IOException.class);
        throwIfUnchecked(thrown);
      }
    }
  }
Closes the file system, runs the {@code onClose} callback and closes all registered resources.
jimfs/src/main/java/com/google/common/jimfs/FileSystemState.java