static void createRequestForPreparedClassEmulated(@NotNull MethodBreakpointBase breakpoint,
                                                    @NotNull DebugProcessImpl debugProcess,
                                                    @NotNull ReferenceType classType,
                                                    @NotNull ClassesByNameProvider classesByName,
                                                    boolean base) {
    if (breakpoint.isWatchExit() && !MethodBreakpointBase.canBeWatchExitEmulated(debugProcess)) {
      breakpoint.disableEmulation();
      return;
    }
    if (!base && !shouldCreateRequest(breakpoint, breakpoint.getXBreakpoint(), debugProcess, true)) {
      return;
    }
    Method lambdaMethod = MethodBytecodeUtil.getLambdaMethod(classType, classesByName);
    if (lambdaMethod != null &&
        breakpoint
          .matchingMethods(StreamEx.of(((ClassType)classType).interfaces()).flatCollection(ReferenceType::allMethods), debugProcess)
          .findFirst().isEmpty()) {
      return;
    }
    StreamEx<Method> methods = lambdaMethod != null
                               ? StreamEx.of(lambdaMethod)
                               : breakpoint.matchingMethods(StreamEx.of(classType.methods()).filter(m -> base || !m.isAbstract()), debugProcess);
    boolean found = false;
    for (Method original : methods) {
      found = true;

      Method bridgeTarget = MethodBytecodeUtil.getBridgeTargetMethod(original, classesByName);
      Method method = bridgeTarget != null ? bridgeTarget : original;

      if (method.isNative()) {
        LOG.info("Breakpoint emulation was disabled because " + method + " is native");
        breakpoint.disableEmulation();
        return;
      }
      if (method.isAbstract()) {
        continue;
      }

      if (breakpoint.isWatchEntry()) {
        // We assume that all VMs start code indexes from zero.
        Location location = new LocationCodeIndexOnly(method, 0);
        createLocationBreakpointRequest(breakpoint, location, debugProcess, true);
      }

      if (breakpoint.isWatchExit()) {
        class BytecodeVisitor extends MethodVisitor implements MethodBytecodeUtil.InstructionOffsetReader {
          private int bytecodeOffset = -1;

          BytecodeVisitor() {
            super(Opcodes.API_VERSION);
          }

          @Override
          public void readBytecodeInstructionOffset(int offset) {
            bytecodeOffset = offset;
          }

          @Override
          public void visitInsn(int opcode) {
            if (Opcodes.IRETURN <= opcode && opcode <= Opcodes.RETURN) {
              assert bytecodeOffset >= 0;
              Location location = new LocationCodeIndexOnly(method, bytecodeOffset);
              createLocationBreakpointRequest(breakpoint, location, debugProcess, false);
            }
          }
        }
        MethodBytecodeUtil.visit(method, new BytecodeVisitor(), false);
      }
    }
    if (base && found) {
      // desired class found - now also track all new classes
      createRequestForSubClasses(breakpoint, debugProcess, classType);
    }
  }
static void createRequestForPreparedClassEmulated(@NotNull MethodBreakpointBase breakpoint,
                                                    @NotNull DebugProcessImpl debugProcess,
                                                    @NotNull ReferenceType classType,
                                                    @NotNull ClassesByNameProvider classesByName,
                                                    boolean base)