You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Daniel Perano (JIRA)" <ji...@apache.org> on 2016/10/31 19:35:58 UTC

[jira] [Comment Edited] (GROOVY-7982) CompileStatic causes GroovyCastException when calling static methods on a Java class

    [ https://issues.apache.org/jira/browse/GROOVY-7982?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15623119#comment-15623119 ] 

Daniel Perano edited comment on GROOVY-7982 at 10/31/16 7:34 PM:
-----------------------------------------------------------------

Gladly. The project consists of mixed Java/Groovy sources which are compiled into a single executable jar. The Java Database class is my own and provides static access to a singleton database connection. The Groovy code is part of a command system that accesses the database. All Groovy sources are compiled and placed in the jar at build time and statically referenced by Java code (i.e. somewhere in Java code, cmdSys.addCommand(new MyGroovyDatabaseCommand())). This is why I don't see how it could be a classloader issue - there is no explicit classloading anywhere in the database system, and the code is all running from an executable jar launched with java -jar myapplication.jar - no WAR or OSGI or anything like that.

The stack trace makes it look to me like an issue with the code generator. If I'm reading the exception message correctly, the code is trying to cast a reference of type Class<Database> to Database, which of course will fail. This is consistent with the decompiled code, which is calling ScriptBytecodeAdapter.castToType(Database.class, Database.class), and the Javadoc for ScriptBytecodeAdapter.castToType() (http://docs.groovy-lang.org/2.4.7/html/api/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.html#castToType(java.lang.Object,%20java.lang.Class)) seems to confirm this.


was (Author: djperano):
Gladly. The project consists of mixed Java/Groovy sources which are compiled into a single executable jar. The Java Database class is my own and provides static access to a singleton database connection. The Groovy code is part of a command system that accesses the database. All Groovy sources are compiled and placed in the jar at build time and statically referenced by Java code (i.e., cmdSys.addCommand(new MyGroovyDatabaseCommand())). This is why I don't see how it could be a classloader issue - there is no explicit classloading anywhere in the database system, and the code is all running from an executable jar launched with java -jar myapplication.jar - no WAR or OSGI or anything like that.

The stack trace makes it look to me like an issue with the code generator. If I'm reading the exception message correctly, the code is trying to cast a reference of type Class<Database> to Database, which of course will fail. This is consistent with the decompiled code, which is calling ScriptBytecodeAdapter.castToType(Database.class, Database.class), and the Javadoc for ScriptBytecodeAdapter.castToType() (http://docs.groovy-lang.org/2.4.7/html/api/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.html#castToType(java.lang.Object,%20java.lang.Class)) seems to confirm this.

> CompileStatic causes GroovyCastException when calling static methods on a Java class
> ------------------------------------------------------------------------------------
>
>                 Key: GROOVY-7982
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7982
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 2.4.7
>            Reporter: Daniel Perano
>
> I have a project with mixed Java and Groovy sources. A Gradle build compiles the Java sources with javac and the Groovy sources with groovyc. There is a Java class that provides access to a database via static methods. The relevant methods in this class are shown below:
> {code:Java|title=Database.java}
> public class Database {
>     public boolean alreadyExists(String name){}
>     public boolean alreadyExists(UUID id){}
>     public void save(DataClass data){}
> }
> {code}
> The Groovy code that causes the GroovyCastException to be thrown is shown below:
> {code:Java|title=DBAccess.groovy}
> // name is an instance of java.lang.String
> // data is an instance of DataClass (see Database.java snippet above)
> if(!Database.alreadyExists(name)){
>     Database.save(data)
>     // ...
> }else{
>     // ...
> }
> {code}
> When the Groovy snippet above runs, the call to Database.alreadyExists() produces the following stack trace:
> org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'class mypackage.Database' with class 'java.lang.Class' to class 'mypackage.Database'
> 	at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnSAM(DefaultTypeTransformation.java:405)
> 	at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnNumber(DefaultTypeTransformation.java:319)
> 	at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:232)
> 	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.java:603)
> 	at myotherpackage.DBAccess.doStuff(DBAccess.groovy:56)
> However, if the if statement is removed, the Database.save() method completes successfully. Decompiling the DBAccess.class file produces the following:
> {code:Java|title=CompiledDBAccess.java}
> if (!((Database)ScriptBytecodeAdapter.castToType(Database.class, Database.class)).alreadyExists(name)) {
>      Database.save((DataClass)data);
>      //...
> } else {
>       //...
> }
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)