code: private void _fill () throws IOException
    {
      byte [] buffer = _getBufIfOpen ();
      if (m_nMarkPos < 0)
        m_nPos = 0; /* no mark: throw away the buffer */
      else
        if (m_nPos >= buffer.length) /* no room left in buffer */
          if (m_nMarkPos > 0)
          {
            /* can throw away early part of the buffer */
            final int sz = m_nPos - m_nMarkPos;
            System.arraycopy (buffer, m_nMarkPos, buffer, 0, sz);
            m_nPos = sz;
            m_nMarkPos = 0;
          }
          else
            if (buffer.length >= m_nMarkLimit)
            {
              /* buffer got too big, invalidate mark */
              m_nMarkPos = -1;
              /* drop buffer contents */
              m_nPos = 0;
            }
            else
            {
              /* grow buffer */
              int nsz = m_nPos * 2;
              if (nsz > m_nMarkLimit)
                nsz = m_nMarkLimit;
              final byte [] nbuf = new byte [nsz];
              System.arraycopy (buffer, 0, nbuf, 0, m_nPos);
              if (!s_aBufUpdater.compareAndSet (this, buffer, nbuf))
              {
                // Can't replace buf if there was an async close.
                // Note: This would need to be changed if fill()
                // is ever made accessible to multiple threads.
                // But for now, the only way CAS can fail is via close.
                // assert buf == null;
                throw new IOException ("Stream closed");
              }
              buffer = nbuf;
            }
      m_nCount = m_nPos;
      // Potentially blocking read
      final int n = _getInIfOpen ().read (buffer, m_nPos, buffer.length - m_nPos);
      if (n > 0)
        m_nCount = n + m_nPos;
    }
docs: Fills the buffer with more data, taking into account shuffling and other
  tricks for dealing with marks. Assumes that it is being called by a method.
  This method also assumes that all data has already been read in, hence pos
  > count.