Example usage for org.objectweb.asm.commons GeneratorAdapter invokeConstructor

List of usage examples for org.objectweb.asm.commons GeneratorAdapter invokeConstructor

Introduction

In this page you can find the example usage for org.objectweb.asm.commons GeneratorAdapter invokeConstructor.

Prototype

public void invokeConstructor(final Type type, final Method method) 

Source Link

Document

Generates the instruction to invoke a constructor.

Usage

From source file:co.cask.cdap.internal.app.runtime.batch.distributed.ContainerLauncherGenerator.java

License:Apache License

/**
 * Generates the bytecode for a main class and writes to the given {@link JarOutputStream}.
 * The generated class looks like this://from   w  w  w  .  j  a v  a2 s .c  o m
 *
 * <pre>{@code
 * class className {
 *   public static void main(String[] args) {
 *     MapReduceContainerLauncher.launch(launcherClassPath, classLoaderName, className, args);
 *   }
 * }
 * }
 * </pre>
 *
 * The {@code launcherClassPath}, {@code classLoaderName} and {@code className} are represented as
 * string literals in the generated class.
 */
private static void generateLauncherClass(String launcherClassPath, String classLoaderName, String className,
        JarOutputStream output) throws IOException {
    String internalName = className.replace('.', '/');

    ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    classWriter.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, internalName, null,
            Type.getInternalName(Object.class), null);

    Method constructor = Methods.getMethod(void.class, "<init>");

    // Constructor
    // MRAppMaster()
    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, constructor, null, null, classWriter);

    mg.loadThis();
    mg.invokeConstructor(Type.getType(Object.class), constructor);
    mg.returnValue();
    mg.endMethod();

    // Main method.
    // public static void main(String[] args) {
    //   MapReduceContainerLauncher.launch(launcherClassPath, classLoaderName, className, args);
    // }
    Method mainMethod = Methods.getMethod(void.class, "main", String[].class);
    mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, mainMethod, null,
            new Type[] { Type.getType(Exception.class) }, classWriter);

    mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
    mg.visitLdcInsn("Launch class " + className);
    mg.invokeVirtual(Type.getType(PrintStream.class), Methods.getMethod(void.class, "println", String.class));

    // The Launcher classpath, classloader name and main classname are stored as string literal in the generated class
    mg.visitLdcInsn(launcherClassPath);
    mg.visitLdcInsn(classLoaderName);
    mg.visitLdcInsn(className);
    mg.loadArg(0);
    mg.invokeStatic(Type.getType(MapReduceContainerLauncher.class),
            Methods.getMethod(void.class, "launch", String.class, String.class, String.class, String[].class));
    mg.returnValue();
    mg.endMethod();

    classWriter.visitEnd();

    output.putNextEntry(new JarEntry(internalName + ".class"));
    output.write(classWriter.toByteArray());
}

From source file:co.cask.cdap.internal.app.runtime.batch.distributed.ContainerLauncherGenerator.java

License:Apache License

/**
 * Generates a class that has a static main method which delegates the call to a static method in the given delegator
 * class with method signature {@code public static void launch(String className, String[] args)}
 *
 * @param className the classname of the generated class
 * @param mainDelegator the class to delegate the main call to
 * @param output for writing the generated bytes
 *//*from   w  w w . j av  a  2  s  .c o  m*/
private static void generateMainClass(String className, Type mainDelegator, JarOutputStream output)
        throws IOException {
    String internalName = className.replace('.', '/');

    ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    classWriter.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, internalName, null,
            Type.getInternalName(Object.class), null);

    // Generate the default constructor, which just call super()
    Method constructor = Methods.getMethod(void.class, "<init>");
    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, constructor, null, null, classWriter);
    mg.loadThis();
    mg.invokeConstructor(Type.getType(Object.class), constructor);
    mg.returnValue();
    mg.endMethod();

    // Generate the main method
    // public static void main(String[] args) {
    //   System.out.println("Launch class .....");
    //   <MainDelegator>.launch(<className>, args);
    // }
    Method mainMethod = Methods.getMethod(void.class, "main", String[].class);
    mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, mainMethod, null,
            new Type[] { Type.getType(Exception.class) }, classWriter);

    mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
    mg.visitLdcInsn("Launch class " + className + " by calling " + mainDelegator.getClassName() + ".launch");
    mg.invokeVirtual(Type.getType(PrintStream.class), Methods.getMethod(void.class, "println", String.class));

    // The main classname is stored as string literal in the generated class
    mg.visitLdcInsn(className);
    mg.loadArg(0);
    mg.invokeStatic(mainDelegator, Methods.getMethod(void.class, "launch", String.class, String[].class));
    mg.returnValue();
    mg.endMethod();

    classWriter.visitEnd();

    output.putNextEntry(new JarEntry(internalName + ".class"));
    output.write(classWriter.toByteArray());
}

From source file:co.cask.cdap.internal.app.runtime.service.http.HttpHandlerGenerator.java

License:Apache License

/**
 * Generates the constructor. The constructor generated has signature {@code (DelegatorContext, MetricsContext)}.
 *///from  w  w  w  . j  av a 2s  .c o  m
private void generateConstructor(TypeToken<? extends HttpServiceHandler> delegateType,
        ClassWriter classWriter) {
    Method constructor = Methods.getMethod(void.class, "<init>", DelegatorContext.class, MetricsContext.class);
    String signature = Signatures.getMethodSignature(constructor, getContextType(delegateType),
            TypeToken.of(MetricsContext.class));

    // Constructor(DelegatorContext, MetricsContext)
    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, constructor, signature, null, classWriter);

    // super(context, metricsContext);
    mg.loadThis();
    mg.loadArg(0);
    mg.loadArg(1);
    mg.invokeConstructor(Type.getType(AbstractHttpHandlerDelegator.class),
            Methods.getMethod(void.class, "<init>", DelegatorContext.class, MetricsContext.class));
    mg.returnValue();
    mg.endMethod();
}

From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java

License:Apache License

/**
 * Generates the constructor. The constructor generated has signature {@code (Schema, FieldAccessorFactory)}.
 *//*from  w  w w  .j av a2  s.  c o  m*/
private void generateConstructor() {
    Method constructor = getMethod(void.class, "<init>", Schema.class, FieldAccessorFactory.class);

    // Constructor(Schema schema, FieldAccessorFactory accessorFactory)
    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, constructor, null, null, classWriter);

    // super(); // Calling Object constructor
    mg.loadThis();
    mg.invokeConstructor(Type.getType(Object.class), getMethod(void.class, "<init>"));

    // if (!SCHEMA_HASH.equals(schema.getSchemaHash().toString())) { throw IllegalArgumentException }
    mg.getStatic(classType, "SCHEMA_HASH", Type.getType(String.class));
    mg.loadArg(0);
    mg.invokeVirtual(Type.getType(Schema.class), getMethod(SchemaHash.class, "getSchemaHash"));
    mg.invokeVirtual(Type.getType(SchemaHash.class), getMethod(String.class, "toString"));
    mg.invokeVirtual(Type.getType(String.class), getMethod(boolean.class, "equals", Object.class));
    Label hashEquals = mg.newLabel();
    mg.ifZCmp(GeneratorAdapter.NE, hashEquals);
    mg.throwException(Type.getType(IllegalArgumentException.class), "Schema not match.");
    mg.mark(hashEquals);

    // this.schema = schema;
    mg.loadThis();
    mg.loadArg(0);
    mg.putField(classType, "schema", Type.getType(Schema.class));

    // For each record field that needs an accessor, get the accessor and store it in field.
    for (Map.Entry<TypeToken<?>, String> entry : fieldAccessorRequests.entries()) {
        String fieldAccessorName = getFieldAccessorName(entry.getKey(), entry.getValue());

        classWriter.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, fieldAccessorName,
                Type.getDescriptor(FieldAccessor.class), null, null);
        // this.fieldAccessorName
        //  = accessorFactory.getFieldAccessor(TypeToken.of(Class.forName("className")), "fieldName");
        mg.loadThis();
        mg.loadArg(1);
        mg.push(entry.getKey().getRawType().getName());
        mg.invokeStatic(Type.getType(Class.class), getMethod(Class.class, "forName", String.class));
        mg.invokeStatic(Type.getType(TypeToken.class), getMethod(TypeToken.class, "of", Class.class));
        mg.push(entry.getValue());
        mg.invokeInterface(Type.getType(FieldAccessorFactory.class),
                getMethod(FieldAccessor.class, "getFieldAccessor", TypeToken.class, String.class));
        mg.putField(classType, fieldAccessorName, Type.getType(FieldAccessor.class));
    }

    mg.returnValue();
    mg.endMethod();
}

From source file:co.cask.cdap.internal.io.FieldAccessorGenerator.java

License:Apache License

private void generateConstructor(Field field) {
    if (isPrivate) {
        classWriter.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, "field",
                Type.getDescriptor(Field.class), null, null).visitEnd();
    }//from ww  w  .j a v a 2  s . c  o  m

    // Constructor(Type classType)
    Method constructor = getMethod(void.class, "<init>", java.lang.reflect.Type.class);
    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, constructor, null, new Type[0], classWriter);
    mg.loadThis();
    mg.loadArg(0);
    mg.invokeConstructor(Type.getType(AbstractFieldAccessor.class), constructor);
    if (isPrivate) {
        initializeReflectionField(mg, field);
    }

    mg.returnValue();
    mg.endMethod();
}

From source file:co.cask.common.internal.io.FieldAccessorGenerator.java

License:Apache License

private void generateConstructor(Field field) {
    if (isPrivate) {
        classWriter.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, "field",
                Type.getDescriptor(Field.class), null, null).visitEnd();
    }/*  w w  w . j a  v  a 2s  . c  o  m*/

    // Constructor(TypeToken<?> classType)
    GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC,
            getMethod(void.class, "<init>", TypeToken.class), null, new Type[0], classWriter);
    mg.loadThis();
    mg.loadArg(0);
    mg.invokeConstructor(Type.getType(AbstractFieldAccessor.class),
            getMethod(void.class, "<init>", TypeToken.class));
    if (isPrivate) {
        initializeReflectionField(mg, field);
    }

    mg.returnValue();
    mg.endMethod();
}

From source file:com.android.build.gradle.internal.incremental.StringSwitch.java

License:Apache License

/**
 * Generates a standard error exception with message similar to:
 *
 *    String switch could not find 'equals.(Ljava/lang/Object;)Z' with hashcode 0
 *    in com/example/basic/GrandChild/*  w w  w .j a v  a  2s . c  o  m*/
 *
 * @param mv The generator adaptor used to emit the lookup switch code.
 * @param visitedClassName The abstract string trie structure.
 */
void writeMissingMessageWithHash(GeneratorAdapter mv, String visitedClassName) {
    mv.newInstance(INSTANT_RELOAD_EXCEPTION_TYPE);
    mv.dup();
    mv.push("String switch could not find '%s' with hashcode %s in %s");
    mv.push(3);
    mv.newArray(OBJECT_TYPE);
    mv.dup();
    mv.push(0);
    visitString();
    mv.arrayStore(OBJECT_TYPE);
    mv.dup();
    mv.push(1);
    visitString();
    visitHashMethod(mv);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
    mv.arrayStore(OBJECT_TYPE);
    mv.dup();
    mv.push(2);
    mv.push(visitedClassName);
    mv.arrayStore(OBJECT_TYPE);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "format",
            "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;", false);
    mv.invokeConstructor(INSTANT_RELOAD_EXCEPTION_TYPE, Method.getMethod("void <init> (String)"));
    mv.throwException();
}

From source file:com.changingbits.Builder.java

License:Apache License

/** Build a {@link LongRangeMultiSet} implementation to
 *  lookup intervals for a given point./*from  w  w w. ja va2s .  com*/
 *
 *  @param useAsm If true, the tree will be compiled to
 *  java bytecodes using the {@code asm} library; typically
 *  this results in a faster (~3X) implementation. */
public LongRangeMultiSet getMultiSet(boolean useAsm, boolean useArrayImpl) {

    finish(useArrayImpl);

    if (useAsm) {
        StringBuilder sb = new StringBuilder();
        sb.append('\n');
        int count = 0;
        for (LongRange range : ranges) {
            sb.append("// range ");
            sb.append(count++);
            sb.append(": ");
            sb.append(range);
            sb.append('\n');
        }
        sb.append('\n');
        sb.append("int upto = 0;\n");
        buildJavaSource(root, 0, sb);
        String javaSource = sb.toString();
        //System.out.println("java: " + javaSource);

        ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
        classWriter.visit(Opcodes.V1_7,
                Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC,
                COMPILED_TREE_CLASS.replace('.', '/'), null, LONG_RANGE_MULTI_SET_TYPE.getInternalName(), null);
        classWriter.visitSource(javaSource, null);

        Method m = Method.getMethod("void <init> ()");
        GeneratorAdapter constructor = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, m, null,
                null, classWriter);
        constructor.loadThis();
        constructor.loadArgs();
        constructor.invokeConstructor(LONG_RANGE_MULTI_SET_TYPE, m);
        constructor.returnValue();
        constructor.endMethod();

        GeneratorAdapter gen = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, LOOKUP_METHOD,
                null, null, classWriter);
        //Label labelTop = new Label();
        //Label labelEnd = new Label();
        //gen.visitLabel(labelTop);
        int uptoLocal = gen.newLocal(Type.INT_TYPE);
        //System.out.println("uptoLocal=" + uptoLocal);
        // nocommit is this not needed!?
        //gen.visitLocalVariable("upto", "I", null, labelTop, labelEnd, uptoLocal);
        gen.push(0);
        gen.storeLocal(uptoLocal, Type.INT_TYPE);
        buildAsm(gen, root, uptoLocal);
        // Return upto:
        gen.loadLocal(uptoLocal, Type.INT_TYPE);
        gen.returnValue();
        //gen.visitLabel(labelEnd);
        gen.endMethod();
        classWriter.visitEnd();

        byte[] bytes = classWriter.toByteArray();

        // javap -c /x/tmp/my.class
        /*
        try {
          FileOutputStream fos = new FileOutputStream(new File("/x/tmp/my.class"));
          fos.write(bytes);
          fos.close();
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        */

        // nocommit allow changing the class loader
        Class<? extends LongRangeMultiSet> treeClass = new Loader(LongRangeMultiSet.class.getClassLoader())
                .define(COMPILED_TREE_CLASS, classWriter.toByteArray());
        try {
            return treeClass.getConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException
                | InvocationTargetException e) {
            throw new RuntimeException(e);
        }

    } else if (useArrayImpl) {
        return new ArrayLongRangeMultiSet(root);
    } else {
        return new SimpleLongRangeMultiSet(root);
    }
}

From source file:com.changingbits.Builder.java

License:Apache License

public LongRangeCounter getCounter(boolean useAsm) {
    finish(false);/*from  w ww .  j  a va 2  s  .  co m*/
    if (useAsm) {
        StringBuilder sb = new StringBuilder();
        sb.append('\n');
        int count = 0;
        for (LongRange range : ranges) {
            sb.append("// range ");
            sb.append(count++);
            sb.append(": ");
            sb.append(range);
            sb.append('\n');
        }
        sb.append('\n');
        buildJavaCounterSource(root, 0, sb, false);
        String javaSource = sb.toString();
        //System.out.println("javaSource:\n" + javaSource);

        ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
        classWriter.visit(Opcodes.V1_7,
                Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC,
                COMPILED_COUNTER_CLASS.replace('.', '/'), null, BASE_LONG_RANGE_COUNTER_TYPE.getInternalName(),
                null);
        classWriter.visitSource(javaSource, null);
        Method m = Method.getMethod("void <init> (com.changingbits.Node, int, int)");
        GeneratorAdapter constructor = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, m, null,
                null, classWriter);
        constructor.loadThis();
        constructor.loadArgs();
        constructor.invokeConstructor(Type.getType(BaseLongRangeCounter.class), m);
        constructor.returnValue();
        constructor.endMethod();

        GeneratorAdapter gen = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, ADD_METHOD,
                null, null, classWriter);
        buildCounterAsm(gen, root, false);
        gen.returnValue();
        gen.endMethod();
        classWriter.visitEnd();

        byte[] bytes = classWriter.toByteArray();

        // javap -c /x/tmp/my.class
        /*
        try {
          FileOutputStream fos = new FileOutputStream(new File("/x/tmp/counter.class"));
          fos.write(bytes);
          fos.close();
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        */

        // nocommit allow changing the class loader
        Class<? extends LongRangeCounter> cl = new CounterLoader(LongRangeCounter.class.getClassLoader())
                .define(COMPILED_COUNTER_CLASS, classWriter.toByteArray());
        try {
            return cl.getConstructor(Node.class, int.class, int.class).newInstance(root,
                    elementaryIntervals.size(), ranges.length);
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException
                | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    } else {
        return new SimpleLongRangeCounter(root, elementaryIntervals, ranges.length);
    }
}

From source file:com.changingbits.Builder.java

License:Apache License

public LongRangeCounter getCounter2() {
    finish(false);/*from   w ww  . ja  va2 s.  co  m*/

    // Maps each range to the leaf counts that contribute to it:
    Map<Integer, List<Integer>> rangeToLeaf = new HashMap<>();
    buildRangeToLeaf(root, new ArrayList<Integer>(), rangeToLeaf);

    StringBuilder sb = new StringBuilder();
    sb.append('\n');
    sb.append("public void add(long v) {\n");
    int count = 0;
    for (LongRange range : ranges) {
        sb.append("  // range ");
        sb.append(count++);
        sb.append(": ");
        sb.append(range);
        sb.append('\n');
    }

    buildJavaCounter2Source(root, 1, sb, false);

    sb.append("}\n\n");
    sb.append("public int[] getCounts() {\n");
    sb.append("  int[] counts = new int[");
    sb.append(ranges.length);
    sb.append("];\n");
    for (int range = 0; range < ranges.length; range++) {
        List<Integer> elements = rangeToLeaf.get(range);
        if (elements != null) {
            sb.append("  counts[");
            sb.append(range);
            sb.append("] = count");
            sb.append(elements.get(0));

            for (int i = 1; i < elements.size(); i++) {
                sb.append(" + count");
                sb.append(elements.get(i));
            }
            sb.append(";\n");
        }
    }
    sb.append("  return counts;\n}\n");

    String javaSource = sb.toString();
    //System.out.println("counter2 javaSource:\n" + javaSource);

    ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    classWriter.visit(Opcodes.V1_7,
            Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC,
            COMPILED_COUNTER_CLASS2.replace('.', '/'), null, LONG_RANGE_COUNTER_TYPE.getInternalName(), null);
    classWriter.visitSource(javaSource, null);

    // Define "int countN" members:
    int numLeaves = elementaryIntervals.size();
    for (int i = 0; i < numLeaves; i++) {
        classWriter.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC, "count" + i, "I", null, null);
    }

    // init:
    Method m = Method.getMethod("void <init> ()");
    GeneratorAdapter constructor = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, m, null,
            null, classWriter);
    // Init all counters to 0:
    for (int i = 0; i < numLeaves; i++) {
        constructor.loadThis();
        constructor.push(0);
        constructor.putField(COMPILED_COUNTER_CLASS2_TYPE, "count" + i, Type.INT_TYPE);
    }
    constructor.loadThis();
    constructor.invokeConstructor(LONG_RANGE_COUNTER_TYPE, m);
    constructor.returnValue();
    constructor.endMethod();

    // void add(long v):
    GeneratorAdapter gen = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, ADD_METHOD, null,
            null, classWriter);
    buildCounterAsm2(gen, root, false);
    gen.returnValue();
    gen.endMethod();

    // int[] getCounts():
    gen = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, GET_COUNTS_METHOD, null, null,
            classWriter);
    int countsLocal = gen.newLocal(INT_ARRAY_TYPE);
    gen.push(ranges.length);
    gen.newArray(Type.INT_TYPE);
    gen.storeLocal(countsLocal);

    for (int range = 0; range < ranges.length; range++) {
        List<Integer> elements = rangeToLeaf.get(range);
        if (elements != null) {
            gen.loadLocal(countsLocal);
            gen.push(range);

            gen.loadThis();
            gen.getField(COMPILED_COUNTER_CLASS2_TYPE, "count" + elements.get(0), Type.INT_TYPE);

            for (int i = 1; i < elements.size(); i++) {
                gen.loadThis();
                gen.getField(COMPILED_COUNTER_CLASS2_TYPE, "count" + elements.get(i), Type.INT_TYPE);
                gen.visitInsn(Opcodes.IADD);
            }

            gen.arrayStore(Type.INT_TYPE);
        }
    }

    gen.loadLocal(countsLocal);
    gen.returnValue();
    gen.endMethod();

    classWriter.visitEnd();

    byte[] bytes = classWriter.toByteArray();

    // javap -c /x/tmp/my.class
    /*
    try {
      FileOutputStream fos = new FileOutputStream(new File("/x/tmp/counter2.class"));
      fos.write(bytes);
      fos.close();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    */

    // nocommit allow changing the class loader
    Class<? extends LongRangeCounter> cl = new CounterLoader(LongRangeCounter.class.getClassLoader())
            .define(COMPILED_COUNTER_CLASS2, classWriter.toByteArray());
    try {
        return cl.getConstructor().newInstance();
    } catch (InstantiationException | IllegalAccessException | NoSuchMethodException
            | InvocationTargetException e) {
        throw new RuntimeException(e);
    }
}