@Test
  public void test() throws Exception {
    HRegionServer regionSvr = UTIL.getRSForFirstRegionInTable(TABLE_NAME);
    HRegion region = regionSvr.getRegions(TABLE_NAME).get(0);
    String regName = region.getRegionInfo().getEncodedName();
    List<HRegion> metaRegs = regionSvr.getRegions(TableName.META_TABLE_NAME);
    if (metaRegs != null && !metaRegs.isEmpty()) {
      LOG.info("meta is on the same server: " + regionSvr);
      // when region is on same server as hbase:meta, reassigning meta would abort the server
      // since WAL is broken.
      // so the region is moved to a different server
      HRegionServer otherRs = UTIL.getOtherRegionServer(regionSvr);
      UTIL.moveRegionAndWait(region.getRegionInfo(), otherRs.getServerName());
      LOG.info("Moved region: " + regName + " to " + otherRs.getServerName());
    }
    HRegionServer rsToSuspend = UTIL.getRSForFirstRegionInTable(TABLE_NAME);
    region = rsToSuspend.getRegions(TABLE_NAME).get(0);

    ZKWatcher watcher = UTIL.getZooKeeperWatcher();
    watcher.getRecoverableZooKeeper().delete(
      ZNodePaths.joinZNode(watcher.getZNodePaths().rsZNode, rsToSuspend.getServerName().toString()),
      -1);
    LOG.info("suspending " + rsToSuspend);
    UTIL.waitFor(60000, 1000, new ExplainingPredicate<Exception>() {

      @Override
      public boolean evaluate() throws Exception {
        for (RegionServerThread thread : UTIL.getHBaseCluster().getRegionServerThreads()) {
          HRegionServer rs = thread.getRegionServer();
          if (rs != rsToSuspend) {
            return !rs.getRegions(TABLE_NAME).isEmpty();
          }
        }
        return false;
      }

      @Override
      public String explainFailure() throws Exception {
        return "The region for " + TABLE_NAME + " is still on " + rsToSuspend.getServerName();
      }
    });
    try {
      region.compact(true);
      fail("Should fail as our wal file has already been closed, "
        + "and walDir has also been renamed");
    } catch (Exception e) {
      LOG.debug("expected exception: ", e);
    }
    Table table = UTIL.getConnection().getTable(TABLE_NAME);
    // should not hit FNFE
    for (int i = 0; i < 20; i++) {
      assertEquals(i, Bytes.toInt(table.get(new Get(Bytes.toBytes(i))).getValue(CF, CQ)));
    }
  }
This testcase is used to ensure that the compaction marker will fail a compaction if the RS is
already dead. It can not eliminate FNFE when scanning but it does reduce the possibility a lot.
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCompactionInDeadRegionServer.java