private E invokeMethodAndFork(SuspendContextImpl context, ThreadReferenceProxyImpl thread) throws InvocationException,
                                                                                                      ClassNotLoadedException,
                                                                                                      IncompatibleThreadStateException,
                                                                                                      InvalidTypeException {
      Ref<Exception> exception = Ref.create();
      Ref<E> result = Ref.create();
      Ref<ThreadBlockedMonitor.InvocationWatcher> invocationWatcherRef = Ref.create();
      if (LOG.isDebugEnabled()) {
        LOG.debug("Invoke in " + context);
        assertThreadSuspended(thread, context);
      }
      getManagerThread().startLongProcessAndFork(() -> {
        try {
          try {
            if (myMethod.isVarArgs()) {
              // See IDEA-63581
              // if vararg parameter array is of interface type and Object[] is expected, JDI wrap it into another array,
              // in this case we have to unroll the array manually and pass its elements to the method instead of array object
              int lastIndex = myMethod.argumentTypeNames().size() - 1;
              if (lastIndex >= 0 && myArgs.size() > lastIndex) { // at least one varargs param
                Object firstVararg = myArgs.get(lastIndex);
                if (myArgs.size() == lastIndex + 1) { // only one vararg param
                  if (firstVararg instanceof ArrayReference arrayRef) {
                    if (((ArrayType)arrayRef.referenceType()).componentType() instanceof InterfaceType) {
                      List<String> argTypes = myMethod.argumentTypeNames();
                      if (argTypes.size() > lastIndex && argTypes.get(lastIndex).startsWith(CommonClassNames.JAVA_LANG_OBJECT)) {
                        // unwrap array of interfaces for vararg param
                        myArgs.remove(lastIndex);
                        myArgs.addAll(arrayRef.getValues());
                      }
                    }
                  }
                }
              }
            }

            if (!Patches.IBM_JDK_DISABLE_COLLECTION_BUG) {
              // ensure args are not collected
              StreamEx.of(myArgs).select(ObjectReference.class).forEach(DebuggerUtilsEx::disableCollection);
            }

            if (Patches.JDK_BUG_ID_21275177 && (ourTraceMask & VirtualMachine.TRACE_SENDS) != 0) {
              //noinspection ResultOfMethodCallIgnored
              StreamEx.of(myArgs).nonNull().forEach(Object::toString);
            }

            // workaround for jdi hang in trace mode, see IDEA-183387
            if (Patches.JDK_BUG_WITH_TRACE_SEND && (getTraceMask() & VirtualMachine.TRACE_SENDS) != 0) {
              StreamEx.of(myArgs).findAny(ThreadReference.class::isInstance).ifPresent(t -> {
                //noinspection UseOfSystemOutOrSystemErr
                System.err.println("[JDI: workaround for invocation of " + myMethod + "]");
                myMethod.virtualMachine().setDebugTraceMode(getTraceMask() & ~VirtualMachine.TRACE_SENDS);
              });
            }

            int invokePolicy = getInvokePolicy(context);
            invocationWatcherRef.set(myThreadBlockedMonitor.startInvokeWatching(invokePolicy, thread, context));
            result.set(invokeMethod(thread.getThreadReference(), invokePolicy, myMethod, myArgs));
          }
          finally {
            if (Patches.JDK_BUG_WITH_TRACE_SEND && (getTraceMask() & VirtualMachine.TRACE_SENDS) != 0) {
              myMethod.virtualMachine().setDebugTraceMode(getTraceMask());
            }
            //  assertThreadSuspended(thread, context);
            if (!Patches.IBM_JDK_DISABLE_COLLECTION_BUG) {
              // ensure args are not collected
              StreamEx.of(myArgs).select(ObjectReference.class).forEach(DebuggerUtilsEx::enableCollection);
            }
          }
        }
        catch (Exception e) {
          exception.set(e);
        }
      });

      try {
        Exception ex = exception.get();
        if (ex != null) {
          if (ex instanceof InvocationException) {
            throw (InvocationException)ex;
          }
          else if (ex instanceof ClassNotLoadedException) {
            throw (ClassNotLoadedException)ex;
          }
          else if (ex instanceof IncompatibleThreadStateException) {
            throw (IncompatibleThreadStateException)ex;
          }
          else if (ex instanceof InvalidTypeException) {
            throw (InvalidTypeException)ex;
          }
          else if (ex instanceof RuntimeException) {
            throw (RuntimeException)ex;
          }
          else {
            logError("Unexpected exception", new Throwable(ex));
          }
        }

        return result.get();
      } finally {
        ThreadBlockedMonitor.InvocationWatcher invocationWatcher = invocationWatcherRef.get();
        if (invocationWatcher != null) {
          invocationWatcher.invocationFinished();
        }
      }
    }
private E invokeMethodAndFork(SuspendContextImpl context, ThreadReferenceProxyImpl thread)