This is an automated email from the ASF dual-hosted git repository.

ptupitsyn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new a333ed677d8 IGNITE-28310 Optimize 
ClientInboundMessageHandler#writeError (#7943)
a333ed677d8 is described below

commit a333ed677d8e03bc734e569399bac1e8485c02f0
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Wed Apr 8 11:52:25 2026 +0300

    IGNITE-28310 Optimize ClientInboundMessageHandler#writeError (#7943)
    
    * Remove legacy stack trace retrieval code, use simple `printStackTrace`
    * Remove extra `toString` call, pass `CharSequence` to `ClientMessagePacker`
---
 .../internal/client/proto/ClientMessagePacker.java |   2 +-
 .../ignite/internal/util/ExceptionUtils.java       | 282 +--------------------
 .../CompletableFutureExceptionMatcher.java         |   2 +-
 3 files changed, 7 insertions(+), 279 deletions(-)

diff --git 
a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessagePacker.java
 
b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessagePacker.java
index 52ef39b0cbf..539e14a1f11 100644
--- 
a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessagePacker.java
+++ 
b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessagePacker.java
@@ -347,7 +347,7 @@ public class ClientMessagePacker implements AutoCloseable {
      *
      * @param s the value to be written.
      */
-    public void packString(@Nullable String s) {
+    public void packString(@Nullable CharSequence s) {
         assert !closed : "Packer is closed";
 
         if (s == null) {
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/util/ExceptionUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/util/ExceptionUtils.java
index 4969432747e..85857fd193e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/util/ExceptionUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/util/ExceptionUtils.java
@@ -30,11 +30,6 @@ import java.io.StringWriter;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
 import java.lang.invoke.WrongMethodTypeException;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.sql.SQLException;
-import java.util.ArrayList;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Objects;
@@ -58,283 +53,16 @@ import org.jetbrains.annotations.Nullable;
  */
 public final class ExceptionUtils {
     /**
-     * The names of methods commonly used to access a wrapped exception.
-     */
-    private static final String[] CAUSE_METHOD_NAMES = {
-            "getCause",
-            "getNextException",
-            "getTargetException",
-            "getException",
-            "getSourceException",
-            "getRootCause",
-            "getCausedByException",
-            "getNested",
-            "getLinkedException",
-            "getNestedException",
-            "getLinkedCause",
-            "getThrowable"
-    };
-
-    /**
-     * The Method object for Java 1.4 getCause.
-     */
-    private static final Method THROWABLE_CAUSE_METHOD;
-
-    static {
-        Method causeMtd;
-
-        try {
-            causeMtd = Throwable.class.getMethod("getCause", (Class<?>) null);
-        } catch (Exception ignored) {
-            causeMtd = null;
-        }
-
-        THROWABLE_CAUSE_METHOD = causeMtd;
-    }
-
-    /**
-     * Introspects the {@code Throwable} to obtain the cause.
-     *
-     * @param throwable The exception to examine.
-     * @return The wrapped exception, or {@code null} if not found.
-     */
-    @Nullable
-    private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
-        if (throwable instanceof SQLException) {
-            return ((SQLException) throwable).getNextException();
-        }
-
-        if (throwable instanceof InvocationTargetException) {
-            return ((InvocationTargetException) 
throwable).getTargetException();
-        }
-
-        return null;
-    }
-
-    /**
-     * Finds a {@code Throwable} by method name.
-     *
-     * @param throwable The exception to examine.
-     * @param mtdName The name of the method to find and invoke.
-     * @return The wrapped exception, or {@code null} if not found.
-     */
-    private static @Nullable Throwable getCauseUsingMethodName(Throwable 
throwable, String mtdName) {
-        Method mtd = null;
-
-        try {
-            mtd = throwable.getClass().getMethod(mtdName, (Class<?>) null);
-        } catch (NoSuchMethodException | SecurityException ignored) {
-            // exception ignored
-        }
-
-        if (mtd != null && 
Throwable.class.isAssignableFrom(mtd.getReturnType())) {
-            try {
-                return (Throwable) mtd.invoke(throwable, 
ArrayUtils.OBJECT_EMPTY_ARRAY);
-            } catch (IllegalAccessException | IllegalArgumentException | 
InvocationTargetException ignored) {
-                // exception ignored
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Finds a {@code Throwable} by field name.
-     *
-     * @param throwable The exception to examine.
-     * @param fieldName The name of the attribute to examine.
-     * @return The wrapped exception, or {@code null} if not found.
-     */
-    private static @Nullable Throwable getCauseUsingFieldName(Throwable 
throwable, String fieldName) {
-        Field field = null;
-
-        try {
-            field = throwable.getClass().getField(fieldName);
-        } catch (NoSuchFieldException | SecurityException ignored) {
-            // exception ignored
-        }
-
-        if (field != null && 
Throwable.class.isAssignableFrom(field.getType())) {
-            try {
-                return (Throwable) field.get(throwable);
-            } catch (IllegalAccessException | IllegalArgumentException 
ignored) {
-                // exception ignored
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Checks if the Throwable class has a {@code getCause} method.
-     *
-     * @return True if Throwable is nestable.
-     */
-    public static boolean isThrowableNested() {
-        return THROWABLE_CAUSE_METHOD != null;
-    }
-
-    /**
-     * Checks whether this {@code Throwable} class can store a cause.
-     *
-     * @param throwable The {@code Throwable} to examine, may be null.
-     * @return Boolean {@code true} if nested otherwise {@code false}.
-     */
-    public static boolean isNestedThrowable(Throwable throwable) {
-        if (throwable == null) {
-            return false;
-        }
-
-        if (throwable instanceof SQLException || throwable instanceof 
InvocationTargetException) {
-            return true;
-        }
-
-        if (isThrowableNested()) {
-            return true;
-        }
-
-        Class<?> cls = throwable.getClass();
-        for (String methodName : CAUSE_METHOD_NAMES) {
-            try {
-                Method mtd = cls.getMethod(methodName, (Class<?>) null);
-
-                if (Throwable.class.isAssignableFrom(mtd.getReturnType())) {
-                    return true;
-                }
-            } catch (NoSuchMethodException | SecurityException ignored) {
-                // exception ignored
-            }
-        }
-
-        try {
-            cls.getField("detail");
-
-            return true;
-        } catch (NoSuchFieldException | SecurityException ignored) {
-            // exception ignored
-        }
-
-        return false;
-    }
-
-    /**
-     * Introspects the {@code Throwable} to obtain the cause.
-     *
-     * @param throwable The throwable to introspect for a cause, may be null.
-     * @return The cause of the {@code Throwable}, {@code null} if none found 
or null throwable input.
-     */
-    public static @Nullable Throwable getCause(Throwable throwable) {
-        return getCause(throwable, CAUSE_METHOD_NAMES);
-    }
-
-    /**
-     * Introspects the {@code Throwable} to obtain the cause.
-     *
-     * @param throwable The throwable to introspect for a cause, may be null.
-     * @param mtdNames The method names, null treated as default set.
-     * @return The cause of the {@code Throwable}, {@code null} if none found 
or null throwable input.
-     */
-    @Nullable
-    public static Throwable getCause(@Nullable Throwable throwable, String[] 
mtdNames) {
-        if (throwable == null) {
-            return null;
-        }
-
-        Throwable cause = getCauseUsingWellKnownTypes(throwable);
-
-        if (cause == null) {
-            if (mtdNames == null) {
-                mtdNames = CAUSE_METHOD_NAMES;
-            }
-
-            for (String mtdName : mtdNames) {
-                if (mtdName != null) {
-                    cause = getCauseUsingMethodName(throwable, mtdName);
-
-                    if (cause != null) {
-                        break;
-                    }
-                }
-            }
-
-            if (cause == null) {
-                cause = getCauseUsingFieldName(throwable, "detail");
-            }
-        }
-
-        return cause;
-    }
-
-    /**
-     * Returns the list of {@code Throwable} objects in the exception chain.
-     *
-     * <p>A throwable without cause will return a list containing one element 
- the input throwable. A throwable with one cause
-     * will return a list containing two elements - the input throwable and 
the cause throwable. A {@code null} throwable will return a list
-     * of size zero.
-     *
-     * <p>This method handles recursive cause structures that might otherwise 
cause infinite loops. The cause chain is processed until
-     * the end is reached, or until the next item in the chain is already in 
the result set.
-     *
-     * @param throwable The throwable to inspect, may be null.
-     * @return The list of throwables, never null.
-     */
-    public static List<Throwable> getThrowableList(Throwable throwable) {
-        List<Throwable> list = new ArrayList<>();
-
-        // TODO: https://issues.apache.org/jira/browse/IGNITE-28026
-        while (throwable != null && !list.contains(throwable)) {
-            list.add(throwable);
-            throwable = getCause(throwable);
-        }
-
-        return list;
-    }
-
-    /**
-     * Collects suppressed exceptions from throwable and all it causes.
-     *
-     * @param t Throwable.
-     * @return List of suppressed throwables.
-     */
-    public static List<Throwable> getSuppressedList(@Nullable Throwable t) {
-        List<Throwable> result = new ArrayList<>();
-
-        if (t == null) {
-            return result;
-        }
-
-        // TODO: https://issues.apache.org/jira/browse/IGNITE-28026
-        do {
-            for (Throwable suppressed : t.getSuppressed()) {
-                result.add(suppressed);
-
-                result.addAll(getSuppressedList(suppressed));
-            }
-        } while ((t = t.getCause()) != null);
-
-        return result;
-    }
-
-    /**
-     * A way to get the entire nested stack-trace of an throwable.
+     * Gets the stack trace as a char sequence.
      *
      * @param throwable The {@code Throwable} to be examined.
-     * @return The nested stack trace, with the root cause first.
+     * @return The stack trace.
      */
-    public static String getFullStackTrace(Throwable throwable) {
+    public static CharSequence getFullStackTrace(Throwable throwable) {
         StringWriter sw = new StringWriter();
         PrintWriter pw = new PrintWriter(sw, true);
-        var ts = getThrowableList(throwable);
-
-        for (Throwable t : ts) {
-            t.printStackTrace(pw);
-
-            if (isNestedThrowable(t)) {
-                break;
-            }
-        }
-
-        return sw.getBuffer().toString();
+        throwable.printStackTrace(pw);
+        return sw.getBuffer();
     }
 
     /**
diff --git 
a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/matchers/CompletableFutureExceptionMatcher.java
 
b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/matchers/CompletableFutureExceptionMatcher.java
index 9af26535682..f2e2f7e8e58 100644
--- 
a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/matchers/CompletableFutureExceptionMatcher.java
+++ 
b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/matchers/CompletableFutureExceptionMatcher.java
@@ -120,7 +120,7 @@ public class CompletableFutureExceptionMatcher extends 
TypeSafeMatcher<Completab
     private static void describeThrowable(Throwable throwable, Description 
mismatchDescription) {
         mismatchDescription.appendValue(throwable)
                 .appendText(System.lineSeparator())
-                .appendText(ExceptionUtils.getFullStackTrace(throwable));
+                
.appendText(ExceptionUtils.getFullStackTrace(throwable).toString());
     }
 
     private boolean matchesWithCause(Throwable e) {

Reply via email to