@Test
  public void testLABChunkQueue() throws Exception {
    ChunkCreator oldInstance = null;
    try {
      MemStoreLABImpl mslab = new MemStoreLABImpl();
      // by default setting, there should be no chunks initialized in the pool
      assertTrue(mslab.getPooledChunks().isEmpty());
      oldInstance = ChunkCreator.instance;
      ChunkCreator.instance = null;
      // reset mslab with chunk pool
      Configuration conf = HBaseConfiguration.create();
      conf.setDouble(MemStoreLAB.CHUNK_POOL_MAXSIZE_KEY, 0.1);
      // set chunk size to default max alloc size, so we could easily trigger chunk retirement
      conf.setLong(CHUNK_SIZE_KEY, MemStoreLABImpl.MAX_ALLOC_DEFAULT);
      // reconstruct mslab
      long globalMemStoreLimit =
        (long) (ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax()
          * MemorySizeUtil.getGlobalMemStoreHeapPercent(conf, false));
      ChunkCreator.initialize(MemStoreLABImpl.MAX_ALLOC_DEFAULT, false, globalMemStoreLimit, 0.1f,
        MemStoreLAB.POOL_INITIAL_SIZE_DEFAULT, null,
        MemStoreLAB.INDEX_CHUNK_SIZE_PERCENTAGE_DEFAULT);
      ChunkCreator.clearDisableFlag();
      mslab = new MemStoreLABImpl(conf);
      // launch multiple threads to trigger frequent chunk retirement
      List<Thread> threads = new ArrayList<>();
      final KeyValue kv = new KeyValue(Bytes.toBytes("r"), Bytes.toBytes("f"), Bytes.toBytes("q"),
        new byte[MemStoreLABImpl.MAX_ALLOC_DEFAULT - 32]);
      for (int i = 0; i < 10; i++) {
        threads.add(getChunkQueueTestThread(mslab, "testLABChunkQueue-" + i, kv));
      }
      for (Thread thread : threads) {
        thread.start();
      }
      // let it run for some time
      Thread.sleep(1000);
      for (Thread thread : threads) {
        thread.interrupt();
      }
      boolean threadsRunning = true;
      boolean alive = false;
      while (threadsRunning) {
        alive = false;
        for (Thread thread : threads) {
          if (thread.isAlive()) {
            alive = true;
            break;
          }
        }
        if (!alive) {
          threadsRunning = false;
        }
      }
      // none of the chunkIds would have been returned back
      assertTrue("All the chunks must have been cleared",
        ChunkCreator.instance.numberOfMappedChunks() != 0);
      Set<Integer> chunkIds = new HashSet<Integer>(mslab.chunks);
      int pooledChunksNum = mslab.getPooledChunks().size();
      // close the mslab
      mslab.close();
      // make sure all chunks where reclaimed back to pool
      int queueLength = mslab.getNumOfChunksReturnedToPool(chunkIds);
      assertTrue(
        "All chunks in chunk queue should be reclaimed or removed"
          + " after mslab closed but actually: " + (pooledChunksNum - queueLength),
        pooledChunksNum - queueLength == 0);
    } finally {
      ChunkCreator.instance = oldInstance;
    }
  }
Test frequent chunk retirement with chunk pool triggered by lots of threads, making sure
there's no memory leak (HBASE-16195)
@throws Exception if any error occurred
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java