docs: private void execute(Iterator<String> classNames) throws Throwable {
      final RunNotifier fNotifier = new OrderedRunNotifier();
      final Result result = new Result();
      final Writer debug = debugMessagesFile == null ? new NullWriter() : new OutputStreamWriter(new FileOutputStream(debugMessagesFile), "UTF-8");
  
      fNotifier.addListener(result.createListener());
  
      fNotifier.addListener(
          new StreamFlusherDecorator(
              new NoExceptionRunListenerDecorator(new RunListenerEmitter(serializer)) {
                @Override
                protected void exception(Throwable t) {
                  warn("Event serializer exception.", t);
                }
              }));
  
      fNotifier.addListener(new RunListener() {
        public void testRunFinished(Result result) throws Exception {
          debug(debug, "testRunFinished(T:" + result.getRunCount() + ";F:" + result.getFailureCount() + ";I:" + result.getIgnoreCount() + ")");
          serializer.flush();
        }
  
        @Override
        public void testRunStarted(Description description) throws Exception {
          debug(debug, "testRunStarted(" + description + ")");
          serializer.flush();
        }
        
        @Override
        public void testStarted(Description description) throws Exception {
          debug(debug, "testStarted(" + description + ")");
          serializer.flush();
        }
        
        public void testFinished(Description description) throws Exception {
          debug(debug, "testFinished(" + description + ")");
          serializer.flush();
        }
        
        @Override
        public void testIgnored(Description description) throws Exception {
          debug(debug, "testIgnored(T:" + description + ")");
        }
        
        @Override
        public void testFailure(Failure failure) throws Exception {
          debug(debug, "testFailure(T:" + failure + ")");
        }
        
        @Override
        public void testAssumptionFailure(Failure failure) {
          try {
            debug(debug, "testAssumptionFailure(T:" + failure + ")");
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        }
      });
  
      /*
       * Instantiate method filter if any.
       */
      String methodFilterGlob = Strings.emptyToNull(System.getProperty(SysGlobals.SYSPROP_TESTMETHOD()));
      Filter methodFilter = Filter.ALL;
      if (methodFilterGlob != null) {
        methodFilter = new MethodGlobFilter(methodFilterGlob);
      }
  
      /*
       * Important. Run each class separately so that we get separate 
       * {@link RunListener} callbacks for the top extracted description.
       */
      debug(debug, "Entering main suite loop.");
      try {
        while (classNames.hasNext()) {
          final String clName = classNames.next();
          debug(debug, "Instantiating: " + clName);
          Class<?> clazz = instantiate(clName);
          if (clazz == null) 
            continue;
    
          Request request = Request.aClass(clazz);
          try {
            Runner runner = request.getRunner();
            methodFilter.apply(runner);
  
            // New RunListener instances should be added per class and then removed from the RunNotifier
            ArrayList<RunListener> runListenerInstances = instantiateRunListeners();
            for (RunListener runListener : runListenerInstances) {
              fNotifier.addListener(runListener);
            }
  
            fNotifier.fireTestRunStarted(runner.getDescription());
            debug(debug, "Runner.run(" + clName + ")");
            runner.run(fNotifier);
            debug(debug, "Runner.done(" + clName + ")");
            fNotifier.fireTestRunFinished(result);
  
            for (RunListener runListener : runListenerInstances) {
              fNotifier.removeListener(runListener);
            }
          } catch (NoTestsRemainException e) {
            // Don't complain if all methods have been filtered out. 
            // I don't understand the reason why this exception has been
            // built in to filters at all.
          }
        }
      } catch (Throwable t) {
        debug(debug, "Main suite loop error: " + t);
        throw t;
      } finally {
        debug(debug, "Leaving main suite loop.");
        debug.close();
      }
    }