private static @Nullable LoaderData readFromIndex(Path index) {
    long started = System.nanoTime();
    boolean isOk = false;
    short version = -1;
    try (SeekableByteChannel channel = Files.newByteChannel(index, READ_OPTIONS)) {
      ByteBuffer buffer = DirectByteBufferPool.DEFAULT_POOL.allocate((int)channel.size());
      try {
        do {
          channel.read(buffer);
        }
        while (buffer.hasRemaining());
        buffer.flip();

        // little endian - native order for Intel and Apple ARM
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        version = buffer.getShort();
        if (version == indexFileVersion) {
          long[] classPackageHashes = new long[buffer.getInt()];
          long[] resourcePackageHashes = new long[buffer.getInt()];
          LongBuffer longBuffer = buffer.asLongBuffer();
          longBuffer.get(classPackageHashes);
          longBuffer.get(resourcePackageHashes);
          buffer.position(buffer.position() + (longBuffer.position() * Long.BYTES));
          LoaderData loaderData = new LoaderData(resourcePackageHashes, classPackageHashes, new NameFilter(new Xor16(buffer)));
          isOk = true;
          return loaderData;
        }
      }
      finally {
        DirectByteBufferPool.DEFAULT_POOL.release(buffer);
      }
    }
    catch (NoSuchFileException ignore) {
      isOk = true;
    }
    catch (Exception e) {
      //noinspection UseOfSystemOutOrSystemErr
      System.err.println("Cannot read classpath index (version=" + version + ", module=" + index.getParent().getFileName() + ")");
      //noinspection CallToPrintStackTrace
      e.printStackTrace();
    }
    finally {
      if (!isOk) {
        try {
          Files.deleteIfExists(index);
        }
        catch (IOException ignore) {
        }
      }
      totalReading.addAndGet(System.nanoTime() - started);
    }

    return null;
  }
private static @Nullable LoaderData readFromIndex(Path index)