@NonNls
  public static String getValueAsString(final EvaluationContext evaluationContext, Value value) throws EvaluateException {
    try {
      if (value == null) {
        return "null";
      }
      if (value instanceof StringReference) {
        ensureNotInsideObjectConstructor((ObjectReference)value, evaluationContext);
        return ((StringReference)value).value();
      }
      if (isInteger(value)) {
        return String.valueOf(((PrimitiveValue)value).longValue());
      }
      if (value instanceof FloatValue) {
        return String.valueOf(((FloatValue)value).floatValue());
      }
      if (value instanceof DoubleValue) {
        return String.valueOf(((DoubleValue)value).doubleValue());
      }
      if (value instanceof BooleanValue) {
        return String.valueOf(((PrimitiveValue)value).booleanValue());
      }
      if (value instanceof CharValue) {
        return String.valueOf(((PrimitiveValue)value).charValue());
      }
      if (value instanceof ObjectReference objRef) {
        if (value instanceof ArrayReference arrayRef) {
          final StringJoiner joiner = new StringJoiner(",", "[", "]");
          for (final Value element : arrayRef.getValues()) {
            joiner.add(getValueAsString(evaluationContext, element));
          }
          return joiner.toString();
        }

        final DebugProcess debugProcess = evaluationContext.getDebugProcess();
        Method toStringMethod = debugProcess.getUserData(TO_STRING_METHOD_KEY);
        if (toStringMethod == null || !toStringMethod.virtualMachine().equals(objRef.virtualMachine())) {
          try {
            ReferenceType refType = getObjectClassType(objRef.virtualMachine());
            toStringMethod = findMethod(refType, "toString", "()Ljava/lang/String;");
            debugProcess.putUserData(TO_STRING_METHOD_KEY, toStringMethod);
          }
          catch (Exception ignored) {
            throw EvaluateExceptionUtil.createEvaluateException(
              JavaDebuggerBundle.message("evaluation.error.cannot.evaluate.tostring", objRef.referenceType().name()));
          }
        }
        if (toStringMethod == null) {
          throw EvaluateExceptionUtil.createEvaluateException(
            JavaDebuggerBundle.message("evaluation.error.cannot.evaluate.tostring", objRef.referenceType().name()));
        }
        Method finalToStringMethod = toStringMethod;
        return processCollectibleValue(
          () -> debugProcess.invokeInstanceMethod(evaluationContext, objRef, finalToStringMethod, Collections.emptyList(), 0),
          result -> {
            // while result must be of com.sun.jdi.StringReference type, it turns out that sometimes (jvm bugs?)
            // it is a plain com.sun.tools.jdi.ObjectReferenceImpl
            if (result == null) {
              return "null";
            }
            return result instanceof StringReference ? ((StringReference)result).value() : result.toString();
          }
        );
      }
      throw EvaluateExceptionUtil.createEvaluateException(JavaDebuggerBundle.message("evaluation.error.unsupported.expression.type"));
    }
    catch (ObjectCollectedException ignored) {
      throw EvaluateExceptionUtil.OBJECT_WAS_COLLECTED;
    }
  }
@NonNls
  public static String getValueAsString(final EvaluationContext evaluationContext, Value value)