public static synchronized void assertCoverage(boolean includeInnerClasses, Class<?>... classes) {

    if (!_dynamicallyInstrumented) {
      return;
    }

    _instrumentation.removeTransformer(_coberturaClassFileTransformer);

    _coberturaClassFileTransformer = null;

    try {
      ProjectData projectData = ProjectDataUtil.captureProjectData();

      List<AssertionError> assertionErrors = new ArrayList<>();

      for (Class<?> clazz : classes) {
        ClassData classData = projectData.getClassData(clazz.getName());

        _assertClassDataCoverage(assertionErrors, clazz, classData);

        if (includeInnerClasses) {
          Class<?>[] declaredClasses = clazz.getDeclaredClasses();

          declaredClass:
          for (Class<?> declaredClass : declaredClasses) {
            for (Class<?> clazz2 : classes) {
              if (clazz2.equals(declaredClass)) {
                continue declaredClass;
              }
            }

            classData = projectData.getClassData(declaredClass.getName());

            _assertClassDataCoverage(assertionErrors, declaredClass, classData);
          }
        }
      }

      if (!assertionErrors.isEmpty()) {
        AssertionError assertionError = assertionErrors.get(0);

        for (int i = 1; i < assertionErrors.size(); i++) {
          assertionError.addSuppressed(assertionErrors.get(i));
        }

        throw assertionError;
      }
    } finally {
      System.clearProperty("junit.code.coverage");

      _dynamicallyInstrumented = false;

      if (_originalClassDefinitions != null) {
        try {
          List<ClassDefinition> classDefinitions =
              new ArrayList<>(_originalClassDefinitions.size());

          for (int i = 0; i < _originalClassDefinitions.size(); i++) {
            OriginalClassDefinition originalClassDefinition = _originalClassDefinitions.get(i);

            ClassDefinition classDefinition = originalClassDefinition.toClassDefinition();

            if (classDefinition != null) {
              classDefinitions.add(classDefinition);
            }
          }

          _originalClassDefinitions = null;

          _instrumentation.redefineClasses(
              classDefinitions.toArray(new ClassDefinition[classDefinitions.size()]));
        } catch (Exception e) {
          throw new RuntimeException("Unable to uninstrument classes", e);
        }
      }
    }
  }
 public static void initialize() {
   ProjectDataUtil.addMergeHook();
 }