runtime failure when "any T" generic method calls another "any T" generic method

Brian Goetz brian.goetz at oracle.com
Thu Jan 8 15:45:16 UTC 2015


Looks like a simple bug where some code path in the specializer is 
forgetting to check for "is this uninstantiated?  if so, ignore it and 
fall back to erased."  We've had a few of these before.

Thanks for the bug report.

On 1/8/2015 3:09 AM, Peter Levart wrote:
> Hi,
>
> Here's another problem I found:
>
>
> public class ValhallaTest<any T> {
>
>      static <any T> void test2() {
>          Class<?> clazz = ValhallaTest<T>.class; // line 7
>          System.out.println("test2 >>> " + clazz);
>      }
>
>      static <any T> void test1() {
>          Class<?> clazz = ValhallaTest<T>.class;
>          System.out.println("test1 >>> " + clazz);
>
>          ValhallaTest.<T>test2();
>      }
>
>      public static void main(String[] args) {
>          ValhallaTest.<boolean>test1();
>          ValhallaTest.<byte>test1();
>          ValhallaTest.<char>test1();
>          ValhallaTest.<short>test1();
>          ValhallaTest.<int>test1();
>          ValhallaTest.<long>test1();
>          ValhallaTest.<float>test1();
>          ValhallaTest.<double>test1();
>          ValhallaTest.<Object>test1();
>          ValhallaTest.<String>test1();
>      }
> }
>
>
> Which prints:
>
>
> Specializing method ValhallaTest$test1${0=Z}.test1()V with class=[] and
> method=[Z]
> Specializing ValhallaTest${0=Z}; searching for ValhallaTest.class (not
> found)
> Specializing ValhallaTest${0=Z}; searching for ValhallaTest.class (found)
> test1 >>> class ValhallaTest${0=Z}
> Specializing method ValhallaTest$test2${0=Z}.test2()V with class=[] and
> method=[Z]
> test2 >>> class ValhallaTest${0=Z}
> Specializing method ValhallaTest$test1${0=B}.test1()V with class=[] and
> method=[B]
> Specializing ValhallaTest${0=B}; searching for ValhallaTest.class (not
> found)
> Specializing ValhallaTest${0=B}; searching for ValhallaTest.class (found)
> test1 >>> class ValhallaTest${0=B}
> Specializing method ValhallaTest$test2${0=B}.test2()V with class=[] and
> method=[B]
> test2 >>> class ValhallaTest${0=B}
> Specializing method ValhallaTest$test1${0=C}.test1()V with class=[] and
> method=[C]
> Specializing ValhallaTest${0=C}; searching for ValhallaTest.class (not
> found)
> Specializing ValhallaTest${0=C}; searching for ValhallaTest.class (found)
> test1 >>> class ValhallaTest${0=C}
> Specializing method ValhallaTest$test2${0=C}.test2()V with class=[] and
> method=[C]
> test2 >>> class ValhallaTest${0=C}
> Specializing method ValhallaTest$test1${0=S}.test1()V with class=[] and
> method=[S]
> Specializing ValhallaTest${0=S}; searching for ValhallaTest.class (not
> found)
> Specializing ValhallaTest${0=S}; searching for ValhallaTest.class (found)
> test1 >>> class ValhallaTest${0=S}
> Specializing method ValhallaTest$test2${0=S}.test2()V with class=[] and
> method=[S]
> test2 >>> class ValhallaTest${0=S}
> Specializing method ValhallaTest$test1${0=I}.test1()V with class=[] and
> method=[I]
> Specializing ValhallaTest${0=I}; searching for ValhallaTest.class (not
> found)
> Specializing ValhallaTest${0=I}; searching for ValhallaTest.class (found)
> test1 >>> class ValhallaTest${0=I}
> Specializing method ValhallaTest$test2${0=I}.test2()V with class=[] and
> method=[I]
> test2 >>> class ValhallaTest${0=I}
> Specializing method ValhallaTest$test1${0=J}.test1()V with class=[] and
> method=[J]
> Specializing ValhallaTest${0=J}; searching for ValhallaTest.class (not
> found)
> Specializing ValhallaTest${0=J}; searching for ValhallaTest.class (found)
> test1 >>> class ValhallaTest${0=J}
> Specializing method ValhallaTest$test2${0=J}.test2()V with class=[] and
> method=[J]
> test2 >>> class ValhallaTest${0=J}
> Specializing method ValhallaTest$test1${0=F}.test1()V with class=[] and
> method=[F]
> Specializing ValhallaTest${0=F}; searching for ValhallaTest.class (not
> found)
> Specializing ValhallaTest${0=F}; searching for ValhallaTest.class (found)
> test1 >>> class ValhallaTest${0=F}
> Specializing method ValhallaTest$test2${0=F}.test2()V with class=[] and
> method=[F]
> test2 >>> class ValhallaTest${0=F}
> Specializing method ValhallaTest$test1${0=D}.test1()V with class=[] and
> method=[D]
> Specializing ValhallaTest${0=D}; searching for ValhallaTest.class (not
> found)
> Specializing ValhallaTest${0=D}; searching for ValhallaTest.class (found)
> test1 >>> class ValhallaTest${0=D}
> Specializing method ValhallaTest$test2${0=D}.test2()V with class=[] and
> method=[D]
> test2 >>> class ValhallaTest${0=D}
> test1 >>> class ValhallaTest
> Specializing method ValhallaTest$test2${}.test2()V with class=[] and
> method=[TT;]
> Exception in thread "main" java.lang.NoClassDefFoundError: ValhallaTest<TT
>          at ValhallaTest$test2${}/401625763.test2(ValhallaTest.java:7)
>          at ValhallaTest.test1(ValhallaTest.java:15)
>          at ValhallaTest.main(ValhallaTest.java:27)
> Caused by: java.lang.ClassNotFoundException: ValhallaTest<TT
>          at java.net.URLClassLoader.findClass(URLClassLoader.java:451)
>          at java.lang.ClassLoader.loadClass(ClassLoader.java:426)
>          at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:317)
>          at java.lang.ClassLoader.loadClass(ClassLoader.java:359)
>          ... 3 more
>
>
> Within tes1() method, everything works fine, but cascading call to
> test2() fails in line 7 where ValhallaTest<T>.class is evaluated, but
> only for reference type T.
>
> Note that there's no specialization for test1() being triggered for
> T=reference (which is understandable), but there is a specialization
> being triggered for cascaded call to test2() in this case. In my
> superficial understanding a call to:
>
>      ValhallaTest.<Object>test1();
>
> ...is implemented as invokestatic, but a call from test1() to:
>
>      ValhallaTest.<T>test2();
>
> ...is implemented as invokedynamic. So in case such call comes from
> non-specialized test1(), it should be wired directly to the
> nonspecialized test2() method, right?
>
> Or, couldn't the call from nonspecialized test1() to .<T>test2() also be
> implemented as invokestatic and be converted to invokedynamic only by
> specialization?
>
> Regards, Peter
>


More information about the valhalla-dev mailing list