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

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Jan 8 11:02:23 UTC 2015


Hi Peter,
this is an issue we know about - the generated bytecode is correct - but 
it's likely we'll need to enhance it to have the bootstrap saying 
something like:

TT;=T

(i.e. tvar = type)

This will help the specializer figuring out that there's really nothing 
to do, since T is itself not specialized, so the erased version of the 
method should be used.

Maurizio


On 08/01/15 08:09, 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