[ https://issues.apache.org/jira/browse/GROOVY-11365?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17842699#comment-17842699 ]
Eric Milles edited comment on GROOVY-11365 at 5/1/24 4:02 PM: -------------------------------------------------------------- In general, I think the JVM enforces that only a subclass can access a protected member (outside of the declaring package). Dynamic mode Groovy indexes protected members down the inheritance chain and provides a mechanism for inner types to pass along method missing to outer types. When a method reference is linked to an invoke dynamic call of Java's {{LambdaMetaFactory}}, the Groovy MOP is bypassed. For your test case, "this" is translated to "getThisObject()". Then an invoke dynamic call `java.lang.invoke.LambdaMetafactory.metafactory(???, "accept", "(LC11365;)Ljava/util/function/Consumer;", "(Ljava/lang/Object;)V", groovy/transform/stc/A11365.op(Ljava/lang/Object;)Ljava/lang/Object; (5), "(Ljava/lang/Integer;)V")` is written. I think the first argument is the Lookup from the closure class (the caller/sender). So, "getThisObject().op(42)" looks like any other third-party method call. It is not a "this" or "super" and C11365 is not a super class. Not sure if there is any way to indicate outer class status. was (Author: emilles): In general, I think the JVM enforces that only a subclass can access a protected member (outside of the declaring package). Dynamic mode Groovy indexes protected members down the inheritance chain and provides a mechanism for inner types to pass along method missing to outer types. When a method reference is linked to an invoke dynamic call of Java's {{LambdaMetaFactory}}, the Groovy MOP is bypassed. For your test case, "this" is translated to "getThisObject()". Then an invoke dynamic call `java.lang.invoke.LambdaMetafactory.metafactory(???, "accept", "(LC11365;)Ljava/util/function/Consumer;", "(Ljava/lang/Object;)V", groovy/transform/stc/A11365.op(Ljava/lang/Object;)Ljava/lang/Object; (5), "(Ljava/lang/Integer;)V")` is written. I think the first argument is the Lookup from the closure class (the caller/sender). > IllegalAccessError when using protected method as reference > ----------------------------------------------------------- > > Key: GROOVY-11365 > URL: https://issues.apache.org/jira/browse/GROOVY-11365 > Project: Groovy > Issue Type: Bug > Components: Compiler > Affects Versions: 4.0.18, 5.0.0-alpha-8, 4.0.21 > Reporter: Christopher Smith > Assignee: Eric Milles > Priority: Critical > > I will try to repro this, but posting in case the description is sufficient > to identify the problem: > I have an abstract base class {{AbstractServiceImpl<E extends Entity>}} that > defines {{protected final E upsert(E entity)}}. From a subclass inside a > closure, I try to use {{this::upsert}} as a {{Consumer<DocumentRequest>}}. > Starting somewhere between 4.0.14 and 4.0.18 (other bugs prevent me from > bisecting further), an {{IllegalAccessError}} gets introduced at runtime: > {code} > java.lang.IllegalAccessError: class > com.example.doc.DocumentRequestServiceImpl$_openUpload_closure2 tried to > access protected method 'com.example.base.Entity > com.example.base.AbstractServiceImpl.upsert(com.example.base.Entity)' > (com.example.doc.DocumentRequestServiceImpl$_openUpload_closure2 and > com.example.base.AbstractServiceImpl are in unnamed module of loader 'app') > {code} > I've examined the bytecode for both the call site and the method > implementation, and I can't see a difference in the code generated between > 4.0.14 and 4.0.18/21. I'm not certain why it works in 4.0.14, but with javac > I would expect to see a lambda bridge to allow the lambda to access the > containing-class-visible-but-only-by-inheritance protected method. -- This message was sent by Atlassian Jira (v8.20.10#820010)