在我从Java11切换到Java17(从Ubuntu20.04库安装的OpenJDK)后,以下代码不起作用:
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.exception.ExceptionUtils;
public class TestClass {
public static void main(String[] args) {
CompletableFuture<String> streamFuture = CompletableFuture.supplyAsync(() -> {
throw MyException.wrapIfNeeded(new Exception("MyException"));
});
String result = null;
try {
result = streamFuture.get();
} catch (Exception e) {
System.out.println("Exception: " + ExceptionUtils.getMessage(e));
}
System.out.println("Result: " + Objects.toString(result));
}
static class MyException extends RuntimeException {
private static final long serialVersionUID = 3349188601484197015L;
public MyException(Throwable cause) {
super(cause == null ? null : cause.getMessage(), cause);
}
public static MyException wrapIfNeeded(Throwable e) {
return e instanceof MyException ? (MyException) e : new MyException(e);
}
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
}在streamFuture.get()中有一个问题-它无限地挂起。我深入研究了一下,发现在java.util.concurrent.ForkJoinPool中有一个unmanagedBlock(ManagedBlocker blocker)方法,它看起来像
/** ManagedBlock for external threads */
private static void unmanagedBlock(ManagedBlocker blocker)
throws InterruptedException {
if (blocker == null) throw new NullPointerException();
do {} while (!blocker.isReleasable() && !blocker.block());
}程序在do-while循环中无限地挂起。
编辑:我发现问题是由添加到我的自定义异常类中的toString()方法引起的。由于某种原因,它在Java11之后开始成为一个问题
发布于 2021-11-25 15:52:53
该问题是由于ReflectionToStringBuilder.toString使用封装的java API造成的。
我们可以尝试像MyException.wrapIfNeeded(new NullPointerException("")).toString()这样的东西,然后看看
线程"main“java.lang.reflect.InaccessibleObjectException:中的
异常无法使字段静态最终长java.lang.RuntimeException.serialVersionUID可访问:模块java.base不能对未命名的模块@b4c966a”打开java.lang“
为什么这个事业会无休止地悬而未决?
CompletableFuture.AsyncSupply#run方法中
static final class AsyncSupply<T> extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {
...
public void run() {
CompletableFuture<T> d; Supplier<? extends T> f;
if ((d = dep) != null && (f = fn) != null) {
dep = null; fn = null;
if (d.result == null) {
try {
d.completeValue(f.get());
} catch (Throwable ex) {
d.completeThrowable(ex);
}
}
d.postComplete();
}
}因为抛出了MyException,所以调用了d.completeThrowable(ex);,在此方法中,它会将异常封装到CompletionException,后者将调用Throwable的构造函数,并将MyException作为cause。
public Throwable(Throwable cause) {
fillInStackTrace();
detailMessage = (cause==null ? null : cause.toString());
this.cause = cause;
}当cause.toString()被调用时,它将抛出前面提到的异常,因此d.completeThrowable(ex);没有完全执行,因此程序将永远挂起。
发布于 2021-11-25 15:31:39
我发现这个问题是由添加到自定义异常类中的toString()方法引起的。由于某些原因(或者更准确地说:ReflectionToStringBuilder.toString(this);)在Java11之后开始成为一个问题。
https://stackoverflow.com/questions/70111913
复制相似问题