Skip to content

Commit a333ed6

Browse files
authored
IGNITE-28310 Optimize ClientInboundMessageHandler#writeError (#7943)
* Remove legacy stack trace retrieval code, use simple `printStackTrace` * Remove extra `toString` call, pass `CharSequence` to `ClientMessagePacker`
1 parent d01c096 commit a333ed6

3 files changed

Lines changed: 7 additions & 279 deletions

File tree

modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientMessagePacker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ public void packDouble(double v) {
347347
*
348348
* @param s the value to be written.
349349
*/
350-
public void packString(@Nullable String s) {
350+
public void packString(@Nullable CharSequence s) {
351351
assert !closed : "Packer is closed";
352352

353353
if (s == null) {

modules/core/src/main/java/org/apache/ignite/internal/util/ExceptionUtils.java

Lines changed: 5 additions & 277 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@
3030
import java.lang.invoke.MethodHandle;
3131
import java.lang.invoke.MethodType;
3232
import java.lang.invoke.WrongMethodTypeException;
33-
import java.lang.reflect.Field;
34-
import java.lang.reflect.InvocationTargetException;
35-
import java.lang.reflect.Method;
36-
import java.sql.SQLException;
37-
import java.util.ArrayList;
3833
import java.util.IdentityHashMap;
3934
import java.util.List;
4035
import java.util.Objects;
@@ -58,283 +53,16 @@
5853
*/
5954
public final class ExceptionUtils {
6055
/**
61-
* The names of methods commonly used to access a wrapped exception.
62-
*/
63-
private static final String[] CAUSE_METHOD_NAMES = {
64-
"getCause",
65-
"getNextException",
66-
"getTargetException",
67-
"getException",
68-
"getSourceException",
69-
"getRootCause",
70-
"getCausedByException",
71-
"getNested",
72-
"getLinkedException",
73-
"getNestedException",
74-
"getLinkedCause",
75-
"getThrowable"
76-
};
77-
78-
/**
79-
* The Method object for Java 1.4 getCause.
80-
*/
81-
private static final Method THROWABLE_CAUSE_METHOD;
82-
83-
static {
84-
Method causeMtd;
85-
86-
try {
87-
causeMtd = Throwable.class.getMethod("getCause", (Class<?>) null);
88-
} catch (Exception ignored) {
89-
causeMtd = null;
90-
}
91-
92-
THROWABLE_CAUSE_METHOD = causeMtd;
93-
}
94-
95-
/**
96-
* Introspects the {@code Throwable} to obtain the cause.
97-
*
98-
* @param throwable The exception to examine.
99-
* @return The wrapped exception, or {@code null} if not found.
100-
*/
101-
@Nullable
102-
private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
103-
if (throwable instanceof SQLException) {
104-
return ((SQLException) throwable).getNextException();
105-
}
106-
107-
if (throwable instanceof InvocationTargetException) {
108-
return ((InvocationTargetException) throwable).getTargetException();
109-
}
110-
111-
return null;
112-
}
113-
114-
/**
115-
* Finds a {@code Throwable} by method name.
116-
*
117-
* @param throwable The exception to examine.
118-
* @param mtdName The name of the method to find and invoke.
119-
* @return The wrapped exception, or {@code null} if not found.
120-
*/
121-
private static @Nullable Throwable getCauseUsingMethodName(Throwable throwable, String mtdName) {
122-
Method mtd = null;
123-
124-
try {
125-
mtd = throwable.getClass().getMethod(mtdName, (Class<?>) null);
126-
} catch (NoSuchMethodException | SecurityException ignored) {
127-
// exception ignored
128-
}
129-
130-
if (mtd != null && Throwable.class.isAssignableFrom(mtd.getReturnType())) {
131-
try {
132-
return (Throwable) mtd.invoke(throwable, ArrayUtils.OBJECT_EMPTY_ARRAY);
133-
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ignored) {
134-
// exception ignored
135-
}
136-
}
137-
138-
return null;
139-
}
140-
141-
/**
142-
* Finds a {@code Throwable} by field name.
143-
*
144-
* @param throwable The exception to examine.
145-
* @param fieldName The name of the attribute to examine.
146-
* @return The wrapped exception, or {@code null} if not found.
147-
*/
148-
private static @Nullable Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
149-
Field field = null;
150-
151-
try {
152-
field = throwable.getClass().getField(fieldName);
153-
} catch (NoSuchFieldException | SecurityException ignored) {
154-
// exception ignored
155-
}
156-
157-
if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
158-
try {
159-
return (Throwable) field.get(throwable);
160-
} catch (IllegalAccessException | IllegalArgumentException ignored) {
161-
// exception ignored
162-
}
163-
}
164-
165-
return null;
166-
}
167-
168-
/**
169-
* Checks if the Throwable class has a {@code getCause} method.
170-
*
171-
* @return True if Throwable is nestable.
172-
*/
173-
public static boolean isThrowableNested() {
174-
return THROWABLE_CAUSE_METHOD != null;
175-
}
176-
177-
/**
178-
* Checks whether this {@code Throwable} class can store a cause.
179-
*
180-
* @param throwable The {@code Throwable} to examine, may be null.
181-
* @return Boolean {@code true} if nested otherwise {@code false}.
182-
*/
183-
public static boolean isNestedThrowable(Throwable throwable) {
184-
if (throwable == null) {
185-
return false;
186-
}
187-
188-
if (throwable instanceof SQLException || throwable instanceof InvocationTargetException) {
189-
return true;
190-
}
191-
192-
if (isThrowableNested()) {
193-
return true;
194-
}
195-
196-
Class<?> cls = throwable.getClass();
197-
for (String methodName : CAUSE_METHOD_NAMES) {
198-
try {
199-
Method mtd = cls.getMethod(methodName, (Class<?>) null);
200-
201-
if (Throwable.class.isAssignableFrom(mtd.getReturnType())) {
202-
return true;
203-
}
204-
} catch (NoSuchMethodException | SecurityException ignored) {
205-
// exception ignored
206-
}
207-
}
208-
209-
try {
210-
cls.getField("detail");
211-
212-
return true;
213-
} catch (NoSuchFieldException | SecurityException ignored) {
214-
// exception ignored
215-
}
216-
217-
return false;
218-
}
219-
220-
/**
221-
* Introspects the {@code Throwable} to obtain the cause.
222-
*
223-
* @param throwable The throwable to introspect for a cause, may be null.
224-
* @return The cause of the {@code Throwable}, {@code null} if none found or null throwable input.
225-
*/
226-
public static @Nullable Throwable getCause(Throwable throwable) {
227-
return getCause(throwable, CAUSE_METHOD_NAMES);
228-
}
229-
230-
/**
231-
* Introspects the {@code Throwable} to obtain the cause.
232-
*
233-
* @param throwable The throwable to introspect for a cause, may be null.
234-
* @param mtdNames The method names, null treated as default set.
235-
* @return The cause of the {@code Throwable}, {@code null} if none found or null throwable input.
236-
*/
237-
@Nullable
238-
public static Throwable getCause(@Nullable Throwable throwable, String[] mtdNames) {
239-
if (throwable == null) {
240-
return null;
241-
}
242-
243-
Throwable cause = getCauseUsingWellKnownTypes(throwable);
244-
245-
if (cause == null) {
246-
if (mtdNames == null) {
247-
mtdNames = CAUSE_METHOD_NAMES;
248-
}
249-
250-
for (String mtdName : mtdNames) {
251-
if (mtdName != null) {
252-
cause = getCauseUsingMethodName(throwable, mtdName);
253-
254-
if (cause != null) {
255-
break;
256-
}
257-
}
258-
}
259-
260-
if (cause == null) {
261-
cause = getCauseUsingFieldName(throwable, "detail");
262-
}
263-
}
264-
265-
return cause;
266-
}
267-
268-
/**
269-
* Returns the list of {@code Throwable} objects in the exception chain.
270-
*
271-
* <p>A throwable without cause will return a list containing one element - the input throwable. A throwable with one cause
272-
* will return a list containing two elements - the input throwable and the cause throwable. A {@code null} throwable will return a list
273-
* of size zero.
274-
*
275-
* <p>This method handles recursive cause structures that might otherwise cause infinite loops. The cause chain is processed until
276-
* the end is reached, or until the next item in the chain is already in the result set.
277-
*
278-
* @param throwable The throwable to inspect, may be null.
279-
* @return The list of throwables, never null.
280-
*/
281-
public static List<Throwable> getThrowableList(Throwable throwable) {
282-
List<Throwable> list = new ArrayList<>();
283-
284-
// TODO: https://issues.apache.org/jira/browse/IGNITE-28026
285-
while (throwable != null && !list.contains(throwable)) {
286-
list.add(throwable);
287-
throwable = getCause(throwable);
288-
}
289-
290-
return list;
291-
}
292-
293-
/**
294-
* Collects suppressed exceptions from throwable and all it causes.
295-
*
296-
* @param t Throwable.
297-
* @return List of suppressed throwables.
298-
*/
299-
public static List<Throwable> getSuppressedList(@Nullable Throwable t) {
300-
List<Throwable> result = new ArrayList<>();
301-
302-
if (t == null) {
303-
return result;
304-
}
305-
306-
// TODO: https://issues.apache.org/jira/browse/IGNITE-28026
307-
do {
308-
for (Throwable suppressed : t.getSuppressed()) {
309-
result.add(suppressed);
310-
311-
result.addAll(getSuppressedList(suppressed));
312-
}
313-
} while ((t = t.getCause()) != null);
314-
315-
return result;
316-
}
317-
318-
/**
319-
* A way to get the entire nested stack-trace of an throwable.
56+
* Gets the stack trace as a char sequence.
32057
*
32158
* @param throwable The {@code Throwable} to be examined.
322-
* @return The nested stack trace, with the root cause first.
59+
* @return The stack trace.
32360
*/
324-
public static String getFullStackTrace(Throwable throwable) {
61+
public static CharSequence getFullStackTrace(Throwable throwable) {
32562
StringWriter sw = new StringWriter();
32663
PrintWriter pw = new PrintWriter(sw, true);
327-
var ts = getThrowableList(throwable);
328-
329-
for (Throwable t : ts) {
330-
t.printStackTrace(pw);
331-
332-
if (isNestedThrowable(t)) {
333-
break;
334-
}
335-
}
336-
337-
return sw.getBuffer().toString();
64+
throwable.printStackTrace(pw);
65+
return sw.getBuffer();
33866
}
33967

34068
/**

modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/matchers/CompletableFutureExceptionMatcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ protected void describeMismatchSafely(CompletableFuture<?> item, Description mis
120120
private static void describeThrowable(Throwable throwable, Description mismatchDescription) {
121121
mismatchDescription.appendValue(throwable)
122122
.appendText(System.lineSeparator())
123-
.appendText(ExceptionUtils.getFullStackTrace(throwable));
123+
.appendText(ExceptionUtils.getFullStackTrace(throwable).toString());
124124
}
125125

126126
private boolean matchesWithCause(Throwable e) {

0 commit comments

Comments
 (0)