Knows Not Much Knows Not Much - 1 month ago 6
Scala Question

Could not initialize class $line10.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$

I am starting my day with a weird problem. Really can't see what is wrong with my code. Take the lines below

import scala.concurrent._
import scala.concurrent.duration._
import scala.util._
import scala.concurrent.ExecutionContext.Implicits.global

def f2 = Future.failed(new Exception("I do nothing"))
def f1 = Future { println("working"); Thread.sleep(5000); 1 }

val list = List(f2, f1)
val consolidated = Future.sequence(list)
consolidated.onComplete {
case Success(_) => println("completed successfully")
case Failure(e) => println(s"failed with ${e.getMessage}")
}
Await.result(consolidated, Duration.Inf)


and do a
:paste
in the REPL. I see a weird exception

~ > scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_121).
Type in expressions for evaluation. Or try :help.

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.concurrent._
import scala.concurrent.duration._
import scala.util._
import scala.concurrent.ExecutionContext.Implicits.global

def f2 = Future.failed(new Exception("no work"))
def f1 = Future { println("working"); Thread.sleep(5000); 1 }

val list = List(f2, f1)
val consolidated = Future.sequence(list)
consolidated.onComplete {
case Success(_) => println("completed successfully")
case Failure(e) => println(s"failed with ${e.getMessage}")
}
Await.result(consolidated, Duration.Inf)


// Exiting paste mode, now interpreting.

java.lang.NoClassDefFoundError: Could not initialize class $line3.$read$$iw$$iw$
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60)
at scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:140)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
java.lang.NoClassDefFoundError: Could not initialize class $line3.$read$$iw$$iw$
at scala.runtime.java8.JFunction0$mcI$sp.apply(JFunction0$mcI$sp.java:12)
at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:653)
at scala.util.Success.$anonfun$map$1(Try.scala:251)
at scala.util.Success.map(Try.scala:209)
at scala.concurrent.Future.$anonfun$map$1(Future.scala:287)
at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:29)
at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:29)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60)
at scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:140)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
java.lang.Exception: I do nothing
at .f2(<console>:16)
... 29 elided

scala>


I really see no reason for
Could not initialize class
errors. According to me the code should just print "failed with no work"

Answer Source

The problem is this

Await.result(consolidated, Duration.Inf)

when you Await a Future, and that future fails, the exception it contains is thrown. Due to how the REPL works, having an uncaught exception causes some of its machinery to break. This seems like a bug in the REPL, but it doesn't seem to have been reported yet.

Note than onComplete doesn't change the result of a Future. It simply schedules something to be done after the Future is complete. In particular, it does not consume the Future. If you meant to transform the Future, you would do something like this:

val transformed: Future[String] = consolidated.andThen {
  case Success(v) => "Completed successfully"
  case Failure(e) => s"Failed with ${e.getMessage}"
}

println(Await.result(transformed, Duration.Inf))