Skip to content

Commit

Permalink
Merge pull request #17523 from mmedenjak/4.0.3-revert-17249
Browse files Browse the repository at this point in the history
Revert "Add caller stacktrace to rethrown RuntimeException (#17249)"
  • Loading branch information
mmedenjak committed Sep 14, 2020
2 parents 98d4642 + 9e8aeae commit d717127
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 90 deletions.
Expand Up @@ -24,8 +24,4 @@ public class HazelcastClientOfflineException extends IllegalStateException {
public HazelcastClientOfflineException() {
super("No connection found to cluster");
}

public HazelcastClientOfflineException(Throwable cause) {
super(cause);
}
}
Expand Up @@ -709,11 +709,7 @@ private Throwable createException(Iterator<ErrorHolder> iterator) {
if (exceptionFactory == null) {
throwable = new UndefinedErrorCodeException(errorHolder.getMessage(), errorHolder.getClassName());
} else {
Throwable cause = createException(iterator);
throwable = exceptionFactory.createException(errorHolder.getMessage(), cause);
if (throwable.getCause() == null && cause != null) {
throwable.initCause(cause);
}
throwable = exceptionFactory.createException(errorHolder.getMessage(), createException(iterator));
}
throwable.setStackTrace(errorHolder.getStackTraceElements().toArray(new StackTraceElement[0]));
return throwable;
Expand Down
Expand Up @@ -19,14 +19,10 @@
import com.hazelcast.core.HazelcastException;
import com.hazelcast.instance.impl.OutOfMemoryErrorDispatcher;
import com.hazelcast.logging.ILogger;
import com.hazelcast.spi.impl.operationservice.WrappableException;

import javax.annotation.Nonnull;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutionException;
import java.util.function.BiConsumer;
Expand All @@ -37,14 +33,6 @@
*/
public final class ExceptionUtil {

private static final MethodHandles.Lookup LOOKUP = MethodHandles.publicLookup();
// new Throwable(String message, Throwable cause)
private static final MethodType MT_INIT_STRING_THROWABLE = MethodType.methodType(void.class, String.class, Throwable.class);
// new Throwable(Throwable cause)
private static final MethodType MT_INIT_THROWABLE = MethodType.methodType(void.class, Throwable.class);
// new Throwable(String message)
private static final MethodType MT_INIT_STRING = MethodType.methodType(void.class, String.class);

private static final BiFunction<Throwable, String, HazelcastException> HAZELCAST_EXCEPTION_WRAPPER = (throwable, message) -> {
if (message != null) {
return new HazelcastException(message, throwable);
Expand Down Expand Up @@ -111,7 +99,7 @@ public static <T extends Throwable> Throwable peel(final Throwable t, Class<T> a
public static <T, W extends Throwable> Throwable peel(final Throwable t, Class<T> allowedType,
String message, BiFunction<Throwable, String, W> exceptionWrapper) {
if (t instanceof RuntimeException) {
return wrapException(t, message, exceptionWrapper);
return t;
}

if (t instanceof ExecutionException || t instanceof InvocationTargetException) {
Expand All @@ -130,20 +118,7 @@ public static <T, W extends Throwable> Throwable peel(final Throwable t, Class<T
return exceptionWrapper.apply(t, message);
}

public static <W extends Throwable> Throwable wrapException(Throwable t, String message,
BiFunction<Throwable, String, W> exceptionWrapper) {
if (t instanceof WrappableException) {
return ((WrappableException) t).wrap();
}
Throwable wrapped = tryWrapInSameClass(t);
return wrapped == null ? exceptionWrapper.apply(t, message) : wrapped;
}

public static RuntimeException wrapException(RuntimeException t) {
return (RuntimeException) wrapException(t, null, HAZELCAST_EXCEPTION_WRAPPER);
}

public static RuntimeException rethrow(final Throwable t) {
public static RuntimeException rethrow(Throwable t) {
rethrowIfError(t);
throw peel(t);
}
Expand Down Expand Up @@ -176,15 +151,10 @@ public static void rethrowIfError(final Throwable t) {
if (t instanceof OutOfMemoryError) {
OutOfMemoryErrorDispatcher.onOutOfMemory((OutOfMemoryError) t);
}
throw wrapError((Error) t);
throw (Error) t;
}
}

public static Error wrapError(Error cause) {
Error result = tryWrapInSameClass(cause);
return result == null ? cause : result;
}

public static RuntimeException rethrowAllowInterrupted(final Throwable t) throws InterruptedException {
return rethrow(t, InterruptedException.class);
}
Expand Down Expand Up @@ -224,27 +194,4 @@ public static <T extends Throwable> RuntimeException sneakyThrow(@Nonnull Throwa
}
};
}

public static <T extends Throwable> T tryWrapInSameClass(T cause) {
Class<? extends Throwable> exceptionClass = cause.getClass();
MethodHandle constructor;
try {
constructor = LOOKUP.findConstructor(exceptionClass, MT_INIT_STRING_THROWABLE);
return (T) constructor.invokeWithArguments(cause.getMessage(), cause);
} catch (Throwable ignored) {
}
try {
constructor = LOOKUP.findConstructor(exceptionClass, MT_INIT_THROWABLE);
return (T) constructor.invokeWithArguments(cause);
} catch (Throwable ignored) {
}
try {
constructor = LOOKUP.findConstructor(exceptionClass, MT_INIT_STRING);
T result = (T) constructor.invokeWithArguments(cause.getMessage());
result.initCause(cause);
return result;
} catch (Throwable ignored) {
}
return null;
}
}
Expand Up @@ -17,15 +17,13 @@
package com.hazelcast.ringbuffer;

import com.hazelcast.spi.exception.SilentException;
import com.hazelcast.spi.impl.operationservice.WrappableException;

/**
* An {@link RuntimeException} that is thrown when accessing an item in the {@link Ringbuffer} using a sequence that is smaller
* than the current head sequence and that the ringbuffer store is disabled. This means that the item isn't available in the
* ringbuffer and it cannot be loaded from the store either, thus being completely unavailable.
*/
public class StaleSequenceException extends RuntimeException
implements SilentException, WrappableException<StaleSequenceException> {
public class StaleSequenceException extends RuntimeException implements SilentException {

private final long headSeq;

Expand All @@ -49,11 +47,4 @@ public StaleSequenceException(String message, long headSeq) {
public long getHeadSeq() {
return headSeq;
}

@Override
public StaleSequenceException wrap() {
StaleSequenceException staleSequenceException = new StaleSequenceException(getMessage(), headSeq);
staleSequenceException.initCause(this);
return staleSequenceException;
}
}
Expand Up @@ -22,10 +22,15 @@
import com.hazelcast.instance.impl.OutOfMemoryErrorDispatcher;
import com.hazelcast.internal.util.executor.UnblockableThread;
import com.hazelcast.logging.ILogger;
import com.hazelcast.spi.impl.operationservice.WrappableException;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
Expand All @@ -46,8 +51,6 @@

import static com.hazelcast.internal.util.ConcurrencyUtil.DEFAULT_ASYNC_EXECUTOR;
import static com.hazelcast.internal.util.ExceptionUtil.sneakyThrow;
import static com.hazelcast.internal.util.ExceptionUtil.wrapError;
import static com.hazelcast.internal.util.ExceptionUtil.wrapException;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater;
import static java.util.concurrent.locks.LockSupport.park;
Expand All @@ -56,7 +59,6 @@

/**
* Custom implementation of {@link java.util.concurrent.CompletableFuture}.
*
* @param <V>
*/
@SuppressFBWarnings(value = "DLS_DEAD_STORE_OF_CLASS_LITERAL", justification = "Recommended way to prevent classloading bug")
Expand All @@ -69,6 +71,13 @@ public String toString() {
return "UNRESOLVED";
}
};
private static final Lookup LOOKUP = MethodHandles.publicLookup();
// new Throwable(String message, Throwable cause)
private static final MethodType MT_INIT_STRING_THROWABLE = MethodType.methodType(void.class, String.class, Throwable.class);
// new Throwable(Throwable cause)
private static final MethodType MT_INIT_THROWABLE = MethodType.methodType(void.class, Throwable.class);
// new Throwable(String message)
private static final MethodType MT_INIT_STRING = MethodType.methodType(void.class, String.class);

private static final AtomicReferenceFieldUpdater<AbstractInvocationFuture, Object> STATE_UPDATER =
newUpdater(AbstractInvocationFuture.class, Object.class, "state");
Expand Down Expand Up @@ -1909,7 +1918,7 @@ static Throwable wrapOrPeel(Throwable cause) {
return cause;
}
if (cause instanceof RuntimeException) {
return wrapException((RuntimeException) cause);
return wrapRuntimeException((RuntimeException) cause);
}
if ((cause instanceof ExecutionException || cause instanceof InvocationTargetException)
&& cause.getCause() != null) {
Expand All @@ -1924,4 +1933,39 @@ static Throwable wrapOrPeel(Throwable cause) {
return new HazelcastException(cause);
}

private static RuntimeException wrapRuntimeException(RuntimeException cause) {
if (cause instanceof WrappableException) {
return ((WrappableException) cause).wrap();
}
RuntimeException wrapped = tryWrapInSameClass(cause);
return wrapped == null ? new HazelcastException(cause) : wrapped;
}

private static Error wrapError(Error cause) {
Error result = tryWrapInSameClass(cause);
return result == null ? cause : result;
}

private static <T extends Throwable> T tryWrapInSameClass(T cause) {
Class<? extends Throwable> exceptionClass = cause.getClass();
MethodHandle constructor;
try {
constructor = LOOKUP.findConstructor(exceptionClass, MT_INIT_STRING_THROWABLE);
return (T) constructor.invokeWithArguments(cause.getMessage(), cause);
} catch (Throwable ignored) {
}
try {
constructor = LOOKUP.findConstructor(exceptionClass, MT_INIT_THROWABLE);
return (T) constructor.invokeWithArguments(cause);
} catch (Throwable ignored) {
}
try {
constructor = LOOKUP.findConstructor(exceptionClass, MT_INIT_STRING);
T result = (T) constructor.invokeWithArguments(cause.getMessage());
result.initCause(cause);
return result;
} catch (Throwable ignored) {
}
return null;
}
}
Expand Up @@ -34,7 +34,6 @@
import com.hazelcast.crdt.TargetNotReplicaException;
import com.hazelcast.durableexecutor.StaleTaskIdException;
import com.hazelcast.internal.cluster.impl.ConfigMismatchException;
import com.hazelcast.internal.util.ExceptionUtil;
import com.hazelcast.map.QueryResultSizeExceededException;
import com.hazelcast.map.ReachedMaxSizeException;
import com.hazelcast.memory.NativeOutOfMemoryError;
Expand Down Expand Up @@ -273,8 +272,7 @@ public static Iterable<Object[]> parameters() {
new Object[]{new IndeterminateOperationStateException(randomString())},
new Object[]{new TargetNotReplicaException(randomString())},
new Object[]{new MutationDisallowedException(randomString())},
new Object[]{new ConsistencyLostException(randomString())},
new Object[]{ExceptionUtil.tryWrapInSameClass(new NullPointerException())}
new Object[]{new ConsistencyLostException(randomString())}
);
}
}
Expand Up @@ -22,13 +22,13 @@
import com.hazelcast.config.Config;
import com.hazelcast.core.HazelcastException;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.internal.util.FilteringClassLoader;
import com.hazelcast.map.IMap;
import com.hazelcast.nio.serialization.HazelcastSerializationException;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
import com.hazelcast.test.annotation.ParallelJVMTest;
import com.hazelcast.test.annotation.QuickTest;
import com.hazelcast.internal.util.FilteringClassLoader;
import org.junit.After;
import org.junit.Test;
import org.junit.experimental.categories.Category;
Expand All @@ -38,6 +38,8 @@
import java.io.FileNotFoundException;

import static java.util.Collections.singletonList;
import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertEquals;

@RunWith(HazelcastParallelClassRunner.class)
@Category({QuickTest.class, ParallelJVMTest.class})
Expand All @@ -50,7 +52,7 @@ public void tearDown() throws Exception {
factory.terminateAll();
}

@Test(expected = HazelcastSerializationException.class)
@Test
public void testUserCodeDeploymentIsDisabledByDefaultOnClient() {
// this test also validate the EP is filtered locally and has to be loaded from the other member
ClientConfig clientConfig = new ClientConfig();
Expand All @@ -62,7 +64,12 @@ public void testUserCodeDeploymentIsDisabledByDefaultOnClient() {
HazelcastInstance client = factory.newHazelcastClient(clientConfig);

IMap<Integer, Integer> map = client.getMap(randomName());
map.executeOnEntries(incrementingEntryProcessor);
try {
map.executeOnEntries(incrementingEntryProcessor);
fail();
} catch (HazelcastSerializationException e) {
assertEquals(ClassNotFoundException.class, e.getCause().getClass());
}
}

private Config createNodeConfig() {
Expand Down
Expand Up @@ -54,16 +54,14 @@ public void testToString() {
public void testPeel_whenThrowableIsRuntimeException_thenReturnOriginal() {
RuntimeException result = ExceptionUtil.peel(throwable);

assertEquals(throwable.getMessage(), result.getMessage());
assertEquals(throwable.getClass(), result.getClass());
assertEquals(throwable, result);
}

@Test
public void testPeel_whenThrowableIsExecutionException_thenReturnCause() {
RuntimeException result = ExceptionUtil.peel(new ExecutionException(throwable));

assertEquals(throwable.getMessage(), result.getMessage());
assertEquals(throwable.getClass(), result.getClass());
assertEquals(throwable, result);
}

@Test
Expand Down
Expand Up @@ -55,6 +55,7 @@
import static com.hazelcast.transaction.TransactionOptions.TransactionType.ONE_PHASE;
import static com.hazelcast.transaction.TransactionOptions.TransactionType.TWO_PHASE;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.hamcrest.core.Is.isA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

Expand All @@ -68,6 +69,7 @@ public class TransactionsWithWriteBehind_whenNoCoalescingQueueIsFullTest extends
@Test
public void prepare_step_throws_reached_max_size_exception_when_two_phase() {
expectedException.expect(TransactionException.class);
expectedException.expectCause(isA(ReachedMaxSizeException.class));

String mapName = "map";
long maxWbqCapacity = 100;
Expand Down
Expand Up @@ -89,7 +89,7 @@ public void get_throwsGivenException_whenUncheckedExceptionSet() throws Exceptio
try {
future.get();
} catch (Exception e) {
assertSame(error.getClass(), e.getClass());
assertSame(error, e);
}
}

Expand Down

0 comments on commit d717127

Please sign in to comment.