public ROW next() {
    Preconditions.checkState(hasNext());
    if (!readBufferUsed) {
      try {
        if (input == null && output != null) {
          // Close output stream if open
          output.close();
          output = null;

          FileInputStream fis = null;
          try {
            fis = new FileInputStream(tmpFile);
            input = new Input(fis);
          } finally {
            if (input == null && fis != null) {
              fis.close();
            }
          }
        }
        if (input != null) {
          // Load next batch from disk
          if (rowsOnDisk >= IN_MEMORY_NUM_ROWS) {
            rowsInReadBuffer = IN_MEMORY_NUM_ROWS;
          } else {
            rowsInReadBuffer = rowsOnDisk;
          }

          Kryo kryo = SerializationUtilities.borrowKryo();
          try {
            for (int i = 0; i < rowsInReadBuffer; i++) {
              readBuffer[i] = (ROW) kryo.readClassAndObject(input);
            }
          } finally {
            SerializationUtilities.releaseKryo(kryo);
          }

          if (input.end()) {
            input.close();
            input = null;
          }

          readBufferUsed = true;
          readCursor = 0;
          rowsOnDisk -= rowsInReadBuffer;
        }
      } catch (Exception e) {
        clear(); // Clean up the cache
        throw new RuntimeException("Failed to load rows from disk", e);
      }
    }

    ROW row = readBuffer[readCursor];
    if (++readCursor >= rowsInReadBuffer) {
      readBufferUsed = false;
      rowsInReadBuffer = 0;
      readCursor = 0;
    }
    return row;
  }
An eager object container that puts every row directly to output stream.
The object can be of any type.
Kryo is used for the serialization/deserialization.
When reading, we load IN_MEMORY_NUM_ROWS rows from input stream to memory batch by batch.
ql/src/java/org/apache/hadoop/hive/ql/exec/persistence/ObjectContainer.java