openjdk11 jvm视角查看java线程异常退出synchronized锁自动释放

##synchronized锁异常 java代码demo

public class ThreadTest {

    public int mul = 1;

    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        Thread yym_user_thread1 = new Thread() {
            public void run() {
                System.out.println("yym_user_thread1");
                threadTest.resources(0);
            }
        };
        yym_user_thread1.setName("yym_user_thread1");
        yym_user_thread1.start();
        //
        //
        Thread.yield();Thread.yield();Thread.yield();
        Thread.yield();Thread.yield();Thread.yield();
        Thread yym_user_thread2 = new Thread() {
            public void run() {
                System.out.println("yym_user_thread2");
                threadTest.resources(1);
            }
        };
        yym_user_thread2.setName("yym_user_thread2");
        yym_user_thread2.start();
    }

    public  void resources(int number) {
        synchronized(this) {
            for (int i = 0; i < 10000; i++) {
                mul++;
            }
            int result = mul / number;
            System.out.println("resources" + result);
        }
    }

}

##javap -v ThreadTest 查看monitorenter monitorexit字节码

major version: 55
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #3                          // ThreadTest
  super_class: #17                        // java/lang/Object
  interfaces: 0, fields: 1, methods: 3, attributes: 4
{0x0000000705f0f9a0}Constant pool:
{0x0000000705f2dd10}   #1 = Methodref          #17.#34        // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#35         // ThreadTest.mul:I
{0x0000000705fc52e0}   #3 = Class              #36            // ThreadTest
   #4 = Methodref          #3.#34         // ThreadTest."<init>":()V
   #5 = Class              #37            // ThreadTest$1
   #6 = Methodref          #5.#38         // ThreadTest$1."<init>":(LThreadTest;)V
   #7 = String             #39            // yym_user_thread1
   #8 = Methodref          #40.#41        // java/lang/Thread.setName:(Ljava/lang/String;)V
   #9 = Methodref          #40.#42        // java/lang/Thread.start:()V
  #10 = Methodref          #40.#43        // java/lang/Thread.yield:()V
  #11 = Class              #44            // ThreadTest$2
  #12 = Methodref          #11.#38        // ThreadTest$2."<init>":(LThreadTest;)V
  #13 = String             #45            // yym_user_thread2
  #14 = Fieldref           #46.#47        // java/lang/System.out:Ljava/io/PrintStream;
{0x000000070610aa38}{0x0000000706114b80}{0x000000070613dfd0}  #15 = InvokeDynamic      #0:#51         // #0:makeConcatWithConstants:(I)Ljava/lang/String;
  #16 = Methodref          #52.#53        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #17 = Class              #54            // java/lang/Object
  #18 = Utf8               InnerClasses
  #19 = Utf8               mul
  #20 = Utf8               I
  #21 = Utf8               <init>
  #22 = Utf8               ()V
  #23 = Utf8               Code
  #24 = Utf8               LineNumberTable
  #25 = Utf8               main
  #26 = Utf8               ([Ljava/lang/String;)V
  #27 = Utf8               resources
  #28 = Utf8               (I)V
  #29 = Utf8               StackMapTable
  #30 = Class              #55            // java/lang/Throwable
  #31 = Utf8               SourceFile
  #32 = Utf8               ThreadTest.java
  #33 = Utf8               NestMembers
  #34 = NameAndType        #21:#22        // "<init>":()V
  #35 = NameAndType        #19:#20        // mul:I
  #36 = Utf8               ThreadTest
  #37 = Utf8               ThreadTest$1
  #38 = NameAndType        #21:#56        // "<init>":(LThreadTest;)V
  #39 = Utf8               yym_user_thread1
  #40 = Class              #57            // java/lang/Thread
  #41 = NameAndType        #58:#59        // setName:(Ljava/lang/String;)V
  #42 = NameAndType        #60:#22        // start:()V
  #43 = NameAndType        #61:#22        // yield:()V
  #44 = Utf8               ThreadTest$2
  #45 = Utf8               yym_user_thread2
  #46 = Class              #62            // java/lang/System
  #47 = NameAndType        #63:#64        // out:Ljava/io/PrintStream;
  #48 = Utf8               BootstrapMethods
{0x0000000706184b20}  #49 = MethodHandle       6:#65          // REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #50 = String             #66            // resources\u0001
  #51 = NameAndType        #67:#68        // makeConcatWithConstants:(I)Ljava/lang/String;
  #52 = Class              #69            // java/io/PrintStream
  #53 = NameAndType        #70:#59        // println:(Ljava/lang/String;)V
  #54 = Utf8               java/lang/Object
  #55 = Utf8               java/lang/Throwable
  #56 = Utf8               (LThreadTest;)V
  #57 = Utf8               java/lang/Thread
  #58 = Utf8               setName
  #59 = Utf8               (Ljava/lang/String;)V
  #60 = Utf8               start
  #61 = Utf8               yield
  #62 = Utf8               java/lang/System
  #63 = Utf8               out
  #64 = Utf8               Ljava/io/PrintStream;
  #65 = Methodref          #71.#72        // java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #66 = Utf8               resources\u0001
  #67 = Utf8               makeConcatWithConstants
  #68 = Utf8               (I)Ljava/lang/String;
  #69 = Utf8               java/io/PrintStream
  #70 = Utf8               println
  #71 = Class              #73            // java/lang/invoke/StringConcatFactory
  #72 = NameAndType        #67:#76        // makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #73 = Utf8               java/lang/invoke/StringConcatFactory
  #74 = Class              #78            // java/lang/invoke/MethodHandles$Lookup
  #75 = Utf8               Lookup
  #76 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #77 = Class              #79            // java/lang/invoke/MethodHandles
  #78 = Utf8               java/lang/invoke/MethodHandles$Lookup
  #79 = Utf8               java/lang/invoke/MethodHandles
{
  public int mul;
{0x00000007061ad120}    descriptor: I
    flags: (0x0001) ACC_PUBLIC

  public ThreadTest();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
{0x00000007061d5a80}{0x000000070601ee30}      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_1
         6: putfield      #2                  // Field mul:I
         9: return
      LineNumberTable:
        line 1: 0
        line 3: 4

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=4, args_size=1
         0: new           #3                  // class ThreadTest
         3: dup
         4: invokespecial #4                  // Method "<init>":()V
         7: astore_1
         8: new           #5                  // class ThreadTest$1
        11: dup
        12: aload_1
        13: invokespecial #6                  // Method ThreadTest$1."<init>":(LThreadTest;)V
        16: astore_2
        17: aload_2
        18: ldc           #7                  // String yym_user_thread1
        20: invokevirtual #8                  // Method java/lang/Thread.setName:(Ljava/lang/String;)V
        23: aload_2
        24: invokevirtual #9                  // Method java/lang/Thread.start:()V
        27: invokestatic  #10                 // Method java/lang/Thread.yield:()V
        30: invokestatic  #10                 // Method java/lang/Thread.yield:()V
        33: invokestatic  #10                 // Method java/lang/Thread.yield:()V
        36: invokestatic  #10                 // Method java/lang/Thread.yield:()V
        39: invokestatic  #10                 // Method java/lang/Thread.yield:()V
        42: invokestatic  #10                 // Method java/lang/Thread.yield:()V
        45: new           #11                 // class ThreadTest$2
        48: dup
        49: aload_1
        50: invokespecial #12                 // Method ThreadTest$2."<init>":(LThreadTest;)V
        53: astore_3
        54: aload_3
        55: ldc           #13                 // String yym_user_thread2
        57: invokevirtual #8                  // Method java/lang/Thread.setName:(Ljava/lang/String;)V
        60: aload_3
        61: invokevirtual #9                  // Method java/lang/Thread.start:()V
        64: return
      LineNumberTable:
        line 6: 0
        line 7: 8
        line 13: 17
        line 14: 23
        line 17: 27
        line 18: 36
        line 19: 45
        line 25: 54
        line 26: 60
        line 27: 64

  public void resources(int);
    descriptor: (I)V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=3, locals=5, args_size=2
         0: aload_0
         1: dup
         2: astore_2
         3: monitorenter
         4: iconst_0
         5: istore_3
         6: iload_3
         7: sipush        10000
        10: if_icmpge     29
        13: aload_0
        14: dup
        15: getfield      #2                  // Field mul:I
        18: iconst_1
        19: iadd
        20: putfield      #2                  // Field mul:I
        23: iinc          3, 1
        26: goto          6
        29: aload_0
        30: getfield      #2                  // Field mul:I
        33: iload_1
        34: idiv
        35: istore_3
        36: getstatic     #14                 // Field java/lang/System.out:Ljava/io/PrintStream;
        39: iload_3
        40: invokedynamic #15,  0             // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
        45: invokevirtual #16                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        48: aload_2
        49: monitorexit
        50: goto          60
        53: astore        4
        55: aload_2
        56: monitorexit
        57: aload         4
        59: athrow
        60: return
      Exception table:
         from    to  target type
             4    50    53   any
            53    57    53   any
      LineNumberTable:
        line 30: 0
        line 31: 4
        line 32: 13
        line 31: 23
        line 34: 29
        line 35: 36
        line 36: 48
        line 37: 60
      StackMapTable: number_of_entries = 4
        frame_type = 253 /* append */
          offset_delta = 6
          locals = [ class java/lang/Object, int ]
        frame_type = 250 /* chop */
          offset_delta = 22
        frame_type = 87 /* same_locals_1_stack_item */
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 6
}
SourceFile: "ThreadTest.java"
NestMembers:
  ThreadTest$2
  ThreadTest$1
InnerClasses:
  #11;                                    // class ThreadTest$2
  #5;                                     // class ThreadTest$1
  public static final #75= #74 of #77;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
  0: #49 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #50 resources\u0001

##gdb线程栈  异常处理

(gdb) c
Continuing.
@@@@-yym-Thread PID: 4160
@@@@-yym-Thread NAME: yym_user_thread2
yym_user_thread2
[Switching to Thread 0x7fffc9d6c700 (LWP 4157)]

Thread 18 "C2 CompilerThre" hit Breakpoint 4, JavaThread::exit (this=0x7fffa4220800, destroy_vm=false, exit_type=JavaThread::normal_exit)
    at /home/yym/code/jdk11u-master/src/hotspot/share/runtime/thread.cpp:1917
1917      this->clear_pending_exception();
(gdb) c
Continuing.
[Switching to Thread 0x7fffc9b6a700 (LWP 4159)]

Thread 20 "yym_user_thread" hit Breakpoint 4, JavaThread::exit (this=0x7ffff07bd800, destroy_vm=false, exit_type=JavaThread::normal_exit)
    at /home/yym/code/jdk11u-master/src/hotspot/share/runtime/thread.cpp:1917
1917      this->clear_pending_exception();
(gdb) s
ThreadShadow::clear_pending_exception (this=0x7ffff07bd800) at /home/yym/code/jdk11u-master/src/hotspot/share/utilities/exceptions.cpp:59
59      void ThreadShadow::clear_pending_exception() {
(gdb) list
54        _pending_exception = exception;
55        _exception_file    = file;
56        _exception_line    = line;
57      }
58
59      void ThreadShadow::clear_pending_exception() {
60        LogTarget(Debug, exceptions) lt;
61        if (_pending_exception != NULL && lt.is_enabled()) {
62          ResourceMark rm;
63          LogStream ls(lt);
(gdb) n
60        LogTarget(Debug, exceptions) lt;
(gdb) p exception
No symbol "exception" in current context.
(gdb) n
61        if (_pending_exception != NULL && lt.is_enabled()) {

 ##抛出异常

##方法退出

 ##gdb调试

(gdb) b thread.cpp:1917

(gdb) p *_pending_exception
$8 = {_mark = 0x7ffff07bd805, _metadata = {_klass = 0xe294f72300014610, _compressed_klass = 83472}}
(gdb) call _pending_exception->print_on(tty)
java.lang.ArithmeticException
{0x0000000714a7b8f0} - klass: 'java/lang/ArithmeticException'
 - ---- fields (total size 5 words):
 - private transient 'backtrace' 'Ljava/lang/Object;' @12  a 'java/lang/Object'[5] {0x0000000714a7b918} (e294f723)
 - private 'detailMessage' 'Ljava/lang/String;' @16  "/ by zero"{0x0000000714a7b8b8} (e294f717)
 - private 'cause' 'Ljava/lang/Throwable;' @20  a 'java/lang/ArithmeticException'{0x0000000714a7b8f0} (e294f71e)
 - private 'stackTrace' '[Ljava/lang/StackTraceElement;' @24  a 'java/lang/StackTraceElement'[0] {0x0000000715120a70} (e2a2414e)
 - private strict 'suppressedExceptions' 'Ljava/util/List;' @28  a 'java/util/Collections$EmptyList'{0x000000071510bb90} (e2a21772)
 - private transient 'depth' 'I' @32  2
(gdb) bt
#0  ThreadShadow::clear_pending_exception (this=0x7ffff07bd800) at /home/yym/code/jdk11u-master/src/hotspot/share/utilities/exceptions.cpp:61
#1  0x00007ffff6173b7c in JavaThread::exit (this=0x7ffff07bd800, destroy_vm=false, exit_type=JavaThread::normal_exit)
    at /home/yym/code/jdk11u-master/src/hotspot/share/runtime/thread.cpp:1917
#2  0x00007ffff61738ef in JavaThread::thread_main_inner (this=0x7ffff07bd800) at /home/yym/code/jdk11u-master/src/hotspot/share/runtime/thread.cpp:1875
#3  0x00007ffff617374a in JavaThread::run (this=0x7ffff07bd800) at /home/yym/code/jdk11u-master/src/hotspot/share/runtime/thread.cpp:1850
#4  0x00007ffff616f8eb in Thread::call_run (this=0x7ffff07bd800) at /home/yym/code/jdk11u-master/src/hotspot/share/runtime/thread.cpp:387
#5  0x00007ffff5f703fd in thread_native_entry (thread=0x7ffff07bd800) at /home/yym/code/jdk11u-master/src/hotspot/os/linux/os_linux.cpp:827
#6  0x00007ffff71c56ba in start_thread (arg=0x7fffc9b6a700) at pthread_create.c:333
#7  0x00007ffff790051d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb)

##yym_user_thread1释放锁

(gdb) set args ThreadTest
(gdb) handle SIGSEGV pass noprint nostop
Signal        Stop      Print   Pass to program Description
SIGSEGV       No        No      Yes             Segmentation fault
(gdb) handle SIGFPE pass noprint nostop
Signal        Stop      Print   Pass to program Description
SIGFPE        No        No      Yes             Arithmetic exception
(gdb) b thread.cpp:1917
(gdb) b ObjectMonitor::exit
(gdb)b ObjectMonitor::ExitEpilog

InterpreterRuntime::monitorexit (thread=0x7ffff06c6800, elem=0x7fffc9b695d8) at /home/yym/code/jdk11u-master/src/hotspot/share/interpreter/interpreterRuntime.cpp:801
801       elem->set_obj(NULL);
(gdb) n
803       thread->last_frame().interpreter_frame_verify_monitor(elem);
(gdb) n
788     IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorexit(JavaThread* thread, BasicObjectLock* elem))
(gdb) p thread->print_on(tty)
"yym_user_thread1" #12 prio=5 os_prio=0 cpu=1.74ms elapsed=132.10s tid=0x00007ffff06c6800 nid=0x2163 runnable  [0x00007fffc9b69000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_in_vm
Thread: 0x00007ffff06c6800  [0x2163] State: _call_back _has_called_back 0 _at_poll_safepoint 0
   JavaThread state: _thread_in_vm
$7 = void
(gdb)

##唤醒其他线程

(gdb) n
[Switching to Thread 0x7fffc9b6a700 (LWP 9733)]

Thread 20 "yym_user_thread" hit Breakpoint 4, ObjectMonitor::ExitEpilog (this=0x7fffb0008b80, Self=0x7ffff072f000, Wakee=0x7fffc9a68600)
    at /home/yym/code/jdk11u-master/src/hotspot/share/runtime/objectMonitor.cpp:1283
1283      assert(_owner == Self, "invariant");
(gdb) n
1291      _succ = Knob_SuccEnabled ? Wakee->_thread : NULL;
(gdb) n
1292      ParkEvent * Trigger = Wakee->_event;

##main释放锁-等待日后验证,现阶段不知道干啥的

(gdb) b thread.cpp:2040

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值