public synchronized void assertPointersAreDisposed() {
    if (!isTracking) {
      throw new IllegalStateException("Double call of assertPointersAreDisposed() - see 'Caused by:' for the previous call", trace);
    }

    List<VirtualFilePointer> pointers = new ArrayList<>(dumpAllPointers());
    for (int i = pointers.size() - 1; i >= 0; i--) {
      VirtualFilePointer pointer = pointers.get(i);
      if (storedPointers.remove(pointer)) {
        pointers.remove(i);
      }
    }

    try {
      Set<VirtualFilePointer> leaked = CollectionFactory.createCustomHashingStrategySet(new HashingStrategy<>() {
        @Override
        public int hashCode(@Nullable VirtualFilePointer pointer) {
          if (pointer == null) {
            return 0;
          }
          String url = pointer.getUrl();
          return SystemInfoRt.isFileSystemCaseSensitive ? url.hashCode() : Strings.stringHashCodeInsensitive(url);
        }

        @Override
        public boolean equals(VirtualFilePointer o1, VirtualFilePointer o2) {
          return o1 == o2 || (o1 != null && o2 != null &&
                              (SystemInfoRt.isFileSystemCaseSensitive
                               ? o1.getUrl().equals(o2.getUrl())
                               : o1.getUrl().equalsIgnoreCase(o2.getUrl())));
        }
      });
      leaked.addAll(pointers);
      leaked.removeAll(storedPointers);

      for (VirtualFilePointer pointer : leaked) {
        ((VirtualFilePointerImpl)pointer).throwDisposalError("Virtual pointer '" + pointer + "' hasn't been disposed:\n" +
                                                             ((VirtualFilePointerImpl)pointer).getStackTrace());
      }
    }
    finally {
      storedPointers.clear();
      trace = new Throwable();
      isTracking = false;
    }
  }
public synchronized void assertPointersAreDisposed()