private MemoryChunk connectChunks(final MemoryChunk firstChunk, final MemoryChunk secondChunk) {
    Preconditions.checkNotNull(firstChunk, "Error: First memory chunk can't be null");
    Preconditions.checkNotNull(secondChunk, "Error: Second memory chunk can't be null");
    Preconditions.checkArgument(
        secondChunk.getAddress() > firstChunk.getAddress(),
        "Error: Second memory chunk must start after the first memory chunk");

    final long newAddress = firstChunk.getAddress();

    MemoryChunk newChunk;

    if ((firstChunk.getAddress() + firstChunk.getLength()) == secondChunk.getAddress()) {
      // The two chunks fit perfectly together, it's only
      // necessary to concatenate them.

      final byte[] newData = concat(firstChunk.getBytes(), secondChunk.getBytes());

      newChunk = new MemoryChunk(newAddress, newData);
    } else {
      // The two chunks don't fit perfectly together.

      // Find out how many bytes to insert between the chunks.
      final int toFill =
          (int) (secondChunk.getAddress() - firstChunk.getAddress()) - firstChunk.getLength();

      // Create the new data array
      final byte[] newData = new byte[firstChunk.getLength() + toFill + secondChunk.getLength()];

      if (toFill > 0) {
        // If there is a gap between the two input chunks,
        // it is sufficient to copy the old data into the
        // new data array.
        // System.arraycopy(firstChunk.getBytes(), 0, newData, 0, firstChunk.getLength());
        // System.arraycopy(secondChunk.getBytes(), 0, newData, firstChunk.getLength() + toFill,
        // secondChunk.getLength());

        // Do not concatenate memory chunks with gaps
        // between them.

        return null;
      } else if (toFill < 0) {
        // If there is an overlap between the two memory
        // chunks, keep the data in the first chunk intact.

        System.arraycopy(firstChunk.getBytes(), 0, newData, 0, firstChunk.getLength());
        System.arraycopy(
            secondChunk.getBytes(),
            -toFill,
            newData,
            firstChunk.getLength(),
            secondChunk.getLength() + toFill);
      }

      newChunk = new MemoryChunk(newAddress, newData);
    }

    // Remove the two old chunks and insert the new chunk instead.
    removeChunk(firstChunk);
    removeChunk(secondChunk);

    insertChunk(newChunk);

    return newChunk;
  }
Connects two memory chunks, removes the two old chunks from memory, and inserts the new chunk
in their place.

@param firstChunk The first memory chunk.
@param secondChunk The second memory chunk.
@return The new memory chunk.
@throws NullPointerException Thrown if either of the two input chunks is null.
@throws IllegalArgumentException Thrown if the start address of the second memory chunk is
    smaller than or equal to the one of the first memory chunk.
java/zylib/src/main/java/com/google/security/zynamics/zylib/general/memmanager/Memory.java