private void generateInnerClassWithCounter()

in test-discovery/src/com/intellij/rt/coverage/testDiscovery/instrumentation/TestDiscoveryInnerClassInstrumenter.java [46:102]


  private void generateInnerClassWithCounter() {
    ClassWriter cw = new ClassWriter(0);
    MethodVisitor mv;

    cw.visit(myClassVersion,
        Opcodes.ACC_STATIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER + Opcodes.ACC_SYNTHETIC,
        myInternalCounterClassJVMName, // ?
        null,
        "java/lang/Object",
        null);

    {
      cw.visitOuterClass(myInternalClassName, myInternalCounterClassJVMName, null);

      cw.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, METHODS_VISITED,
          METHODS_VISITED_CLASS, null, null);

      MethodVisitor staticBlockVisitor = cw.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
      staticBlockVisitor.visitCode();
      initField(staticBlockVisitor);
      staticBlockVisitor.visitInsn(Opcodes.RETURN);
      staticBlockVisitor.visitMaxs(ADDED_CODE_STACK_SIZE, 0);
      staticBlockVisitor.visitEnd();
    }

    {
      mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
      mv.visitVarInsn(Opcodes.ALOAD, 0);
      mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
          "java/lang/Object",
          "<init>",
          "()V", false);
      mv.visitInsn(Opcodes.RETURN);
      mv.visitMaxs(1, 1);
      mv.visitEnd();
    }

    cw.visitEnd();

    try {
      byte[] bytes = cw.toByteArray();
      //saveBytes(bytes, myInternalCounterClassJVMName.replace('/', '.') + ".class");

      Method defineClassMethodRef = myDefineClassMethodRef;
      if (defineClassMethodRef == null) {
        defineClassMethodRef = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
        if (defineClassMethodRef != null) {
          defineClassMethodRef.setAccessible(true);
          myDefineClassMethodRef = defineClassMethodRef;
        }
      }

      defineClassMethodRef.invoke(myClassLoader, bytes, 0, bytes.length);
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }