code: public void open(final MutableObjectIterator<BT> buildSide,	final MutableObjectIterator<PT> probeSide,
  		boolean buildOuterJoin) throws IOException {
  
  		this.buildSideOuterJoin = buildOuterJoin;
  
  		// sanity checks
  		if (!this.closed.compareAndSet(true, false)) {
  			throw new IllegalStateException("Hash Join cannot be opened, because it is currently not closed.");
  		}
  		
  		// grab the write behind buffers first
  		for (int i = this.numWriteBehindBuffers; i > 0; --i) {
  			this.writeBehindBuffers.add(this.availableMemory.remove(this.availableMemory.size() - 1));
  		}
  		// open builds the initial table by consuming the build-side input
  		this.currentRecursionDepth = 0;
  		buildInitialTable(buildSide);
  		
  		// the first prober is the probe-side input
  		this.probeIterator = new ProbeIterator<PT>(probeSide, this.probeSideSerializer.createInstance());
  		
  		// the bucket iterator can remain constant over the time
  		this.bucketIterator = new HashBucketIterator<BT, PT>(this.buildSideSerializer, this.recordComparator, probedSet, buildOuterJoin);
  	}
docs: Opens the hash join. This method reads the build-side input and constructs the initial
  hash table, gradually spilling partitions that do not fit into memory.
  
  @param buildSide      Build side input.
  @param probeSide      Probe side input.
  @param buildOuterJoin Whether outer join on build side.
  @throws IOException Thrown, if an I/O problem occurs while spilling a partition.