title: Throwing exception from CompletableFuture hangs get() and join() in Java 17
body: <p>After I have switched from Java 11 to Java 17 (OpenJDK installed from Ubuntu 20.04 repository), the following code doesn't work:</p>
  <pre class="lang-java prettyprint-override"><code>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&lt;String&gt; streamFuture = CompletableFuture.supplyAsync(() -&gt; {
              throw MyException.wrapIfNeeded(new Exception(&quot;MyException&quot;));
          });
          String result = null;
          try {
              result = streamFuture.get();
          } catch (Exception e) {
              System.out.println(&quot;Exception: &quot; + ExceptionUtils.getMessage(e));
          }
          System.out.println(&quot;Result: &quot; + 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);
          }
      }
  }
  </code></pre>
  <p>There is a problem in <code>streamFuture.get()</code> - it hangs infinitely. I dug deeper and found that in <code>java.util.concurrent.ForkJoinPool</code> there is a method <code>unmanagedBlock(ManagedBlocker blocker)</code> which looks like</p>
  <pre class="lang-java prettyprint-override"><code>    /** ManagedBlock for external threads */
      private static void unmanagedBlock(ManagedBlocker blocker)
          throws InterruptedException {
          if (blocker == null) throw new NullPointerException();
          do {} while (!blocker.isReleasable() &amp;&amp; !blocker.block());
      }
  </code></pre>
  <p>and the program hangs infinitely in the do-while loop.</p>
  <p>EDIT:
  I found out the problem is cause by the <code>toString()</code> method added to my custom exception class. For some reason it started to be a problem after Java 11</p>