javap difference when compiling with/without assertion
Pergunta
Scala for the Impatient Chapter 15 Exercise 10: Add assert(n >= 0
to a factorial
method. Compile with assertions enabled and verify that factorial(-1)
throws an exception. Compile without assertions. What happens? Use javap
to check what happened to the assertion call.
My code:
object Test {
def factorial(x: Int): Int = {
assert(x >= 0, "Call to factorial must be >= 0!")
x match {
case 0 => 1
case x: Int => x * factorial(x - 1)
}
}
def main(args: Array[String]): Unit = {
factorial(-1)
}
}
I compiled with scalac
first, inspected it using javap Test
, then compiled again with scalac -Xelide-below MAXIMUM
and inspected with the same command - I can't seem to find a difference between the two.
I understand compiling with assertions will throw the exception when I try to execute the program, and compiling without assertions will cause a stack overflow error, but I can't find the difference in javap
...
Solução
When I try this with javap -v
I find the following lines in the version with assertions enabled, but not in the other:
20: invokevirtual #27; //Method scala/Predef$.assert:(ZLscala/Function0;)V
...
27: if_icmpne 34
30: iconst_1
31: goto 55
So that certainly looks okay.
The problem may be that you're either not looking at the bytecode (which requires the -c
or -v
flag to javap
), or—much more likely—that you're looking at the output of javap
for the Test
class, not Test$
. See for example Programming in Scala for more detail:
For every Scala singleton object, the compiler will create a Java class for the object with a dollar sign added to the end. For a singleton object named
App
, the compiler produces a Java class namedApp$
. This class has all the methods and fields of the Scala singleton object.
If you list the contents of the directory you've compiled in, you'll see both Test.class
and Test$.class
. Using javap -v Test$
will show you the latter, which is where you'll find the difference.