8

When I execute following code in scala REPL console:

java.util.Collections.max(new java.util.ArrayList[String]())

NoSuchMethodError exception is thrown:

java.lang.NoSuchMethodError: java.util.Collections.max(Ljava/util/Collection;)Lj
ava/lang/Comparable;
        at .<init>(<console>:8)
        at .<clinit>(<console>)
        at .<init>(<console>:11)
        at .<clinit>(<console>)
        at $export(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:592)

        at scala.tools.nsc.interpreter.IMain$Request$$anonfun$10.apply(IMain.sca
la:828)
        at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:4
3)
        at scala.tools.nsc.io.package$$anon$2.run(package.scala:31)
        at java.lang.Thread.run(Thread.java:662)

Scala 2.9.0.1, Java 1.6.0_25

Why an exception is thrown here? The same code executed from Java behaves as expected (throws NoSuchElementException).

0

1 Answer 1

5

This is a compiler bug that is affecting both Scala 2.8 and 2.9, where the compiler does not compute the proper erasured method signature. I am not aware of a bug report.

Compiling the method:

object Test { def main(a: Array[String]) {
  val a = new java.util.ArrayList[String]()
  java.util.Collections.max(a)
}}

Results into the following bytecode:

public void main(java.lang.String[]);
  Code:
   Stack=2, Locals=3, Args_size=2
   0:   new #16; //class java/util/ArrayList
   3:   dup
   4:   invokespecial   #18; //Method java/util/ArrayList."<init>":()V
   7:   astore_2
   8:   aload_2
   9:   invokestatic    #24; //Method java/util/Collections.max:(Ljava/util/Collection;)Ljava/lang/Comparable;
   12:  pop
   13:  return

Please note that bytecode at offset 9 invokes a static method with a Comparable return type, while the actual Collections.max has Object as the return type:

$ javap -p java.util.Collections | grep max
    public static java.lang.Object max(java.util.Collection);
Sign up to request clarification or add additional context in comments.

2 Comments

Curious. Javadoc says <T extends Object & Comparable<? super T>> T.
@Daniel, The JVM looks at the erasured type of the method; so T gets erasured to Object, but Scalac expects it to be erasured to Comparable. You can review my email in the scala-user mailing list for more details.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.