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

@WithReadLock in inner class of @CompileStatic class causes java.lang.VerifyError

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.5.2
    • 3.0.0-alpha-4, 2.5.3
    • None
    • Ubuntu 18.04 x86_64, OpenJDK 10

    Description

      Minimal reproduction:

      import groovy.transform.CompileStatic
      import groovy.transform.WithReadLock
      
      @CompileStatic
      class A {
          private class B {
              @WithReadLock
              int getFoo() {
                  0
              }
          }
      
          private B b
      
          A() {
              b = new B()
          }
      }
      
      def a = new A()
      

      Output from groovy:

      Caught: java.lang.VerifyError: Bad type on operand stack
      Exception Details:
        Location:
          A$B.getFoo()I @4: invokevirtual
        Reason:
          Type 'A' (current frame, stack[0]) is not assignable to 'java/util/concurrent/locks/ReentrantReadWriteLock$ReadLock'
        Current Frame:
          bci: @4
          flags: { }
          locals: { 'A$B' }
          stack: { 'A' }
        Bytecode:
          0x0000000: 2ab4 0015 b600 2d01 5703 3c00 2ab4 0015
          0x0000010: b600 3001 5700 1bac 0000 bf00 0000 0000
          0x0000020: 0000 0000 0000 00bf 4d2a b400 15b6 0030
          0x0000030: 0157 2cbf 0000 bf                      
        Exception Handler Table:
          bci [9, 12] => handler: 40
          bci [22, 24] => handler: 40
        Stackmap Table:
          full_frame(@24,{},{Object[#51]})
          same_locals_1_stack_item_frame(@27,Object[#51])
          full_frame(@40,{Object[#2]},{Object[#51]})
          full_frame(@52,{},{Object[#51]})
      
      java.lang.VerifyError: Bad type on operand stack
      Exception Details:
        Location:
          A$B.getFoo()I @4: invokevirtual
        Reason:
          Type 'A' (current frame, stack[0]) is not assignable to 'java/util/concurrent/locks/ReentrantReadWriteLock$ReadLock'
        Current Frame:
          bci: @4
          flags: { }
          locals: { 'A$B' }
          stack: { 'A' }
        Bytecode:
          0x0000000: 2ab4 0015 b600 2d01 5703 3c00 2ab4 0015
          0x0000010: b600 3001 5700 1bac 0000 bf00 0000 0000
          0x0000020: 0000 0000 0000 00bf 4d2a b400 15b6 0030
          0x0000030: 0157 2cbf 0000 bf                      
        Exception Handler Table:
          bci [9, 12] => handler: 40
          bci [22, 24] => handler: 40
        Stackmap Table:
          full_frame(@24,{},{Object[#51]})
          same_locals_1_stack_item_frame(@27,Object[#51])
          full_frame(@40,{Object[#2]},{Object[#51]})
          full_frame(@52,{},{Object[#51]})
      
          at A.<init>(test.groovy:16)
          at test.run(test.groovy:20)

      From a glance at the bytecode, it looks like Groovy is creating the $reentrantlock field in A$B as it should, but in the actual method it tries to use this$0 (i.e. the reference to the enclosing outer A object) as a ReentrantReadWriteLock instead.

      This error also occurs with @WithWriteLock, but doesn't occur with @Synchronized.

      Attachments

        Issue Links

          Activity

            People

              paulk Paul King
              curtis.mackie Curtis Mackie
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: