精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

JDK的sql設(shè)計不合理導(dǎo)致的驅(qū)動類初始化死鎖問題

開發(fā) 開發(fā)工具
這篇文章是使用我們生產(chǎn)環(huán)境的一個系統(tǒng)的線程dump和內(nèi)存dump為基礎(chǔ)進行分析展開的。

[[181411]]

問題描述

當(dāng)我們一個系統(tǒng)既需要mysql驅(qū)動,也需要oracle驅(qū)動的時候,在并發(fā)加載初始化這些驅(qū)動類的過程中產(chǎn)生死鎖的可能性非常大,下面是一個模擬的例子,對于Thread2的實現(xiàn)其實是jdk里java.sql.DriverService的邏輯,也是我們第一次調(diào)用java.sql.DriverManager.registerDriver注冊一個驅(qū)動實例要走的邏輯(jdk1.6下),不過這篇文章是使用我們生產(chǎn)環(huán)境的一個系統(tǒng)的線程dump和內(nèi)存dump為基礎(chǔ)進行分析展開的。

如果以上代碼運行過程中發(fā)現(xiàn)有線程一直卡死在Class.forName的調(diào)用里,那么說明問題已經(jīng)重現(xiàn)了。

先上兩張圖

內(nèi)存態(tài)線程堆棧

線程堆棧

存疑點

仔細看看上面的線程dump分析和內(nèi)存dump分析里的線程分析模塊,您可能會有如下兩個疑惑:

  • 【為什么線程[Thread-0]一直卡在Class.forName的位置】:這有點出乎意料,做一個類加載要么找不到拋出ClassNotFoundException,要么找到直接返回,為什么會一直卡在這個位置呢?
  • 【明明[Thread-0]注冊的是mysql驅(qū)動為什么會去加載Odbc的驅(qū)動類】:通過[Thread-0]在棧上看倒數(shù)第二幀展開看到傳入Class.forName的參數(shù)是com.mysql.jdbc.Driver,然后展開棧上順序第二幀,看到傳入的參數(shù)是sun.jdbc.odbc.JdbcOdbcDriver,這意味著在對mysql驅(qū)動類做加載初始化的過程中又觸發(fā)了JdbcOdbc驅(qū)動類的加載

疑惑點解釋

疑惑二:

第一個疑惑我們先留著,先解釋下第二個疑惑,大家可以對照堆棧通過反編譯rt.jar還有ojdbc6-11.2.0.3.0.jar看具體的代碼

驅(qū)動類加載過程簡要介紹:

當(dāng)要注冊某個sql驅(qū)動的時候是通過調(diào)用java.sql.DriverManager.registerDriver來實現(xiàn)的(注意這個方法加了synchronized關(guān)鍵字,后面解釋第一個疑惑的時候是關(guān)鍵),而這個方法在第一次執(zhí)行過程中,會在當(dāng)前線程classloader的classpath下尋找所有/META-INF/services/java.sql.Driver文件,這個文件在mysql和oracle驅(qū)動jar里都有,里面寫的是對應(yīng)的驅(qū)動實現(xiàn)類名,這種機制是jdk提供的spi實現(xiàn),找到這些文件之后,依次使用Class.forName(driverClassName, true, this.loader)來對這些驅(qū)動類進行加載,其中第二個參數(shù)是true,意味著不僅僅做一次loadClass的動作,還會初始化該類,即調(diào)用包含靜態(tài)塊的< clinit >方法,執(zhí)行完之后才會返回,這樣就解釋了第二個疑惑,在mysql驅(qū)動注冊過程中還會對odbc驅(qū)動類進行加載并初始化

感想:

其實我覺得這種設(shè)計有點傻,為什么要干和自己不相關(guān)的事情呢,畫蛇添足的設(shè)計,首先類初始化的開銷是否放到一起做并沒有多大區(qū)別,其次正由于這種設(shè)計導(dǎo)致了今天這個死鎖的發(fā)生

疑惑一:

現(xiàn)在來說第一個疑惑,為什么會一直卡在Class.forName呢,到底卡在哪里,于是再通過jstack -m 命令將jvm里的堆棧也打印出來,如下所示

我們看到其實正在做類的初始化動作,并且線程正在調(diào)用ObjectSynchronizer::waitUninterruptibly一直沒返回,在看這方法的調(diào)用者instanceKlass1::initialize_impl,我們找到源碼位置如下:

類的初始化過程:

當(dāng)某個線程獲得機會對某個類進行初始化的時候(請看上面的Step 6),會設(shè)置這個類的init_state屬性為being_initialized(如果初始化好了會設(shè)置為fully_initialized,異常的話會設(shè)置為initialization_error),還會設(shè)置init_thread屬性為當(dāng)前線程,在這個設(shè)置過程中是有針對這個類提供了一把互斥鎖的,因此當(dāng)有別的線程進來的時候會被攔截在外面,如果設(shè)置完了,這把互斥鎖也釋放了,但是因為這個類的狀態(tài)被設(shè)置了,因此并發(fā)問題也得到了解決,當(dāng)另外一個線程也嘗試初始化這個類的時候會判斷這個類的狀態(tài)是不是being_initialized,并且其init_thread不是當(dāng)前線程,那么就會一直卡在那里,也就是此次線程dump的線程所處的狀態(tài),正在初始化類的線程會調(diào)用< clinit >方法,如果正常結(jié)束了,那么就設(shè)置其狀態(tài)為fully_initialized,并且通知之前卡在那里等待初始化完成的線程,然他們繼續(xù)往下走(下一個動作就是再判斷下狀態(tài),發(fā)現(xiàn)完成了就直接return了)

猜想:

在了解了上面的過程之后,于是我們猜測兩種可能

  • 第一,這個類的狀態(tài)還是being_intialized,還在while循環(huán)里沒有跳出來
  • 第二,事件通知機制出現(xiàn)了問題,也就是pthread_cond_wait和pthread_cond_signal之間的通信過程出現(xiàn)了問題。

不過第二種可能性非常小,比較linux久經(jīng)考驗了,那接下來我們驗證其實是第一個猜想

驗證:

我們通過GDB attach的方式連到了問題機器上(好在機器沒有掛),首先我們要找到具體的問題線程,我們通過上面的jstack -m命令看到了線程ID是5738,然后通過info threads找到對應(yīng)的線程,并得到它的序號14

然后通過thread 14切換到對應(yīng)的線程,并通過bt看到了如下的堆棧,正如我們想象的那樣,正在做類的初始化,一直卡在那里

我們通過f 6選擇第7幀,在通過disassemble反匯編該幀,也就是對instanceKlass::initialize_impl ()這個方法反匯編

從上面的注釋我們其實得出了,我們要看當(dāng)前類的初始化狀態(tài),那就是看eax寄存器偏移0xe0的位置的值,而eax其實就是ebp寄存器偏移0xfffffff4位置的值,于是我們通過如下地址內(nèi)存查到得到是4

而4其實代表的就是being_initialized這個狀態(tài),代碼如下

從這于是我們驗證了第一個猜想,其實是狀態(tài)一直沒有變更,因此一直卡在那里,為了更進一步確認這個問題,要是我們能找到該類的init_thread線程id就更清楚了,拿到這個ID我們就能看到這個線程棧,就知道它在干什么了,但是很遺憾,這個很難獲取到,至少我一直沒有找到辦法,因為線程ID在線程對象里一直沒有存,都是調(diào)用的os函數(shù)來獲取的,得換個思路。

突然發(fā)現(xiàn)instanceKlass.hpp代碼中得知兩個屬性原來是相鄰的(init_state和init_thread),于是斷定下一個地址的值就代表是這個線程對象了,但是其屬性何其多,找到想要的太不易了,最主要的是還擔(dān)心自己看的代碼和服務(wù)器上的jvm代碼不一致,這樣更蛋疼了,于是繼續(xù)查看Thread.hpp中的JavaThread類,找到個關(guān)鍵字0xDEAD-2=0xDEAB,這個有可能是volatile TerminatedTypes _terminated屬性的值,于是把線程對象打印出來,果然查到了關(guān)鍵字0xDEAB

因此順著這個屬性繼續(xù)往上找,找到了_thread_state表示線程狀態(tài)的值(向上偏移三個字),0x0000000a,即10,然后查看代碼知道原來線程是出于block狀態(tài)

JavaThreadState

這樣一來查看下線程dump,發(fā)現(xiàn)Thread-1正好處于BLOCKED狀態(tài),也就是說Thread-1就是那個正在對mysql驅(qū)動類做初始化的線程,這說明Thread-0和Thread-1成功互鎖了

于是我們展開Thread-1,看到- waiting to lock <0x71ae2ec0> (a java.lang.Class for java.sql.DriverManager),該線程正在等待java.sql.DriverManager類型鎖,而blocked在那里,而這個類型鎖是被Thread-0線程持有的,從Thread-1這個線程堆棧來看它其實也是在做Class.forName動作,并且通過Thread-1,展開第四幀我們可以看到其正在對加載

  1. sun.jdbc.odbc.JdbcOdbcDriver 

問題現(xiàn)場遐想:

于是我們大膽設(shè)想一個場景,Thread-1先獲取到初始化sun.jdbc.odbc.JdbcOdbcDriver的機會,然后在執(zhí)行sun.jdbc.odbc.JdbcOdbcDriver這個類的靜態(tài)塊的時候調(diào)用DriverManager.registerDriver(new Driver());,而該方法之前已經(jīng)提到了是會加同步鎖的,再想象一下,在這個這個靜態(tài)塊之前,并且設(shè)置了sun.jdbc.odbc.JdbcOdbcDriver類的初始化狀態(tài)為being_initialized之后,Thread-0這個線程執(zhí)行到了卡在的那個位置,并且我們從其堆棧可以看出它已經(jīng)持有了java.sql.DriverManager這個類型的鎖,因此這兩個線程陷入了互鎖狀態(tài)

【本文是51CTO專欄作者李嘉鵬的原創(chuàng)文章,轉(zhuǎn)載請通過微信公眾號(你假笨,id:lovestblog)聯(lián)系作者本人獲取授權(quán)】

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來源: 你假笨
相關(guān)推薦

2010-04-28 09:50:14

Oracle數(shù)據(jù)庫

2011-04-06 16:40:27

C++構(gòu)造函數(shù)

2013-01-14 09:29:04

2024-07-26 10:42:30

2011-05-10 10:38:54

布線光纖

2012-12-10 09:57:00

路由器交換機

2023-12-07 12:26:08

Java開發(fā)

2011-04-06 12:29:42

2012-05-23 12:46:53

JavaJava類

2023-10-31 09:29:03

Java配置

2011-08-17 12:25:11

2012-02-28 10:04:09

Java

2013-03-04 11:10:03

JavaJVM

2020-09-15 09:55:30

類比Python開發(fā)

2024-03-08 08:26:25

類的加載Class文件Java

2021-01-29 06:08:33

JDK15Java

2011-03-22 14:59:36

2010-02-03 11:01:18

C++類靜態(tài)成員初始化

2011-06-09 14:13:06

C++JAVA缺省初始化

2010-03-25 14:42:33

點贊
收藏

51CTO技術(shù)棧公眾號

日韩欧美激情视频| 欧美日韩一区二区三区69堂| 日韩一级免费毛片| 国产视频久久| 最近2019中文字幕大全第二页 | 激情伦成人综合小说| 亚洲 欧美 中文字幕| 小说区亚洲自拍另类图片专区| 亚洲韩国日本中文字幕| 色综合色综合色综合色综合| 金瓶狂野欧美性猛交xxxx | 蜜桃91精品入口| 91av国产精品| 欧美一级一区| 欧美大成色www永久网站婷| 亚洲av无码国产精品久久| yiren22亚洲综合| 五月天精品一区二区三区| 亚洲午夜精品福利| 三区在线观看| 丰满少妇久久久久久久| 国产日产欧美a一级在线| 日韩成人免费在线观看| 久久久久电影| 中文字幕日本精品| 一卡二卡三卡四卡| 国产精品超碰| 日韩女优av电影在线观看| 亚洲欧美另类动漫| 成人欧美magnet| 精品国产31久久久久久| 黄色片免费在线观看视频| 九色在线免费| 久久伊99综合婷婷久久伊| 国产成人精品福利一区二区三区 | 国产精品自拍毛片| 国产精品视频内| 中文字幕在线天堂| 国产一区二区你懂的| 欧美激情三级免费| 国产精品白嫩白嫩大学美女| 欧美电影一二区| 在线精品高清中文字幕| 久久精品无码一区| 精品在线手机视频| 日韩国产欧美精品在线| 偷偷色噜狠狠狠狠的777米奇| 亚洲精品午夜| 亚洲成人xxx| 亚洲一区二区在线免费| 国产精品极品在线观看| 欧美精品一区二区三区视频| 久久久久久久久久久影视| 国产精品国产三级在线观看| 91精品国产丝袜白色高跟鞋| 天堂av2020| www999久久| 欧美精品乱人伦久久久久久| 色噜噜狠狠一区二区| 激情欧美一区二区三区黑长吊| 在线欧美小视频| 青青在线视频免费| 日韩漫画puputoon| 欧美二区三区的天堂| 亚洲一区二区三区四区精品| 国产日韩一区二区三免费高清 | 日韩欧美亚洲系列| 久久精品在线免费观看| 亚洲精品二区| dy888亚洲精品一区二区三区| 亚洲欧美日韩国产另类专区| 4444在线观看| 成年人在线网站| 91国偷自产一区二区三区观看| 国产高清视频网站| 国产一区二区三区| 精品国产一区二区三区久久影院 | 亚洲性图第一页| 麻豆成人入口| 国产亚洲精品一区二555| 青青青视频在线免费观看| 国产精品传媒精东影业在线| 欧美美最猛性xxxxxx| 日韩成人高清视频| 美女一区二区久久| 成人片在线免费看| 户外极限露出调教在线视频| 中文字幕一区二区三区在线播放| 国产免费一区二区三区四在线播放| 欧美人体视频xxxxx| 一本大道综合伊人精品热热| 中文字幕22页| 日韩欧美在线精品| 久久综合网hezyo| 人人干人人干人人干| 日本亚洲一区二区| 都市激情久久久久久久久久久| 91免费欧美精品| 欧美交换国产一区内射| 一区二区三区高清视频在线观看| 国产精品video| www.av网站| 国产欧美日韩精品在线| 国产精品自拍合集| 日本中文字幕一区二区| 精品成人一区二区三区四区| 国产sm调教视频| 红桃视频亚洲| 国产主播欧美精品| 日本精品专区| 一区二区三区蜜桃| 国产福利影院在线观看| 成人h动漫精品一区二区器材| 伊人久久久久久久久久| 日本网站免费观看| 国产黄人亚洲片| 相泽南亚洲一区二区在线播放| 精品精品导航| 日韩一区二区中文字幕| 五月婷六月丁香| 亚洲欧美日韩国产一区二区| 99在线视频免费观看| 日韩专区在线| 91国内精品野花午夜精品| 日本一卡二卡在线| 欧美一区二区三区久久精品茉莉花 | 日韩电影在线一区| 97人摸人人澡人人人超一碰| aiai在线| 欧美专区亚洲专区| 国产全是老熟女太爽了| 欧美性色综合| 99免费在线观看视频| 黄av在线播放| 在线不卡中文字幕| 国产又粗又长免费视频| 久久av一区| 蜜桃导航-精品导航| av免费不卡国产观看| 精品少妇一区二区三区视频免付费| 久久久久久久麻豆| 国内久久婷婷综合| gogogo免费高清日本写真| 日韩一级免费视频| 欧一区二区三区| 日韩精品中文字幕久久臀| 国产精久久久久久| 成人激情小说网站| 日本a视频在线观看| xvideos.蜜桃一区二区| 久久免费视频在线| 亚洲男人第一天堂| 亚洲国产色一区| 亚洲精品乱码久久久久久蜜桃图片| 欧美久久视频| 国产美女精品久久久| 欧美aaa免费| 精品91自产拍在线观看一区| 国产精品999久久久| 成人黄色大片在线观看| 国产青青在线视频| 免费成人av| 国产精品一区二区久久| 免费a级毛片在线播放| 欧美日韩视频第一区| 日韩免费av一区| 狠狠久久亚洲欧美| 国产91在线亚洲| 免费福利视频一区| 国产97人人超碰caoprom| av国产在线观看| 91精品黄色片免费大全| 黄色一级视频免费| 91啪九色porn原创视频在线观看| 超碰网在线观看| 91综合视频| 国产精品青青草| 成人性生交大片免费网站| 中文字幕无线精品亚洲乱码一区| 国产精品毛片一区视频播| 夜夜嗨av一区二区三区四季av| 国产成人精品无码片区在线| 日韩和欧美的一区| 三上悠亚免费在线观看| 久久免费视频66| 国产精品成人v| 亚洲av无码国产精品久久| 中文字幕高清在线播放| 夜夜嗨av一区二区三区四区| 96亚洲精品久久久蜜桃| 亚洲成a人在线观看| 香蕉网在线播放| 紧缚奴在线一区二区三区| 免费在线观看视频a| 欧美一级精品片在线看| 99一区二区三区| 不卡亚洲精品| 午夜精品久久久久久久久久久久久| 理论视频在线| 日韩女优电影在线观看| 五月激情丁香网| 亚洲一卡二卡三卡四卡无卡久久| 成人免费网站黄| 国产成人免费网站| 男人搞女人网站| 极品av少妇一区二区| 日产国产精品精品a∨| 日韩在线精品强乱中文字幕| 国产精品成人免费电影| 久草在线视频网站| 最新中文字幕亚洲| 日韩av视屏| 精品毛片乱码1区2区3区| 久久国产乱子伦精品| 亚洲电影在线免费观看| 男的操女的网站| 中文字幕二三区不卡| 女同性恋一区二区三区| 国产成人日日夜夜| 999久久久精品视频| 日韩主播视频在线| 久在线观看视频| 欧美日韩国产精品一区二区亚洲| 亚洲欧美日韩精品在线| 天堂一区二区三区四区| 超碰97在线人人| 蜜桃在线一区| 91免费电影网站| 日韩亚洲国产免费| 国产精品久久久久久久久久小说 | 成人高h视频在线| 另类专区亚洲| 人体精品一二三区| 九色porny丨首页入口在线| 欧美黄色片视频| 亚洲制服国产| 久久夜色精品国产| 日本精品在线| 日韩午夜在线视频| 在线观看a视频| 少妇精69xxtheporn| 高清在线观看av| 亚洲图片制服诱惑| 国外av在线| 国产亚洲成精品久久| 玖玖综合伊人| 亚洲区一区二区| 亚洲成人福利视频| 米奇精品关键词| 国产精品一区二区不卡视频| 亚洲视频一起| 国产精品日韩一区二区免费视频| 91蜜桃臀久久一区二区| 成人午夜电影在线播放| 国产成人在线中文字幕| 国产伦精品一区二区三区免 | 欧美成人一级视频| 日本高清视频在线| 亚洲精品日韩欧美| 二区在线视频| 日韩中文字幕视频在线| 国产美女福利在线| 欧美国产亚洲视频| 理论片午夜视频在线观看| 欧美诱惑福利视频| 国精产品一区二区三区有限公司| 国产精品久在线观看| 亚洲欧美专区| 成人欧美一区二区三区视频| 欧美黑人巨大videos精品| 欧美日韩一区二区视频在线| 视频在线不卡免费观看| 91免费版看片| 一区二区三区精品视频在线观看| 国产91对白刺激露脸在线观看| 日韩高清不卡一区| 国产亚洲色婷婷久久| 91一区二区三区在线观看| 极品人妻videosss人妻| 亚洲三级电影网站| 日本三级黄色大片| 欧美伊人久久久久久久久影院 | 日本一本高清视频| 在线中文字幕一区| av无码精品一区二区三区宅噜噜| 精品国产91亚洲一区二区三区婷婷| 巨骚激情综合| 欧美插天视频在线播放| 中文字幕在线官网| 91免费福利视频| 少妇精品久久久一区二区三区 | 亚洲一区区二区| 国产无遮挡猛进猛出免费软件 | 欧美成人一区二区在线| 93在线视频精品免费观看| 亚洲精品无码国产| 免费成人在线视频观看| 成年女人免费视频| 国产精品国产三级国产普通话99| 日本三级网站在线观看| 欧美日韩视频专区在线播放| 日本xxxxxwwwww| 久久影院模特热| 欧美大片高清| av在线亚洲男人的天堂| 成人高清av| 亚洲人成网站色在线观看| 真实乱视频国产免费观看| 亚洲欧美日韩在线| 国产情侣免费视频| 亚洲国产另类久久精品| 成人av福利| 国产精品国产三级国产aⅴ9色| 中文无码日韩欧| 三年中文高清在线观看第6集| 亚洲欧美大片| 亚洲av无码一区二区三区网址| 亚洲精选一二三| 怡红院成永久免费人全部视频| 亚洲精品国产精品自产a区红杏吧 亚洲精品国产精品乱码不99按摩 亚洲精品国产精品久久清纯直播 亚洲精品国产精品国自产在线 | 在线观看亚洲一区| 高清毛片aaaaaaaaa片| 日韩在线观看你懂的| 日韩精品99| 精品在线观看一区二区| 九七久久人人| 在线观看视频91| 色吊丝在线永久观看最新版本| 久久99视频免费| 国产精品18| 中文字幕欧美日韩一区二区三区 | 想看黄色一级片| 国产精品久久久久久久久图文区 | 一区二区三区观看| 日韩在线a电影| 加勒比综合在线| 色呦呦国产精品| 国产人成在线视频| 日本中文字幕不卡免费| 亚洲小说图片| 国产视频一区二区视频| 久久久久久久一区| www.com亚洲| 一本色道久久88精品综合| 亚洲综合在线电影| 视频一区二区精品| 美女久久久精品| 手机看片国产日韩| 欧美日韩在线播放一区| 在线观看a视频| 成人免费激情视频| 午夜亚洲福利| 一二三区视频在线观看| 亚洲国产精品久久久男人的天堂 | 波多野结衣一二区| 伊人伊成久久人综合网站| 成人国产精选| 午夜啪啪免费视频| 国产精品99久久久久| 久久久99精品| 亚洲精品大尺度| 日韩天堂在线| 国产高清免费在线| 国产盗摄一区二区三区| 久久久精品国产sm调教| 日韩精品极品毛片系列视频| 波多野结衣久久精品| 日韩在线观看电影完整版高清免费| 喷白浆一区二区| 天天天天天天天天操| 精品久久99ma| 桃色一区二区| 懂色av一区二区三区四区五区| 国产盗摄女厕一区二区三区| 国产视频91在线| 国产亚洲一级高清| 免费观看性欧美大片无片| 欧美日韩成人免费视频| 欧美国产一区二区在线观看| 国内精品久久久久久久久久久 | 欧美男男gaygay1069| 黄色一级片av| 91视频免费观看| 一区二区的视频| 97免费中文视频在线观看| 国产欧美一区二区三区精品观看 | 136福利精品导航| 97xxxxx| 亚洲日本中文字幕区| 天堂网www中文在线| 成人国产精品久久久| 国产精品视区| 国精品无码一区二区三区| 亚洲精品videossex少妇| 久久精品国产福利| 国产av天堂无码一区二区三区| 国产女主播视频一区二区| 成人毛片在线免费观看| 国产精品久久久久999| 禁久久精品乱码|