@Test
  public void testBucketImageProviderCacheClosesDuringBucketMove() {
    VM server1 = getVM(0);
    VM server2 = getVM(1);

    int redundantCopies = 0;
    String regionName = "region1";

    server1.invoke(() -> createPersistentPartitionedRegion(regionName, getUniqueName(),
        getDiskDirs(), redundantCopies));

    // Do puts before starting the second server so that we guarantee all buckets reside on the
    // first server. This way we ensure a rebalance should have some work to do.
    server1.invoke(() -> {
      doPuts(regionName);
    });

    // Recycling server 2 sets the "recreated" state on the partitioned buckets, which can
    // change the behavior during failed GII handling when receiving bucket images. See
    // AbstractDiskRegion.isRecreated.
    server2.invoke(() -> {
      createPersistentPartitionedRegion(regionName, getUniqueName(), getDiskDirs(),
          redundantCopies);
      getCache().close();
      createPersistentPartitionedRegion(regionName, getUniqueName(), getDiskDirs(),
          redundantCopies);
    });

    server1.invoke(() -> {
      InternalResourceManager manager = getCache().getInternalResourceManager();

      // This will cause a CacheClosedException to occur during rebalance, specifically
      // when a RequestImageMessage during any bucket GII is received.
      DistributionMessageObserver
          .setInstance(
              new CacheClosingDistributionMessageObserver("_B__" + regionName + "_", getCache()));

      try {
        doRebalance(false, manager);
      } catch (CacheClosedException ex) {
        // The CacheClosingDistributionMessageObserver will cause an expected CacheClosedException
      } finally {
        DistributionMessageObserver.setInstance(null);
      }

      // Rebuild the cache and retry the rebalance. We expect it to succeed because the
      // CacheClosingDistributionMessageObserver has been uninstalled.
      createPersistentPartitionedRegion(regionName, getUniqueName(), getDiskDirs(),
          redundantCopies);
      manager = getCache().getInternalResourceManager();
      RebalanceResults results = doRebalance(false, manager);

      // The rebalance should have done some work since the buckets were imbalanced
      assertThat(results.getTotalBucketTransfersCompleted() > 0).isTrue();
    });
  }
If the bucket image provider's cache is recycled while a bucket is moving during a rebalance,
we expect a subsequent rebalance will succeed after the cache is reconstructed.
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/control/RebalanceOperationDistributedTest.java