You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Shil Sinha (JIRA)" <ji...@apache.org> on 2015/10/09 21:56:05 UTC

[jira] [Comment Edited] (GROOVY-7549) java.lang.IllegalAccessError occurs when attempting to run code built with CompileStatic

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

Shil Sinha edited comment on GROOVY-7549 at 10/9/15 7:55 PM:
-------------------------------------------------------------

The underlying issue, I think, is that `if1.doStuff()` results in an invokevirtual instruction targeting the implementation when compiled with @CompileStatic, rather than an invokeinterface instruction (which is what the equivalent java code would yield). This is a result of the way direct method call targets are chosen; the inferred type of a receiver is 'preferred' to the declared type of the accessed variable, causing TheImplementation.doStuff() to be chosen over TheInterface.doStuff().


was (Author: shils):
The underlying issue, I think, is that `if1.doStuff()` results in an invokeVirtual instruction when compiled with @CompileStatic, rather than an invokeInterface instruction (which is what the equivalent java code would yield). This appears to be a result of the way direct method call targets are chosen; the inferred type of a receiver is 'preferred' to the declared type of the accessed variable, causing TheImplementation.doStuff() to be chosen over TheInterface.doStuff().

> java.lang.IllegalAccessError occurs when attempting to run code built with CompileStatic
> ----------------------------------------------------------------------------------------
>
>                 Key: GROOVY-7549
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7549
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 2.4.4
>            Reporter: Steven Walters
>            Priority: Minor
>
> Given a small code setup such as the following, where there exists a
> # A publicly declared interface
> # A package private implementation of the interface
> # A static factory class that returns an instance of the implementation *as the implementation class*
> {code:title=packa.TheInterface.groovy|borderStyle=solid}
> package packa
> public interface TheInterface {
>     public void doStuff()
> }
> {code}
> {code:title=packb.TheImplementation.groovy|borderStyle=solid}
> package packb
> import packa.TheInterface
> @groovy.transform.CompileStatic
> @groovy.transform.PackageScope
> class TheImplementation implements TheInterface {
>     public void doStuff() {
>         System.out.println("Do some stuff")
>     }
> }
> {code}
> {code:title=packb.TheFactory.groovy|borderStyle=solid}
> package packb
> public class TheFactory {
>     static TheImplementation getAnInstance() {
>         return new TheImplementation()
>     }
> }
> {code}
> With CompileStatic, calling the factory method successfully works, but calling any method on the returned object fails with {{java.lang.IllegalAccessError}}.
> When CompileStatic is removed, the code runs without issue.
> Such as the following.
> {code:title=packa.TheMain.groovy|borderStyle=solid}
> package packa
> import packb.TheFactory
> @groovy.transform.CompileStatic
> public class TheMain {
>     public static void main(String[] args) {
>         TheInterface if1 = TheFactory.anInstance
>         /* the following only fails when CompileStatic is enabled with the following error:
>          * Exception in thread "main" java.lang.IllegalAccessError: tried to access class packb.TheImplementation from class packa.TheMain */
>         if1.doStuff()
>     }
> }
> {code}
> There seem to be some interesting factors here, as changing the {{TheFactory}} to return {{TheInterface}} instead of {{TheImplemenation}} also seems to resolve the issue.
> However, changing the return of the {{TheFactory}} is not desirable, as in the actual production the above sample was formulated from, there are other classes in the {{packb}} package that utilize {{TheFactory}} and should not require class casts from {{TheInterface}} to {{TheImplementation}}



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