Hi Arno,
I did some research on that issue and this is what I found:
Janino 2.5.6 seems to have a problem when generating bytecode for calling a method of an interface if this method is not declared in that interface
and is also not defined in the actual implementation of that interface but instead is inherited directly from java.lang.Object. This is always the
case with the method getClass() which is declared final in java.lang.Object.
Here is an example:
When you compile this class with janino 2.5.6 and try to execute the code you get the exception:
line 9 in the source code above is:
But when you compile this class with janino 2.3.16 or 2.3.17 or with Sun's javac 1.4.2 or 1.5.0 you get the correct behaviour and the program reports
when executed.
If you take a look at the generated bytecode utilising Sun's javap the problem is easy to see:
janino 2.5.6 compiles the method call getClass() as
while janino 2.3.16, 2.3.17 and javac 1.4.2, 1.5.0 translate it to
I think this is where the problem originates in. I suppose the bytecode generated with janino 2.3.16, 2.3.17 or javac 1.4.2, 1.5.0 is correct while the bytecode generated with janino 2.5.6 is incorrect because the getClass() method should be called on java.lang.Object.
As I discovered further, calling the getClass() method on java.util.List instead of on java.lang.Object occurs the first time (after janino 2.3.16) in janino 2.3.18.
I had a look into the janino 2.5.6 sources and I think the problem might be the code at UnitCompiler.java line 2823:
The call of compileGetValue returns an IClass object for targetType that represents a java.util.List instead of a java.lang.Object.
targetType itself is used in line 2885:
If you replace line 2885 with
you get the following bytecode generated
and the exception doesn't occur.
However I'm not a janino expert and so I guess this approach has other undesirable side effects.
I think it may be better to change line 2823 or the method compileGetValue() that returns targetType.
Maybe it would be best to set
under certain circumstances, for instance when
represents java.lang.Object.
In this context I found something very interesting:
When you compile the following class
with janino 2.3.16, 2.3.17 or janino 2.5.6 you get list.hashCode() compiled to
and I think this is what everybody would expect because the method hashCode() is explicitly declared in the interfaces java.util.List and java.util.Collection.
The Sun compilers (javac 1.4.2 and 1.5.0) however translate list.hashCode() to
The compiled programs work for all versions alike but it seems that javac codes a invokevirtual call for java.lang.Object whenever the declaring class is java.lang.Object.
bye
Matthias
Hi Judith,
which JDK version and JANINO version do you use? Which line is line 10? I reckon the "public static final LOG..." line.
CU
Arno