@SuppressWarnings({"ConstantConditions", "unchecked"}) @Test @BadApple public void testIndexShardLifecycleLeak() throws Exception { client() .admin() .indices() .prepareCreate("test") .setSettings( ImmutableSettings.builder() .put("index.number_of_shards", 1) .put("index.number_of_replicas", 0)) .execute() .actionGet(); client().admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet(); IndicesService indicesService = cluster().getInstance(IndicesService.class); IndexService indexService = indicesService.indexServiceSafe("test"); Injector indexInjector = indexService.injector(); IndexShard shard = indexService.shardSafe(0); Injector shardInjector = indexService.shardInjector(0); performCommonOperations(); List<WeakReference> indexReferences = new ArrayList<WeakReference>(); List<WeakReference> shardReferences = new ArrayList<WeakReference>(); // TODO if we could iterate over the already created classes on the injector, we can just add // them here to the list // for now, we simple add some classes that make sense // add index references indexReferences.add(new WeakReference(indexService)); indexReferences.add(new WeakReference(indexInjector)); indexReferences.add(new WeakReference(indexService.mapperService())); for (DocumentMapper documentMapper : indexService.mapperService()) { indexReferences.add(new WeakReference(documentMapper)); } indexReferences.add(new WeakReference(indexService.aliasesService())); indexReferences.add(new WeakReference(indexService.analysisService())); indexReferences.add(new WeakReference(indexService.fieldData())); indexReferences.add(new WeakReference(indexService.queryParserService())); // add shard references shardReferences.add(new WeakReference(shard)); shardReferences.add(new WeakReference(shardInjector)); indexService = null; indexInjector = null; shard = null; shardInjector = null; client().admin().indices().prepareDelete().execute().actionGet(); for (int i = 0; i < 100; i++) { System.gc(); int indexNotCleared = 0; for (WeakReference indexReference : indexReferences) { if (indexReference.get() != null) { indexNotCleared++; } } int shardNotCleared = 0; for (WeakReference shardReference : shardReferences) { if (shardReference.get() != null) { shardNotCleared++; } } logger.info( "round {}, indices {}/{}, shards {}/{}", i, indexNotCleared, indexReferences.size(), shardNotCleared, shardReferences.size()); if (indexNotCleared == 0 && shardNotCleared == 0) { break; } } // Thread.sleep(1000000); for (WeakReference indexReference : indexReferences) { assertThat( "dangling index reference: " + indexReference.get(), indexReference.get(), nullValue()); } for (WeakReference shardReference : shardReferences) { assertThat( "dangling shard reference: " + shardReference.get(), shardReference.get(), nullValue()); } }