Uploaded image for project: 'Java Mission Control'
  1. Java Mission Control
  2. JMC-6819

Agent instrumentation causing stack map frame verification error

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P2 P2
    • 8.0.0
    • None
    • Mission Control Core
    • None

      Exception Details:

      Exception in thread "main" java.lang.VerifyError: Bad local variable type
      Exception Details:
        Location:
          com/tabjy/dining_philosophers/Chopstick.pickUp(Lcom/tabjy/dining_philosophers/Philosopher;J)Z @34: aload_0
        Reason:
          Type top (current frame, locals[0]) is not assignable to reference type
        Current Frame:
          bci: @34
          flags: { }
          locals: { top, top, top, top, 'com/tabjy/dining_philosophers/__JFREventChopstickPickUp' }
          stack: { }
        Bytecode:
          0000000: bb00 2a59 59b7 002b b600 2e3a 042a b400
          0000010: 1f20 b200 34b6 0038 9a00 0a03 1904 b600
          0000020: 3bac 2a2b b500 3d04 1904 b600 3bac     
        Stackmap Table:
          full_frame(@34,{Top,Top,Top,Top,Object[#42]},{})
      
      	at com.tabjy.dining_philosophers.DiningPhilosophers.main(DiningPhilosophers.java:17)
       
      

      Post-instrumentation bytecode:

        public boolean pickUp(com.tabjy.dining_philosophers.Philosopher, long) throws java.lang.InterruptedException;
          descriptor: (Lcom/tabjy/dining_philosophers/Philosopher;J)Z
          flags: (0x0001) ACC_PUBLIC
          Code:
            stack=4, locals=5, args_size=3
               0: new           #42                 // class com/tabjy/dining_philosophers/__JFREventChopstickPickUp
               3: dup
               4: dup
               5: invokespecial #43                 // Method com/tabjy/dining_philosophers/__JFREventChopstickPickUp."<init>":()V
               8: invokevirtual #46                 // Method com/tabjy/dining_philosophers/__JFREventChopstickPickUp.begin:()V
              11: astore        4
              13: aload_0
              14: getfield      #31                 // Field lock:Ljava/util/concurrent/locks/ReentrantLock;
              17: lload_2
              18: getstatic     #52                 // Field java/util/concurrent/TimeUnit.MILLISECONDS:Ljava/util/concurrent/TimeUnit;
              21: invokevirtual #56                 // Method java/util/concurrent/locks/ReentrantLock.tryLock:(JLjava/util/concurrent/TimeUnit;)Z
              24: ifne          34
              27: iconst_0
              28: aload         4
              30: invokevirtual #59                 // Method com/tabjy/dining_philosophers/__JFREventChopstickPickUp.commit:()V
              33: ireturn
              34: aload_0
              35: aload_1
              36: putfield      #61                 // Field pickedUpBy:Lcom/tabjy/dining_philosophers/Philosopher;
              39: iconst_1
              40: aload         4
              42: invokevirtual #59                 // Method com/tabjy/dining_philosophers/__JFREventChopstickPickUp.commit:()V
              45: ireturn
            StackMapTable: number_of_entries = 1
              frame_type = 255 /* full_frame */
                offset_delta = 34
                locals = [ top, top, top, top, class com/tabjy/dining_philosophers/__JFREventChopstickPickUp ]
                stack = []
            LineNumberTable:
              line 24: 13
              line 25: 27
              line 28: 34
              line 29: 39
            LocalVariableTable:
              Start  Length  Slot  Name   Signature
                 13      33     0  this   Lcom/tabjy/dining_philosophers/Chopstick;
                 13      33     1 philosopher   Lcom/tabjy/dining_philosophers/Philosopher;
                 13      33     2 timeout   J
          Exceptions:
            throws java.lang.InterruptedException
      

      This bug was discovered while I was coming up with a demo for the agent.

      The exact condition triggering this error is yet unclear. I'll keep update once I make new discovery. 

      Update: the agent generates faulty instrumentation if the original bytecode consists of a "same_frame" frame type.

      However, it happens only if original bytecode consists a compressed-frame in the stack map (ie. not a new frame).

      update:

      The issue is reproducible when the target function consists of multiple exit points, and a compressed stack map frame describing a jump target, followed by a function exit (ie. *return instructions). A simple example could be something like(, given javac writes a compressed frame instead of a new expanded frame):

      public int echo(int arg) {
          if (arg > 42) {
              return 42;
          }
          return arg;
      }
      

       
      This may be related to JMC-6532.

            kxu Kangcheng Xu
            kxu Kangcheng Xu
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: