/**
   * Uses 'loader' to load class 'clzz', and calls the static method 'method'. If the return value
   * does not equal 'value' (or if an exception is thrown), then a test failure is indicated.
   *
   * <p>If 'value' is null, then no equality check is performed -- the assertion fails only if an
   * exception is thrown.
   */
  protected void assertStaticCallEquals(
      ClassLoader loader, Class clzz, String method, Object value) {
    java.lang.Class<?> cls = null;
    try {
      cls = java.lang.Class.forName(clzz.getName(), true, loader);
    } catch (ClassNotFoundException e) {
    }
    assertNotNull(cls);

    java.lang.reflect.Method m = null;
    try {
      m = cls.getMethod(method);
    } catch (NoSuchMethodException e) {
    }
    assertNotNull(m);

    try {
      Object res = m.invoke(null);
      assertNotNull(res);
      if (value != null) {
        assertEquals(res, value);
      }
    } catch (InvocationTargetException | IllegalAccessException e) {
      fail("Unexpected exception thrown: " + e.getCause(), e.getCause());
    }
  }
  /**
   * Creates a class which calls target::method(args) via invokevirtual, compiles and loads both the
   * new class and 'target', and then invokes the method. If an exception of type 'exceptionType' is
   * not thrown, then a test failure is indicated.
   */
  public void assertThrows(
      java.lang.Class<?> exceptionType,
      Class target,
      ConcreteMethod method,
      String returns,
      String... args) {

    Compiler compiler = compilerLocal.get();
    compiler.setFlags(compilerFlags());

    Class iv = invokeVirtualHarness(target, method, returns, args);
    ClassLoader loader = compiler.compile(iv, target);

    java.lang.Class<?> cls = null;
    try {
      cls = java.lang.Class.forName(iv.getName(), true, loader);
    } catch (ClassNotFoundException e) {
    }
    assertNotNull(cls);

    java.lang.reflect.Method m = null;
    try {
      m = cls.getMethod(method.getName());
    } catch (NoSuchMethodException e) {
    }
    assertNotNull(m);

    try {
      m.invoke(null);
      fail("Exception should have been thrown");
    } catch (InvocationTargetException | IllegalAccessException e) {
      if (verboseLocal.get() == Boolean.TRUE) {
        System.out.println(e.getCause());
      }
      assertTrue(exceptionType.isAssignableFrom(e.getCause().getClass()));
    }
    compiler.cleanup();
  }