Scala Programming Language
  1. Scala Programming Language
  2. SI-6548

JVM crashes when reflecting a Scala class with a Java annotation with a nested enumeration type

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: Scala 2.10.0-RC2, Scala 2.10.0
    • Fix Version/s: Scala 2.11.0-M2
    • Component/s: Reflection
    • Environment:

      Description

      Given the following Java annotation:

      Anno.java
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      
      @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD,
          ElementType.TYPE, ElementType.PARAMETER})
      @Retention(RetentionPolicy.RUNTIME)
      public @interface Anno
      {
          public Value value() default Value.VALUE;
      
          public enum Value
          {
              VALUE;
          }
      }
      

      An the following Scala class:

      Bean.scala
      import reflect.runtime.currentMirror
      
      class Bean {
        @Anno(Anno.Value.VALUE)
        def value = 1
      }
      
      object Bean extends App {
        currentMirror.classSymbol(classOf[Bean]).isCaseClass
        
      }
      

      Under a recent 2.10.0 snapshot, compilation succeeds, but running Bean.scala in the code runner produces this crash:

      $ javac Anno.java
      $ scalac Bean.scala
      $ scala Bean
      scala.reflect.internal.FatalError: bad symbolic reference to value Value in object Anno (a classfile may be missing)
      	at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:48)
      	at scala.reflect.internal.SymbolTable.globalError(SymbolTable.scala:47)
      	at scala.reflect.internal.Symbols$StubSymbol$class.fail(Symbols.scala:3110)
      	at scala.reflect.internal.Symbols$StubSymbol$class.info(Symbols.scala:3123)
      	at scala.reflect.internal.Symbols$StubTermSymbol.info(Symbols.scala:3132)
      	at scala.reflect.internal.Symbols$StubTermSymbol.info(Symbols.scala:3132)
      	at scala.reflect.internal.pickling.UnPickler$Scan.scala$reflect$internal$pickling$UnPickler$Scan$$fromName$1(UnPickler.scala:207)
      	at scala.reflect.internal.pickling.UnPickler$Scan.readExtSymbol$1(UnPickler.scala:226)
      	at scala.reflect.internal.pickling.UnPickler$Scan.readSymbol(UnPickler.scala:245)
      	at scala.reflect.internal.pickling.UnPickler$Scan.readSymbolRef(UnPickler.scala:778)
      	at scala.reflect.internal.pickling.UnPickler$Scan.readConstant(UnPickler.scala:416)
      	at scala.reflect.internal.pickling.UnPickler$Scan$$anonfun$readClassfileAnnotArg$3.apply(UnPickler.scala:454)
      	at scala.reflect.internal.pickling.UnPickler$Scan$$anonfun$readClassfileAnnotArg$3.apply(UnPickler.scala:454)
      	at scala.reflect.internal.pickling.UnPickler$Scan.at(UnPickler.scala:171)
      	at scala.reflect.internal.pickling.UnPickler$Scan.readClassfileAnnotArg(UnPickler.scala:454)
      	at scala.reflect.internal.pickling.UnPickler$Scan.readAnnotationInfo(UnPickler.scala:468)
      	at scala.reflect.internal.pickling.UnPickler$Scan.readSymbolAnnotation(UnPickler.scala:486)
      	at scala.reflect.internal.pickling.UnPickler$Scan.run(UnPickler.scala:88)
      	at scala.reflect.internal.pickling.UnPickler.unpickle(UnPickler.scala:37)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror.unpickleClass(JavaMirrors.scala:561)
      	at scala.reflect.runtime.SymbolLoaders$TopClassCompleter.complete(SymbolLoaders.scala:31)
      	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1217)
      	at scala.reflect.internal.Symbols$Symbol.initialize(Symbols.scala:1349)
      	at scala.reflect.internal.Symbols$Symbol.hasFlag(Symbols.scala:603)
      	at scala.reflect.internal.Symbols$ClassSymbol.isCaseClass(Symbols.scala:2864)
      	at Bean$delayedInit$body.apply(Bean.scala:10)
      	at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
      	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
      	at scala.App$$anonfun$main$1.apply(App.scala:71)
      	at scala.App$$anonfun$main$1.apply(App.scala:71)
      	at scala.collection.immutable.List.foreach(List.scala:309)
      	at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
      	at scala.App$class.main(App.scala:71)
      	at Bean$.main(Bean.scala:9)
      	at Bean.main(Bean.scala)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      	at java.lang.reflect.Method.invoke(Method.java:597)
      	at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:71)
      	at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
      	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:139)
      	at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:71)
      	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:139)
      	at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:28)
      	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45)
      	at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:35)
      	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45)
      	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:74)
      	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
      	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105)
      	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
      java.lang.RuntimeException: error reading Scala signature of Bean: bad symbolic reference to value Value in object Anno (a classfile may be missing)
      	at scala.reflect.internal.pickling.UnPickler.unpickle(UnPickler.scala:45)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror.unpickleClass(JavaMirrors.scala:561)
      	at scala.reflect.runtime.SymbolLoaders$TopClassCompleter.complete(SymbolLoaders.scala:31)
      	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1217)
      	at scala.reflect.internal.Symbols$Symbol.initialize(Symbols.scala:1349)
      	at scala.reflect.internal.Symbols$Symbol.hasFlag(Symbols.scala:603)
      	at scala.reflect.internal.Symbols$ClassSymbol.isCaseClass(Symbols.scala:2864)
      	at Bean$delayedInit$body.apply(Bean.scala:10)
      	at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
      	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
      	at scala.App$$anonfun$main$1.apply(App.scala:71)
      	at scala.App$$anonfun$main$1.apply(App.scala:71)
      	at scala.collection.immutable.List.foreach(List.scala:309)
      	at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
      	at scala.App$class.main(App.scala:71)
      	at Bean$.main(Bean.scala:9)
      	at Bean.main(Bean.scala)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      	at java.lang.reflect.Method.invoke(Method.java:597)
      	at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:71)
      	at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
      	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:139)
      	at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:71)
      	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:139)
      	at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:28)
      	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45)
      	at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:35)
      	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45)
      	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:74)
      	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
      	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105)
      	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
      

        Issue Links

          Activity

          Hide
          Paul Phillips added a comment -

          The "object Anno" needs a member "object Value" which it has not been given. Either that or we need to do better at being flexible when someone uses a path involving java classes, and treat the dots as type selections when necessary and valid in java.

          scala> import scala.reflect.runtime.universe._
          import scala.reflect.runtime.universe._
          
          scala> typeOf[Anno].declarations
          res1: reflect.runtime.universe.MemberScope = SynchronizedOps(class Value, object Value, method value)
          
          // Geez, is this really the most direct route to the type of the companion
          scala> typeOf[Anno].typeSymbol.companionSymbol.typeSignature.declarations
          res2: reflect.runtime.universe.MemberScope = SynchronizedOps(class Value)
          
          Show
          Paul Phillips added a comment - The "object Anno" needs a member "object Value" which it has not been given. Either that or we need to do better at being flexible when someone uses a path involving java classes, and treat the dots as type selections when necessary and valid in java. scala> import scala.reflect.runtime.universe._ import scala.reflect.runtime.universe._ scala> typeOf[Anno].declarations res1: reflect.runtime.universe.MemberScope = SynchronizedOps(class Value, object Value, method value) // Geez, is this really the most direct route to the type of the companion scala> typeOf[Anno].typeSymbol.companionSymbol.typeSignature.declarations res2: reflect.runtime.universe.MemberScope = SynchronizedOps(class Value)
          Show
          Eugene Burmako added a comment - https://github.com/scala/scala/pull/1727
          Hide
          Paul Phillips added a comment -

          f274490

          Show
          Paul Phillips added a comment - f274490
          Hide
          Adriaan Moors added a comment - - edited

          Due to binary compatibility restrictions, this cannot go into 2.10.1-RC1.

          See https://github.com/scala/scala/pull/2103.

          Show
          Adriaan Moors added a comment - - edited Due to binary compatibility restrictions, this cannot go into 2.10.1-RC1. See https://github.com/scala/scala/pull/2103 .

            People

            • Assignee:
              Eugene Burmako
              Reporter:
              Christopher Currie
            • Votes:
              1 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development