Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-10450

Cannot call BiPredicate methods on closures or lambdas on JRE 16+

Attach filesAttach ScreenshotVotersWatch issueWatchersCreate sub-taskLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 3.0.9
    • 3.0.16
    • None

    Description

      The issue was first discovered by a Spock user in Spock-1412.

      Under Groovy 3.0.9, the following code works on JREs 8-15, but starts failing on 16+, possibly due to JEP 396 (Strongly Encapsulate JDK Internals by Default):

      import java.util.function.BiPredicate
      
      class CombineBiPredicatesAndClosures {
        static void main(String[] args) {
          println "Java version: ${System.properties['java.version']}"
      
          // Old-school anonymous class instead of closure or lambda
          /*
          BiPredicate<String, Integer> bi = new BiPredicate<String, Integer>() {
            @Override
            boolean test(String domain, Integer score) {
              return domain.equalsIgnoreCase("google.com")
            }
          }
          */
      
          // Lambda syntax only works in Groovy 3+
          //BiPredicate<String, Integer> bi = (domain, score) -> domain.equalsIgnoreCase("google.com")
          //def bi2 = (domain, score) -> score == 11
      
          // Closure syntax works in Groovy 2.5, too
          BiPredicate<String, Integer> bi = { domain, score -> domain.equalsIgnoreCase("google.com") }
          def bi2 = { domain, score -> score == 11 }
      
          def logicalNot = bi.negate()
          assert logicalNot.test("acme.org", 11)
          assert !logicalNot.test("google.com", 11)
      
          def logicalOr = bi | bi2
          assert logicalOr.test("google.com", 11)
          assert logicalOr.test("google.com", 0)
          assert logicalOr.test("x", 11)
          assert !logicalOr.test("x", 0)
      
          def logicalAnd = bi & bi2
          assert logicalAnd.test("google.com", 11)
          assert !logicalAnd.test("google.com", 0)
          assert !logicalAnd.test("x", 11)
          assert !logicalAnd.test("x", 0)
        }
      }
      

      Running the program yields something like:

      Java version: 16
      Exception in thread "main" java.lang.reflect.InvocationTargetException
      	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
      	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
      	at org.codehaus.groovy.vmplugin.v9.Java9.of(Java9.java:160)
      	at org.codehaus.groovy.vmplugin.v9.Java9.getInvokeSpecialHandle(Java9.java:179)
      	at org.codehaus.groovy.runtime.ConversionHandler.lambda$invoke$0(ConversionHandler.java:97)
      	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
      	at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:97)
      	at jdk.proxy1/jdk.proxy1.$Proxy9.negate(Unknown Source)
      	at java_util_function_BiPredicate$negate.call(Unknown Source)
      	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)
      	at CombineBiPredicatesAndClosures.main(CombineBiPredicatesAndClosures.groovy:25)
      Caused by: java.lang.IllegalAccessException: module jdk.proxy1 does not open jdk.proxy1 to unnamed module @153f5a29
      	at java.base/java.lang.invoke.MethodHandles.privateLookupIn(MethodHandles.java:260)
      	... 15 more
      

      When running the same program on Groovy 4.0.0-rc-2, there are no problems on JDK 16+. Using the commented-out anonymous class instead of either a lambda or closure also works around the problem on Groovy 3.

      Could you please fix this for the next 3.0.x version? Thank you.

      Attachments

        Issue Links

        Activity

          This comment will be Viewable by All Users Viewable by All Users
          Cancel

          People

            emilles Eric Milles
            kriegaex Alexander Kriegisch
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Slack

                Issue deployment