ConfigurationStateUpdater { @VisibleForTesting PipelineInterpreter.State reload() { return reloadAndSave(); } @Inject  ConfigurationStateUpdater(RuleService ruleService,
                                     PipelineService pipelineService,
                                     PipelineStreamConnectionsService pipelineStreamConnectionsService,
                                     PipelineRuleParser pipelineRuleParser,
                                     MetricRegistry metricRegistry,
                                     FunctionRegistry functionRegistry,
                                     @Named("daemonScheduler") ScheduledExecutorService scheduler,
                                     EventBus serverEventBus,
                                     PipelineInterpreter.State.Factory stateFactory,
                                     @Named("generate_native_code") boolean allowCodeGeneration); static boolean isAllowCodeGeneration(); PipelineInterpreter.State getLatestState(); @Subscribe void handleRuleChanges(RulesChangedEvent event); @Subscribe void handlePipelineChanges(PipelinesChangedEvent event); @Subscribe void handlePipelineConnectionChanges(PipelineConnectionsChangedEvent event); @Subscribe void handlePipelineStateChange(PipelineInterpreter.State event);  }
@Test public void testClassUnloading() { final Injector injector = Guice.createInjector( new InMemoryServicesModule(), new ProcessorFunctionsModule(), new SchedulerBindings(), binder -> binder.install(new FactoryModuleBuilder().build(PipelineInterpreter.State.Factory.class)), binder -> binder.bindConstant().annotatedWith(Names.named("generate_native_code")).to(true), binder -> binder.bindConstant().annotatedWith(Names.named("cached_stageiterators")).to(true), binder -> binder.bindConstant().annotatedWith(Names.named("processbuffer_processors")).to(1), binder -> binder.bind(StreamService.class).to(DummyStreamService.class), binder -> binder.bind(GrokPatternService.class).to(InMemoryGrokPatternService.class), binder -> binder.bind(FunctionRegistry.class).asEagerSingleton(), binder -> binder.bind(MetricRegistry.class).toProvider(MetricRegistryProvider.class).asEagerSingleton() ); final MetricRegistry metricRegistry = injector.getInstance(MetricRegistry.class); final Gauge<Long> pipelineLoadedClasses = metricRegistry.register("jvm.cl.loaded-classes", (Gauge<Long>) () -> PipelineClassloader.loadedClasses.get()); final RuleService ruleService = injector.getInstance(RuleService.class); ruleService.save(RuleDao.create("00001", "some rule", "awesome rule", "rule \"arrsome\" when true then let x = now(); end", null, null)); final ConfigurationStateUpdater updater = injector.getInstance(ConfigurationStateUpdater.class); final Gauge<Long> unloadedClasses = metricRegistry.getGauges((name, metric) -> name.startsWith("jvm.cl.unloaded")).get("jvm.cl.unloaded"); long i = 0; final Long initialLoaded = pipelineLoadedClasses.getValue(); while (i++ < 100) { final long initialUnloaded = unloadedClasses.getValue(); this.reload = null; reload = updater.reload(); if (i % 10 == 0) { System.gc(); log.info("\nClassloading metrics:\n====================="); metricRegistry.getGauges((name, metric) -> name.startsWith("jvm.cl")).forEach((s, gauge) -> { log.info("{} : {}", s, gauge.getValue()); }); Assertions.assertThat(unloadedClasses.getValue()).isGreaterThan(initialUnloaded); } } Assertions.assertThat(pipelineLoadedClasses.getValue()).isGreaterThan(initialLoaded); }