亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

深入拆解ThreadLocal:線程隔離、弱引用、內(nèi)存泄漏與OOM排查

深入拆解ThreadLocal:線程隔離、弱引用、內(nèi)存泄漏與OOM排查 并發(fā)編程系列寫到這一篇前面的內(nèi)容基本都在圍繞一個(gè)詞打轉(zhuǎn)共享。鎖、原子類、并發(fā)容器本質(zhì)上都是想讓多個(gè)線程更安全、更高效地協(xié)作同一份數(shù)據(jù)。而ThreadLocal的思路是反著來(lái)的——既然共享這么容易出問(wèn)題那干脆每個(gè)線程各存一份誰(shuí)也別碰誰(shuí)的。這個(gè)思路聽(tīng)著簡(jiǎn)單但背后牽扯到弱引用、內(nèi)存泄漏、線程池上下文傳遞一系列坑值得用一整篇來(lái)拆。ThreadLocal解決的是線程隔離問(wèn)題不是并發(fā)原子性問(wèn)題搞清楚這一點(diǎn)后面所有原理和實(shí)戰(zhàn)姿勢(shì)才立得住。這一篇我打算從最經(jīng)典的SimpleDateFormat翻車現(xiàn)場(chǎng)切入先讓你明白ThreadLocal到底解決了什么問(wèn)題然后進(jìn)源碼拆一遍set/get/remove的完整鏈路重點(diǎn)講ThreadLocalMap的哈希設(shè)計(jì)和弱引用機(jī)制接著把內(nèi)存泄漏的形成鏈路徹底還原說(shuō)清楚為什么線程池是重災(zāi)區(qū)再給出實(shí)戰(zhàn)層面的使用規(guī)范包括remove的幾種姿勢(shì)和上下文封裝思路最后記錄一次線上OOM排查實(shí)錄手把手走一遍jmap加MAT的定位流程。適合剛學(xué)并發(fā)編程的同學(xué)建立正確認(rèn)知也適合被ThreadLocal泄漏或臟數(shù)據(jù)坑過(guò)的人對(duì)照著排查。1. 從SimpleDateFormat翻車現(xiàn)場(chǎng)切入ThreadLocal到底解決了什么問(wèn)題1.1 SimpleDateFormat在多線程下的崩潰如果你在Java后端寫過(guò)日期格式化大概率見(jiàn)過(guò)這個(gè)經(jīng)典事故一個(gè)SimpleDateFormat實(shí)例被多個(gè)線程同時(shí)調(diào)用parse()或format()結(jié)果日期串錯(cuò)位、數(shù)字亂掉甚至直接拋NumberFormatException。private static final SimpleDateFormat SDF new SimpleDateFormat(yyyy-MM-dd HH:mm:ss); public String formatDate(Date date) { return SDF.format(date); // 并發(fā)調(diào)用時(shí)偶發(fā)錯(cuò)亂 }根因不復(fù)雜SimpleDateFormat內(nèi)部維護(hù)了一個(gè)Calendar對(duì)象format()和parse()過(guò)程中要反復(fù)讀寫這個(gè)共享的Calendar。多個(gè)線程同時(shí)操作同一份可變狀態(tài)又沒(méi)有同步數(shù)據(jù)被互相覆蓋自然就亂了。你單獨(dú)跑單測(cè)永遠(yuǎn)復(fù)現(xiàn)不出來(lái)一壓測(cè)就現(xiàn)原形。1.2 加鎖、每次新建和ThreadLocal三條路的取舍解決這個(gè)線程安全問(wèn)題通常有三條路。第一條是給format()加synchronized或使用ReentrantLock。這能保證正確性但等于把并發(fā)的日期格式化全部串行化。想象一個(gè)支付系統(tǒng)每秒鐘幾千筆訂單都要格式化時(shí)間所有請(qǐng)求擠在同一把鎖上性能損耗肉眼可見(jiàn)。第二條是每次調(diào)用都new SimpleDateFormat()。這條路避免了共享可變狀態(tài)但頻繁創(chuàng)建對(duì)象會(huì)增加GC壓力。雖然JIT的逃逸分析在部分場(chǎng)景能把對(duì)象優(yōu)化到棧上但依賴編譯器優(yōu)化本身不可靠尤其在對(duì)象構(gòu)造較重、調(diào)用頻繁時(shí)效果并不穩(wěn)定。第三條就是用ThreadLocal給每個(gè)線程緩存一個(gè)SimpleDateFormat實(shí)例private static final ThreadLocalSimpleDateFormat DATE_FORMAT ThreadLocal.withInitial(() - new SimpleDateFormat(yyyy-MM-dd HH:mm:ss)); public String formatDate(Date date) { return DATE_FORMAT.get().format(date); }每個(gè)線程第一次get()時(shí)通過(guò)withInitial創(chuàng)建自己的實(shí)例之后一直復(fù)用。線程之間互不干擾不需要加鎖也不存在頻繁創(chuàng)建對(duì)象的開銷。這也直接點(diǎn)出了ThreadLocal的核心定位給每個(gè)線程一份獨(dú)立的私有副本把共享問(wèn)題轉(zhuǎn)化成隔離問(wèn)題。方案是否線程安全并發(fā)度對(duì)象創(chuàng)建開銷代碼侵入synchronized加鎖安全低串行無(wú)額外對(duì)象低每次new實(shí)例安全高高依賴GC兜底低ThreadLocal緩存安全高每個(gè)線程僅一次中需注意清理1.3 ThreadLocal解決的是線程隔離不是并發(fā)修改不少初學(xué)者把ThreadLocal當(dāng)成線程安全的Map來(lái)用這是個(gè)危險(xiǎn)的誤解。ThreadLocal并不保證你對(duì)某個(gè)對(duì)象內(nèi)部狀態(tài)的修改是原子的它只是讓每個(gè)線程看到不同的對(duì)象實(shí)例。你往ThreadLocal里放一個(gè)共享的ArrayList再讓100個(gè)線程同時(shí)往這個(gè)List里add那該出事還是出事因?yàn)長(zhǎng)ist本身還是同一個(gè)。所以在實(shí)踐中ThreadLocal的典型場(chǎng)景是那種每個(gè)線程天然該有一份但又不方便作為參數(shù)層層傳遞的東西事務(wù)連接、用戶登錄上下文、traceId、請(qǐng)求級(jí)別的緩存、框架層面的上下文對(duì)象。Spring的RequestContextHolder、MyBatis的SqlSessionTemplate在底層都用ThreadLocal綁定當(dāng)前線程的資源。理解這點(diǎn)你才不會(huì)被后續(xù)的內(nèi)存泄漏問(wèn)題帶偏思路——它存儲(chǔ)的本質(zhì)是線程級(jí)上下文而不是并發(fā)安全容器。2. ThreadLocal的源碼級(jí)拆解線程本地變量是怎么存進(jìn)去、取出來(lái)的2.1 每個(gè)線程都自帶了兩個(gè)Map字段很多人以為ThreadLocal是把數(shù)據(jù)存在ThreadLocal對(duì)象里這是錯(cuò)的。真正存儲(chǔ)數(shù)據(jù)的地方是Thread類內(nèi)部的兩個(gè)字段threadLocals和inheritableThreadLocals??碕DK源碼里Thread.java的字段定義一目了然ThreadLocal.ThreadLocalMap threadLocals null; ThreadLocal.ThreadLocalMap inheritableThreadLocals null;每個(gè)線程對(duì)象自帶一個(gè)ThreadLocalMap。當(dāng)你調(diào)用ThreadLocal.set(value)的時(shí)候本質(zhì)是把當(dāng)前線程的threadLocals這個(gè)Map取出來(lái)往里面塞了一條記錄key是ThreadLocal對(duì)象自身value是你傳入的數(shù)據(jù)。不同ThreadLocal實(shí)例就是同一個(gè)線程Map里不同的key。所以線程隔離的準(zhǔn)確含義是數(shù)據(jù)分散存儲(chǔ)在各個(gè)線程自己的Map里而不是存在ThreadLocal對(duì)象上。inheritableThreadLocals則是給子線程用的后面講子線程傳遞時(shí)再細(xì)說(shuō)。這里先記住getMap(t)方法本身沒(méi)做什么高深的事它就是返回t.threadLocals這個(gè)字段。很多人在看源碼時(shí)卡在這個(gè)方法上其實(shí)它就是個(gè)訪問(wèn)器熱詞里那句threadlocal getmap指的就是這一步。ThreadLocalMap getMap(Thread t) { return t.threadLocals; }2.2 set、get、remove的完整調(diào)用鏈先看set()在JDK 8里的實(shí)現(xiàn)public void set(T value) { Thread t Thread.currentThread(); ThreadLocalMap map getMap(t); if (map ! null) map.set(this, value); else createMap(t, value); }流程很直白拿到當(dāng)前線程取出它的threadLocals如果Map已經(jīng)存在就直接往里放不存在就創(chuàng)建一個(gè)新Map并塞入第一條記錄。createMap內(nèi)部會(huì)new一個(gè)初始容量16的ThreadLocalMap并把當(dāng)前ThreadLocal和value作為第一個(gè)Entry放進(jìn)去。再看get()public T get() { Thread t Thread.currentThread(); ThreadLocalMap map getMap(t); if (map ! null) { ThreadLocalMap.Entry e map.getEntry(this); if (e ! null) return (T)e.value; } return setInitialValue(); }線程的Map存在并且能找到以當(dāng)前ThreadLocal為key的Entry就返回里面的value找不到就調(diào)用setInitialValue()——它會(huì)執(zhí)行initialValue()方法默認(rèn)返回nullwithInitial就是重寫這個(gè)方法把初始值塞進(jìn)Map再返回。remove()更直接public void remove() { ThreadLocalMap m getMap(Thread.currentThread()); if (m ! null) m.remove(this); }看到這里你應(yīng)該已經(jīng)發(fā)現(xiàn)一個(gè)關(guān)鍵點(diǎn)ThreadLocal的線程隔離能力完全建立在每個(gè)Thread對(duì)象內(nèi)部的Map之上。這意味著只要線程還活著它Map里所有的value都不會(huì)被自動(dòng)釋放。這條結(jié)論是理解內(nèi)存泄漏的起點(diǎn)。2.3 哈希散列為什么ThreadLocal敢用線性探測(cè)硬扛沖突ThreadLocalMap底層是個(gè)Entry數(shù)組初始容量16負(fù)載因子是2/3。每個(gè)ThreadLocal實(shí)例在創(chuàng)建時(shí)都會(huì)通過(guò)一個(gè)全局的AtomicInteger累加得到一個(gè)threadLocalHashCode增量是那個(gè)著名的魔數(shù)0x61c88647源碼里叫HASH_INCREMENT。private final int threadLocalHashCode nextHashCode(); private static int nextHashCode() { return nextHashCode.getAndAdd(HASH_INCREMENT); }為什么要定這個(gè)增量它和黃金分割比例有關(guān)對(duì)應(yīng)的是斐波那契散列。簡(jiǎn)單說(shuō)0x61c88647能保證ThreadLocal的哈希值在數(shù)組長(zhǎng)度是2的冪時(shí)均勻地散布在槽位上最大程度避免多個(gè)ThreadLocal擠在同一條探測(cè)序列上。你不需要深挖數(shù)學(xué)推導(dǎo)只要記住結(jié)論ThreadLocalMap的鑰匙分布是經(jīng)過(guò)精心設(shè)計(jì)的所以在ThreadLocal數(shù)量不多的前提下用開放地址法線性探測(cè)解決沖突就夠了不需要像HashMap那樣掛鏈表、轉(zhuǎn)紅黑樹。定位槽位的語(yǔ)句是這樣的int i key.threadLocalHashCode (table.length - 1);table.length永遠(yuǎn)是2的冪所以按位與等價(jià)于取模而且比取模快。如果槽位被占就往后找空位找的時(shí)候如果遇到key為null的過(guò)期Entry還會(huì)順手做清理。這套機(jī)制讓ThreadLocalMap在低沖突場(chǎng)景下性能非常好代價(jià)是它不適合存儲(chǔ)大量key——如果你在一個(gè)線程里new了幾百個(gè)ThreadLocal線性探測(cè)的性能就會(huì)明顯劣化。這也是為什么實(shí)戰(zhàn)規(guī)范里強(qiáng)調(diào)能復(fù)用的ThreadLocal盡量復(fù)用。3. 弱引用不等于安全ThreadLocal內(nèi)存泄漏的完整鏈路分析3.1 Entry的引用鏈key是弱引用value是強(qiáng)引用先看ThreadLocalMap.Entry的定義static class Entry extends WeakReferenceThreadLocal? { Object value; Entry(ThreadLocal? k, Object v) { super(k); value v; } }注意Entry繼承自WeakReference也就是說(shuō)Entry本身是個(gè)弱引用引用的是key也就是ThreadLocal對(duì)象。而value字段是一個(gè)普通強(qiáng)引用。整條引用鏈畫出來(lái)是這樣Thread 對(duì)象 └─ ThreadLocalMap └─ Entry[] └─ Entry (弱引用 - ThreadLocal key) └─ value (強(qiáng)引用 - 你塞進(jìn)去的數(shù)據(jù))弱引用的語(yǔ)義是當(dāng)GC發(fā)生時(shí)如果一個(gè)對(duì)象只被弱引用指向沒(méi)有任何強(qiáng)引用它就會(huì)被回收。也就是說(shuō)ThreadLocal對(duì)象一旦在業(yè)務(wù)代碼里失去外部強(qiáng)引用比如方法局部變量用完了GC就有資格回收它Entry的key就變成null。這看起來(lái)是個(gè)保護(hù)機(jī)制框架不知道業(yè)務(wù)什么時(shí)候不再需要ThreadLocal所以用弱引用保證ThreadLocal實(shí)例本身可以被回收。但value沒(méi)有這層保護(hù)。value是強(qiáng)引用只要Entry還在value就一直在。而Entry被線程的ThreadLocalMap持有ThreadLocalMap又被線程對(duì)象持有。只要線程還活著這條鏈就斷不開。3.2 泄漏的完整形成條件我見(jiàn)過(guò)很多人把ThreadLocal內(nèi)存泄漏簡(jiǎn)單歸結(jié)為用了弱引用這其實(shí)是誤解。弱引用恰恰是為了避免ThreadLocal對(duì)象本身泄漏真正的問(wèn)題出在value的強(qiáng)引用鏈上。一個(gè)完整的泄漏需要同時(shí)滿足三個(gè)條件ThreadLocal對(duì)象失去外部強(qiáng)引用。最常見(jiàn)的是在方法內(nèi)部直接new ThreadLocal()使用方法執(zhí)行完局部變量沒(méi)了ThreadLocal實(shí)例只剩Entry里的弱引用GC一發(fā)生就被回收。線程是長(zhǎng)生命周期的。線程池里的worker線程、Tomcat的請(qǐng)求處理線程都是長(zhǎng)期存活的只要線程不死它的ThreadLocalMap就一直在。沒(méi)有后續(xù)操作觸發(fā)清理。如果后面再也不碰這個(gè)ThreadLocalMap底層的expungeStaleEntry()清理邏輯永遠(yuǎn)不會(huì)執(zhí)行value就變成永遠(yuǎn)無(wú)法訪問(wèn)但一直被強(qiáng)引用的垃圾。典型的業(yè)務(wù)場(chǎng)景長(zhǎng)這樣public void handleRequest(Request req) { ThreadLocalbyte[] holder new ThreadLocal(); holder.set(new byte[1024 * 1024]); // 1MB // 業(yè)務(wù)處理... // 忘記remove方法結(jié)束后holder失去外部引用 }如果這個(gè)handleRequest被丟進(jìn)一個(gè)線程池執(zhí)行每個(gè)請(qǐng)求都new一個(gè)ThreadLocal并set入大對(duì)象那么每次請(qǐng)求都會(huì)在線程的Map里留下一個(gè)key為null、value為1MB數(shù)組的過(guò)期Entry。線程池線程不死這些Entry就永遠(yuǎn)躺在那里。QPS稍微高一點(diǎn)內(nèi)存漲起來(lái)非??臁?.3 線程池既是泄漏放大器也是臟數(shù)據(jù)制造機(jī)線程池把線程長(zhǎng)生命周期這個(gè)條件放大了。普通線程執(zhí)行完一個(gè)任務(wù)就結(jié)束整個(gè)ThreadLocalMap隨著線程銷毀被回收根本談不上泄漏。但線程池的worker線程是復(fù)用的它們一直在等新任務(wù)threadLocals這個(gè)Map也跟著一直存活。線程池還會(huì)帶來(lái)第二個(gè)問(wèn)題臟數(shù)據(jù)串線。假設(shè)你寫了一個(gè)登錄用戶信息上下文private static ThreadLocalUser currentUser new ThreadLocal();任務(wù)A里執(zhí)行了currentUser.set(userA)但忘了remove任務(wù)A跑完worker線程回到池子里待命。任務(wù)B被分配到同一個(gè)worker線程如果任務(wù)B的代碼路徑在某個(gè)分支沒(méi)有主動(dòng)set用戶信息它c(diǎn)urrentUser.get()讀到的就是用戶A的信息。輕則業(yè)務(wù)數(shù)據(jù)錯(cuò)亂重則出現(xiàn)越權(quán)訪問(wèn)。這類問(wèn)題在代碼Review里很難發(fā)現(xiàn)因?yàn)樗皇潜噩F(xiàn)的完全取決于線程池把哪個(gè)任務(wù)分配給哪個(gè)worker。所以在線程池場(chǎng)景下ThreadLocal的正確用法不是用完等GC而是用后必須remove甚至要在任務(wù)最外層做防御性清理。3.4 ThreadLocalMap的兜底清理機(jī)制能救命但不能依賴JDK的設(shè)計(jì)者當(dāng)然知道這個(gè)坑所以ThreadLocalMap在幾個(gè)關(guān)鍵操作里內(nèi)置了清理邏輯set()時(shí)如果發(fā)現(xiàn)相同key的Entry會(huì)用新值覆蓋并對(duì)探測(cè)路徑上的過(guò)期Entry做清理get()未直接命中時(shí)會(huì)在getEntryAfterMiss()里線性向后找遇到key為null的Entry會(huì)調(diào)用expungeStaleEntry()把value置null、槽位置空rehash()時(shí)也會(huì)先全面清理再擴(kuò)容。這套機(jī)制確實(shí)能在很多情況下兜底比如你反復(fù)set同一個(gè)ThreadLocal舊的過(guò)期Entry大概率會(huì)被順帶清掉。它的問(wèn)題是一切清理都必須由后續(xù)的set/get/remove操作觸發(fā)。如果線程執(zhí)行完任務(wù)后長(zhǎng)時(shí)間閑置沒(méi)有任何關(guān)于這個(gè)Map的操作過(guò)期Entry就一直靜止在內(nèi)存里。你指望GC救你但GC根本碰不到value——它有一條完整的強(qiáng)引用鏈。結(jié)論很明確底層清理是優(yōu)化不是保障業(yè)務(wù)側(cè)的remove()才是唯一靠得住的釋放手段。4. 實(shí)戰(zhàn)守則如何正確使用ThreadLocal而不埋雷4.1 remove是底線三種清理姿勢(shì)先說(shuō)最基礎(chǔ)的姿勢(shì)也是我要求團(tuán)隊(duì)必須遵守的用完之后在finally里remove無(wú)論正常返回還是拋出異常都必須執(zhí)行。private static final ThreadLocalString TRACE_ID new ThreadLocal(); public void process() { try { TRACE_ID.set(generateTraceId()); doSomething(); } finally { TRACE_ID.remove(); } }為什么必須在finally而不是在方法末尾因?yàn)榉椒ㄖ虚g拋了異常末尾的remove根本執(zhí)行不到然后殘留值就留在線程里了。線上拋異常是常態(tài)不是意外。很多泄漏就是在某個(gè)異常分支里漏掉了清理。第二種姿勢(shì)是在框架的攔截器或過(guò)濾器中統(tǒng)一清理。以Spring Web應(yīng)用為例如果你需要請(qǐng)求級(jí)的上下文更推薦用HandlerInterceptor的afterCompletion方法public class TraceIdInterceptor implements HandlerInterceptor { Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { TraceContext.clear(); // 內(nèi)部調(diào)用ThreadLocal.remove() } }Filter或者Interceptor的好處是入口和出口都在框架層面業(yè)務(wù)代碼不需要在每個(gè)方法里try-finally漏清理的概率大大降低。第三種姿勢(shì)是封裝成AutoCloseable配合try-with-resources使用public class AutoThreadLocalT extends ThreadLocalT implements AutoCloseable { Override public void close() { remove(); } }這種寫法適合那種只在單個(gè)方法里臨時(shí)用的場(chǎng)景代碼會(huì)更緊湊但我個(gè)人更推薦前兩種——因?yàn)閠ry-with-resources要求每個(gè)用到的代碼塊都正確寫語(yǔ)法而Filter/Interceptor是集中式治理對(duì)團(tuán)隊(duì)更友好。4.2 static修飾符到底該不該加這是一個(gè)經(jīng)常被問(wèn)到的點(diǎn)。結(jié)論分兩種情況。如果ThreadLocal是Spring單例Bean的成員變量那實(shí)例只有一份ThreadLocal對(duì)象長(zhǎng)期存活相當(dāng)于static。這種情況下用不用static修飾影響不大但為了語(yǔ)義清晰統(tǒng)一用private static final。真正危險(xiǎn)的是在短生命周期對(duì)象里持有ThreadLocal。比如一個(gè)每次請(qǐng)求都new的Helper類里面定義了一個(gè)實(shí)例字段ThreadLocalString holder。Helper對(duì)象在請(qǐng)求結(jié)束時(shí)失去引用ThreadLocal對(duì)象也失去強(qiáng)引用GC把這key回收后Map里就剩一個(gè)value還在。如果這個(gè)請(qǐng)求跑在線程池里下次任務(wù)又new一個(gè)新的Helper、新的ThreadLocalMap里的過(guò)期Entry持續(xù)累積。這種寫法是我在代碼Review里看到最多的隱性雷。所以我的建議是ThreadLocal實(shí)例能定義為static final就優(yōu)先static final。它不會(huì)讓你少寫remove但能避免ThreadLocal對(duì)象本身被GC回收導(dǎo)致value失聯(lián)這條更隱蔽的泄漏路徑。4.3 統(tǒng)一封裝上下文工具類把ThreadLocal關(guān)進(jìn)籠子業(yè)務(wù)代碼里散落使用ThreadLocal最大的問(wèn)題不是語(yǔ)法錯(cuò)誤而是管理混亂。今天你在A服務(wù)里set了個(gè)用戶ID明天B服務(wù)也想用又不好意思改A的代碼于是自己又new了一個(gè)ThreadLocal。線程Map里的key越來(lái)越多清理也越來(lái)越不徹底。我建議每個(gè)項(xiàng)目針對(duì)線程級(jí)上下文做統(tǒng)一封裝。比如這樣一個(gè)TraceContextpublic final class TraceContext { private static final ThreadLocalString TRACE_ID new ThreadLocal(); private TraceContext() { } public static void setTraceId(String traceId) { TRACE_ID.set(traceId); } public static String getTraceId() { return TRACE_ID.get(); } public static void clear() { TRACE_ID.remove(); } }然后在整個(gè)調(diào)用鏈的最外層——Filter、Interceptor、或者異步任務(wù)的入口——統(tǒng)一調(diào)用setTraceId統(tǒng)一在finally里調(diào)用clear。業(yè)務(wù)代碼只通過(guò)靜態(tài)方法讀寫不需要知道底層的ThreadLocal長(zhǎng)什么樣。這樣做還有一個(gè)好處以后想換成TransmittableThreadLocal只需要改這一個(gè)類不用滿項(xiàng)目找散落的ThreadLocal.set/get。4.4 子線程與線程池的變量傳遞InheritableThreadLocal的局限和TTL的解法很多場(chǎng)景需要把父線程的上下文傳到子線程比如異步任務(wù)里記錄traceId。JDK提供的原生方案是InheritableThreadLocal。它的實(shí)現(xiàn)原理是父線程創(chuàng)建子線程時(shí)把父線程的inheritableThreadLocals里的Entry復(fù)制一份給子線程。注意是創(chuàng)建線程那一刻的快照而且這個(gè)復(fù)制是淺拷貝——如果value是可變對(duì)象父子線程持有的是同一個(gè)引用并發(fā)修改照樣有競(jìng)爭(zhēng)問(wèn)題。InheritableThreadLocal最大的局限在于線程池。線程池的worker線程不是每次任務(wù)都新建的它早在提交任務(wù)之前就創(chuàng)建好了。父線程想傳值給worker線程根本不觸發(fā)線程創(chuàng)建過(guò)程InheritableThreadLocal完全無(wú)效。而且即使你第一次提交任務(wù)時(shí)值傳過(guò)去了下次提交新值也不會(huì)更新因?yàn)閣orker線程不會(huì)再走創(chuàng)建線程復(fù)制這條路徑。這個(gè)場(chǎng)景下業(yè)界更常用的方案是阿里開源的TransmittableThreadLocal簡(jiǎn)稱TTL。它的思路是在任務(wù)提交時(shí)捕獲當(dāng)前線程TTL值的快照任務(wù)真正執(zhí)行前把快照回放到執(zhí)行線程上執(zhí)行結(jié)束后恢復(fù)執(zhí)行線程原有的值。使用方式很簡(jiǎn)單ExecutorService executor TtlExecutors.getTtlExecutorService(executorService); executor.submit(() - { // 這里能正確讀到提交任務(wù)時(shí)的上下文 });不引入依賴包的情況下你也可以自己包裝Runnable在run()前后手動(dòng)set/remove實(shí)現(xiàn)思路和TTL一致提交時(shí)快照?qǐng)?zhí)行前回放執(zhí)行后清理。只不過(guò)TTL把這個(gè)邏輯封裝好了還支持Java Agent方式自動(dòng)透?jìng)鳌H绻?xiàng)目里大量使用線程池且需要傳遞traceId、用戶身份這類上下文建議直接把TTL納入基礎(chǔ)設(shè)施。5. 一次線上OOM排查實(shí)錄如何定位到ThreadLocal泄漏5.1 現(xiàn)象老年代持續(xù)上漲但GC后回不去之前接手過(guò)一個(gè)異步處理服務(wù)現(xiàn)象很典型JVM老年代使用率從啟動(dòng)后一路爬升Full GC之后也只是從95%降到80%很快又漲回去。接口響應(yīng)時(shí)間越來(lái)越長(zhǎng)最后每天固定OOM一次只能靠重啟續(xù)命。第一反應(yīng)肯定是先看GC日志和內(nèi)存曲線。用jstat看一眼jstat -gcutil pid 1000輸出里重點(diǎn)觀察FGCFull GC次數(shù)和O老年代使用率。如果YGC很頻繁、FGC也在持續(xù)增長(zhǎng)但老年代使用率始終處于高位說(shuō)明堆里有大量對(duì)象無(wú)法被回收。這時(shí)候就要考慮是不是有對(duì)象被長(zhǎng)生命周期對(duì)象比如線程、類加載器、緩存持有形成了事實(shí)上的泄漏。值得提醒的是不要一看內(nèi)存高就無(wú)腦調(diào)-Xmx。調(diào)大堆只會(huì)推遲OOM時(shí)間不會(huì)解決問(wèn)題。正確步驟是把堆dump下來(lái)看對(duì)象構(gòu)成。5.2 用jmap導(dǎo)出堆快照再用MAT定位可疑對(duì)象低峰期用jmap導(dǎo)出堆快照jmap -dump:live,formatb,fileheap.bin pid注意live參數(shù)會(huì)先觸發(fā)一次Full GC生產(chǎn)環(huán)境盡量在業(yè)務(wù)低谷操作或者改用jcmd pid GC.heap_dump heap.bin。dump文件通常很大本地用MATMemory Analyzer打開。打開后先看Histogram直方圖按retained heap排序。在這個(gè)服務(wù)里我很快就看到了一個(gè)熟悉的自定義類RequestContext有幾萬(wàn)個(gè)實(shí)例retained heap占了差不多1GB。這個(gè)類為什么會(huì)單例持有那么多實(shí)例肯定是被某個(gè)容器類緩存了。接下來(lái)右鍵這個(gè)類選擇List objects - with incoming references看看引用它的是什么。你會(huì)看到大量引用來(lái)自java.lang.ThreadLocal$ThreadLocalMap$Entry這就基本鎖定方向了這些對(duì)象都被ThreadLocalMap里的Entry強(qiáng)引用著。5.3 順著GC Roots路徑確認(rèn)是ThreadLocal鏈確認(rèn)這一步需要右鍵對(duì)象選Path to GC Roots - exclude weak references。如果之前看過(guò)一遍ThreadLocal的引用鏈此刻再看這條路徑會(huì)非常清晰Thread (worker線程) └─ ThreadLocalMap └─ Entry[ ] └─ Entry └─ value (RequestContext實(shí)例)路徑里能看到Thread對(duì)象是GC Roots因?yàn)榫€程池里的worker線程都活著正等著新任務(wù)。順著路徑往下還會(huì)發(fā)現(xiàn)一個(gè)關(guān)鍵細(xì)節(jié)很多Entry的key已經(jīng)是null了。這說(shuō)明ThreadLocal對(duì)象本身已經(jīng)被GC回收但value還躺在Entry里。這就是典型的key弱引用被回收、value強(qiáng)引用殘留的泄漏形態(tài)。如果只看Entry數(shù)量還不足以定位到代碼就再切到線程棧視圖把目標(biāo)Thread的線程棧打出來(lái)看看這個(gè)線程最近在執(zhí)行什么業(yè)務(wù)然后回代碼里找這個(gè)業(yè)務(wù)鏈路上的set()調(diào)用。我當(dāng)時(shí)就是從worker線程綁定的任務(wù)名一路追到一個(gè)公共的異步切面發(fā)現(xiàn)在切面里為了記錄traceId每次請(qǐng)求都new ThreadLocal()set完之后沒(méi)有remove方法結(jié)束ThreadLocal失去強(qiáng)引用剩下的value就全留在線程池線程的Map里了。5.4 修復(fù)與驗(yàn)證一行remove解決幾百M(fèi)B內(nèi)存修復(fù)方案很簡(jiǎn)單把那個(gè)切面里的new ThreadLocal改成靜態(tài)常量并在finally塊里調(diào)用remove()。public class AsyncTraceAspect { private static final ThreadLocalString TRACE_ID new ThreadLocal(); public Object around(ProceedingJoinPoint point) throws Throwable { try { TRACE_ID.set(buildTraceId()); return point.proceed(); } finally { TRACE_ID.remove(); } } }改完之后再用jmap導(dǎo)一次堆用MAT對(duì)比修復(fù)前后的對(duì)象數(shù)量。最直觀的驗(yàn)證指標(biāo)有兩個(gè)一是RequestContext的實(shí)例數(shù)從幾萬(wàn)降到了和線程數(shù)同一量級(jí)二是老年代使用率在幾次Full GC后穩(wěn)定在30%左右不再持續(xù)爬坡。這個(gè)效果不是靠調(diào)參數(shù)調(diào)出來(lái)的是真正把引用鏈斷了。排查過(guò)程中還有一個(gè)容易忽略的點(diǎn)如果你在MAT里用exclude weak references查不到GC Roots路徑不要慌。key為null的Entry本身已經(jīng)斷開了對(duì)ThreadLocal的引用MAT的弱引用排除規(guī)則可能導(dǎo)致路徑不顯示。這時(shí)候換include all references再查或者直接在Dominator Tree里找ThreadLocalMap通常能看到完整的引用鏈。這次排查給我留下的最深印象是ThreadLocal泄漏很少是單個(gè)大對(duì)象的問(wèn)題更多是業(yè)務(wù)對(duì)象被線程池線程長(zhǎng)期持有的組合問(wèn)題。你單看每個(gè)對(duì)象都不算大但線程池有幾百個(gè)線程每個(gè)線程攢幾百個(gè)過(guò)期Entry就是幾百M(fèi)B甚至上GB的垃圾。它在代碼Review階段極難發(fā)現(xiàn)因?yàn)樗衧et/remove分散在各個(gè)方法里沒(méi)有一個(gè)集中的審視點(diǎn)。這也是為什么我會(huì)在前面的實(shí)戰(zhàn)部分反復(fù)強(qiáng)調(diào)統(tǒng)一封裝和攔截器清理——線上少踩一個(gè)坑比事后排查輕松太多。最后分享一個(gè)我個(gè)人的習(xí)慣線上服務(wù)里如果需要排查ThreadLocal相關(guān)的問(wèn)題除了jmap和MAT也可以用Arthas的watch命令觀察某個(gè)上下文類的set和remove調(diào)用次數(shù)。如果發(fā)現(xiàn)set被瘋狂觸發(fā)但remove幾乎不觸發(fā)那基本不用dump堆也能判斷問(wèn)題出在哪了。這套組合拳下來(lái)ThreadLocal這個(gè)線程私有的小籠子在你手里就不再是黑盒了。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
亚洲免费97免费| 国语精品内射在线观看| 国产精品人人爽人人做可爱福利| 久久这里精品国产99丫e6| 日日摸天天爽夜夜欢| 亚洲va综合va国产va中文| 亚洲激情久久久伊人综合| 精品性爱一区二区| 欧美天天性| 秋霞男人网| 天天色天天干天天爱| 亚洲国产蜜臀系列在线观看| 麻豆久久久久久久久丝袜| 强被迫伦姧在线观看无码网站| 9久在线视频只有精品| 四虎免费看黄| 簧片免费看视频| 清纯唯美第一页| 超碰到97情色| 久久久久久性爱视频| 屌逼麻豆| 8x福利精品第一福利视频导航| 亚洲 欧美 第一页| 欧洲与亚洲欧美精品中文字幕| 久久美女国产| 中文字幕一区二区视频在线观看| 9长久久精品| 欧美淫穴| 激情啪啪拍91| 强奸乱伦日韩AV| 清纯唯美亚洲综合| 天天草天天日| 狠狠操狠狠操操| 久久久久久久97| 高清不卡 中文 人妻| 精品视频97| 久久久婷婷| 91久久免费视频互動交流| 欧美精品欧美精品系列 | 亚洲精品a人片在线观看视| 美日韩男女操屄视频| 91精品老女人| 四虎精品永久在线观看| 国产自产22区| 国产自偷| 激情人妻另类| 国产极品久久久| 另类av综合久久| 日韩中字av一区| 日韩av在线免费网站| 操我无码| 久久男人的天堂国产| 69精品久久久久中文字幕| 亞洲久久直播| 屁屁影院一区二区三区国产| 亚洲第一在线视频| 日韩黄色电影网站| 婷婷五月丁香五月| 欧美永久激情一区二区| 国产91专区| 久久久久久久久久久久97| 丝袜高跟澳门91视频| 亚洲素人综合| 欧差乱伦二三| 亚洲无码视频免费在线观看网址!| 亚洲一区日韩精品中文字幕| 国产无码精品高清| 亚洲av成人精品一区| 九九九精品美女| 97超碰色屌| 私色综合网| 亚洲蜜臀懂色| 91无遮挡| 亚洲中文制服诱惑| 亚洲情色一区综合| 黄站在线免费观看| 国产91精品在线免费| 操我无码| 久久久久中出| 97久久久网站| 天天色黄色影院天天操| 中文字幕 国产区| 人妻天堂综合网| 黄污污污污| 欧美猛交黑寡妇中文字幕| 天天影视综合色| 思思热在线视频免费| 亚洲A曰本VA欧美VA视频| 久操99| 久久久久极品| 日韩少妇无码| 精久久久91| 色臀AV| 深夜国产一区二区三区在线看| 日本特黄f c2| 久久久久亚洲| 日韩欧美字幕亚洲一区二区| 国产五码丝袜屁眼| 免费看片黄| 超碰成人免费| 国产精品久久久777| 欧美 色 亚洲| 亚洲九区| 日韩专区久久久| 人妻另类 专区 欧美 制服| 男男H黄动漫啪啪无遮挡网站| 欧美久久九九| 婷婷久月| 天天操天天射青青草| 日韩日韩日韩-国产乱码精品一区二区| 欧美人体性爱互联网第一页婷婷日本| 91丨国产丨白浆| 亚洲精品天天影视综合网| 97国产|免费| 国产精品无码在线| 亚洲偷拍欧美激情| 91AV入口| 九九热超碰97亚洲最新香蕉 | 99综合视频| 亚洲性感丝袜诱惑在线观看| 男男H黄动漫啪啪无遮挡网站| 久久一二三四不卡| 国产亚洲精品美女久久久久久2021| 操人妻丝袜高跟| 亚洲性天堂| 久久久久久久人妻| 操曰本熟女| 一级aaaaa欧美中文字幕录像片| 亚洲国产欧美日韩人妻日中文| 亚洲天天自拍| 性色av蜜臀av色欲aV| 夜夜狼人妻| 日韩在线欧美精品一区二区| 神马久久中文字幕| 伊人久久大香线蕉无码| 欧美日韩亚洲天堂| 日韩在线97| 97摸视频| 97香蕉网| 六月婷婷一区二区三区| 色呦呦、国产精品| 被窝影院午夜看片无码| 日韩丝袜高跟制服在线观看| 免费岛国一级片| 亚洲国产精品久久久久婷婷青年| 欧美区亚洲区偷拍区| 日韩激情视频| 九九性爱网| 97精品久久| 欧美亚洲一区二区久久久婷精品大包诱| 日本在线观看网址| 久久后入制服| 欧美性爱一内片一区二区三区| 91欧美情色| 午夜丁香婷婷| 久久国产熟女影院| 亚洲精品国产拍免费91在线| 97久久精品亚洲中六字幕| 亚洲国产精品无码AV在线| 天堂国产AV| 日本欧美一区二区三区免费| 性色亚洲| 97超碰色中文字幕| 九久9热| 两性色网| 国产粉嫩蜜臀av一区二区三区 | jizz啪啪| 懂色AV网| 九一综合网| 91精品综合久久久久久五月丁香| 亚洲图片激情综合另类| 亚洲一区在线观看欧洲| 天天久久久久久| 色婷婷综合久久中文字幕雪峰| 国产亚洲精品第一最新| 91快色色色色色| 免费a v| 亚洲高清少妇| 中文字幕一区二区三区视频播放| 欧美自拍网| 2017大香蕉国产精品久久| 99热婷婷| 日本一区二区不卡精品| 国产v片在线免费观看| 亚熟hd视频在线| 九九亚洲视频| 亚洲精品三| 在线A日本| 久久久久人| 久久九七| 日韩天堂av电影在线观看| 亚欧高清在线| 日韩精品中文字幕一| 日韩精品在线视频,日韩精品……| 福利五区| 久草久日| 啊啊啊啊啊啊啊啊啊在线观看| 亚洲另类久操网| 欧美后进式| 久久女婷| 丁香五月性| 精品久久久中文字幕不| 日韩三级一区| 国产夫妻一区二区| 九九拍拍精品视频在线播放| 欧美在线色图| 国产一区二区久久| 亚洲一区二区三区久久 亚洲一区二区| 黄色av播放免不| 欧美色五月| 国产色呦呦| 日躁天天爽爽| 秋霞网无码| 日韩欧美女求操每天更新| 看看日B真人视频| 亚洲综合 欧美| 女上位精品在线| 激情文学小说一区二区| 九九九九一级| 日韩欧视频| 骚女天天综合网| 超碰综合97在线| 五月天九九日国产精品一区二区三区| 97青娱乐超碰久久| 九九人妻| 人妻第一页| 久久久久久九九九九| 国产一级高清免费观看| 国产成年女人免费视频播放a| 国产高清精品一区二区三区毛片| 人、人、摸,人、人、草| 中文字幕一区二区三区高清| 国产精品白丝在线播放| 91爆操视频| 亚洲AV无码国产精品久久久久| 日本色色网| 清清一区二区三区四区不卡视频| 日本999精品视频| 综合色久欲| 欧美最婬乱婬爆婬牲视频| 中国熟女网站| 嗯嗯不要 视频| 日本一久是| 后入福利视频| 欧美亚洲| AA特级绝黄| 丁香六月婷| 久久超碰亚洲人| 啊啊啊啊好大好硬啊啊啊啊啊| 欧美后入式| 97超碰磁| 亚洲 日韩 欧美 国产综合体| 欧美黄色图片| 国产999精品久久久| 欧美片第一页| 色一射色一射| 国内一级精品| 亚洲 欧美日韩 另类| 欧美男女午夜啪啪| 午夜啊啊| 国产av美女被艹的乱叫| 成人AV素股で擦久久| 久久久国产精品亚洲精品| 亚洲在线91| 热99这里只有精品| 久久神马影院| 张柏芝国产一区在线观看| 国语对白在线播放视频| 啊啊啊啊操死我了| 国产精品成久久久久午夜午夜| 亚洲最大网站av| 超碰久草| 精品欧美А∨无码黑人大荫蒂| 97在线精品| 亚洲资源网| 美国黄片aaa| 97九色人妻| 亚洲色图欧美色图综合| 男女一级A片大黄,一进一出| 国产后入清纯| 性爱Av免费| 宅男91视频在线播放| 色网亚洲人| 另类一区| 天天干1区2区在线| 91操人| 欧美在线l亚洲| 看日韩黄片| 97舔舔| 欧美日韩亚洲天堂| 欧美熟女少妇| 黄色免费网| 91在线美女| 天天激清| 久久久久9999精品九九九| 日韩精品国产一区二区| 人妻酒店出差被中出免费在线播放| 热99这里有精品综合久久 | 国产无码久久高清| 男人干美女| 久艾草在线精品视频在线观看| 日本熟妇熟色97一本在线观看| 午夜传煤十二区精品| 一块操欧美性爱| 无码人妻丰满熟妇区毛片| 1769一区二区| 亚洲综合有码| 久热色情精品| 美女写真| 91日产桃蜜| Julia在线播放亚洲久久| 老鸭窝成人免费毛片视频| 五月天精品| 夜夜嗨视频| 一个人在线看的黄色电影网站| 尹人免费观看视频在线| 欧美亚洲涩涩| 亚洲AV免费在线| 东京热综合久久一区二区| 日本高清电影欧美色图| 日本东京热久久久电影| 中国熟女91| 狠狠操狠狠| 久久伊人最新网址视频| 欧美在线干| 男人的天堂不卡一区二区| 91精品国产91久久福利| 加勒比伊人综合| 天天色播| 东京热视频网| 中文字幕第7页| 欧美不卡在线美女| 久久亚洲AV无码专区首页| 欧美图片色五月天| 97综合在线观看| 久操视频资源站公开| 欧美黄业| 骚鸭AV| 人妻少妇精品视频一区二区三区| 久久综合乱子伦国产免费| 黄色区免费观看中文字幕| 全国男人天堂网| 丰满搜索结果 -第18页- 久久高清无码 | 久久av一级av少妇av高潮 | 大伊香蕉在线视频免费| 国产高清成人免费视频| 97在线日韩中文字幕| 日本九九久久99播| 欧洲天天在线| 九九久久综合| 性爱乱伦一区| 午夜AV人气不卡| 日本影视久久免费| 欧美美逼| 亚洲日本大香蕉1| 超碰夫妻97| 蜜臀av一区二区三区免费观看| 伦伦成年午夜免费视频| 精品性爱| 9久精品| 久久精品成人| 丝袜狂射91| surenchaopeng| 狼人综合婷婷激情四射| 色欧美天天| 97精品综合久久| 一级日本牲交大片好爽在线看| 狠日欧美| 亚洲日韩天堂| 亚洲色宗合| 日韩91网| 国产97亚洲| 综合亚州欧美| 这里都是精品| 视频不卡中文字幕| 欧美v日韩v亚洲v最新在线| 啊啊啊啊免费视频| 绯色一区二区三区不卡少妇| 亚洲天堂久久久久久粉红视频| 久久三区四区| 97干97色| 一区二区三区美女超清| 日韩福利电影网| 在线亚洲欧美| 中文字幕在线免费观看2| 91中出| 国产91福利小视频在线观看| 日韩欧美性爱电影在线观看| 中文字幕丰满人妻日本| 精品国产91av一区二区三区| 免费一级性爱久久| 久久久久免费看少妇A片特黄| 成人免费视瓶| 久久黄色视频一区二区三区| 国产高清免费不卡av| 91成人久久| 色综合av男人天堂| 欧美一区二区三区日韩| 欧美一级三级| 清纯唯美激情四射| 国产精品熟女九九九| 中文久久96| 97在线日韩中文字幕| 四虎在线视频| 国产成人拍国产亚洲精品| 91午夜无码| 亭亭丁香激情| 91美女在线视频| 精品成人女人久久| 老熟女91视频| 少妇啪啪自拍| AA丁香综合激情| 蜜桃久久久久久| 天天综合网~91入口| 人妻丰满熟妇av无码区蜜桃| 美女诱惑一区| 26uuu国产成人综合| 九九激情网| 夜夜狼人妻| 亚洲亚洲亚洲天堂天堂| 乱性AV| 91干熟女| 97超级欧美| 97久久超碰国产精品| AAAA欧美日韩| 99爱精品| 日本熟妇自慰性高潮一区二区三区| 欧美日韩精品久久久久久久久东北老熟妇| 琪琪精品免费一区二区三区| 99精品网| 综合色久欲| 国产精品麻豆免费视频| 亚洲无套久久嗯嗯| 黑人精品欧美一区二区蜜桃| 一区二区三区亚洲| 东京太热久久久| 男人成人黄色视频在线观看免费下载| 亚洲色图 欧美| 国产乱码精品一区二区三区四川| 韩国女主播青草在线| 激情综合 婷婷五月 红杏| 日本熟女不卡视频| 欧美综合骚| 啊灬啊灬啊灬啊灬高潮奶出了免费视| 亚洲视频中文一区| 久久久久久久人妻| 超碰在线成人电影| 丰满人妻一区二区三区大胸懂色| 国产乱码精品久久久久久| 热热色91| 婷婷丁香久久| 亚洲风情综合网| 曰韩操B| 免费看污网站| 小说区 图片区色 综合区| 五月天社区| 蜜桃网熟妇| 91社操逼| 欧美亚洲厕所精品偷拍91 | 婷婷五月天av| 午夜啊啊| 中文字幕在线免费观看视频| 欧美在线|亚洲| 在线观看岛国有码| 在线小视频| 曰韩操B| 日日AV加勒比| 无码 黑人一区二区三区| 欧美日日夜夜| 色哟哟AⅤ| 日韩中文字幕熟妇人妻| av毛片aaaaa免费看| 嗯嗯,啊啊,国产精品| 亚洲精品九九九| 天天干夜夜| 另类 日韩 熟女| 久久精品电影| 五月婷婷激情网| 骚鸭AV| 色九月| 日韩小电影| 欧美黑人猛交春色影视大全| 国产乱伦视频污| 亚洲综合性感在线| 自拍偷拍亚洲熟女妇人精品| 亚洲综合射| 国产成人精品亚洲日本| 天天综合网日韩| 色91综合网| 草草影院日本第一页| 2019午夜福利视频| 国产伦精品一区二区三区在线观 | 日本高清_区二区三区| 无码操逼天堂| 国产原创自拍| 欧美黄色片在线播放| 精吧天堂| 色色无码| 亚洲一区二区久久久久| 中文字幕熟女人妻丝袜丝| 男人的天堂啪啪| 久久久久亚洲三级电影| 少好三P| 亚洲熟妇极品| 色爱三区| 久久久久久网址| 老熟妇一区二区三区啪啪| 欧美国产日韩高清在线| 国产强奸AV在线| 嫩草 我啊~嗯~在线| 亚洲精品男人的天堂| 亚洲影院无码在线| 激情内射| 欧美情色男人的天堂| 五月婷婷丁香中文字幕| 在线观看不卡一区二区三区| 亚州欧美在线| 美女干逼2| 亚洲熟妇自偷自拍另欧美| 小视频国产| 中文字幕成人乱码熟女精品国50 | 嗯啊抽插大香蕉网页| 久久久性爱| 亚洲污污网站| AV丝袜少妇| 五月婷婷六月天| 两性色网| 国产精品99精品视频网站| 一二区在线观看视频| 91成人国产综合久久精品蜜月| 啊…啊…操我用力操我| 久久免费精品视频免一| 国产一级高跟丝袜| 超碰在线欧美性爱激情| 女性91网站| 欧美色91| 久久精品一区一起草| 国产丰满少妇久久久精品影院| 超碰人人妻| 999国产精品999| 国产宅男宅女在线观看| 国产精品久久久久久高清无码免费看| 欧美色人| 青青草国产欧美非洲黑人| 蜜区区视频79 | 日韩性爱一级片| 九七色图| 1240青青草一区二区三区视频天爱| 天天天操天天天爱| 黑人精品久久97| 国产精品网站www| 欧美少妇一区二区三区| 日本天天人人狠狠在线日美女 | 婷婷导航| 东京热激情视频一二三区| 久久亚洲婷婷| 激情五月天色色| 日本九九九九| 丁香五月成人| 亚州情色j区| 91视频国品一二三区| 国产精品电影| 久久久久久久久久久久欧美日| 神马久久久久眼| 色呦呦、国产精品| 亚洲美女30b| 日欧毛片久久| 伊人在线大香蕉视频久久| 97欧美色综合| 亚洲国产天堂| 亚洲影视综合| 亚洲精品一区二区精华| 不卡av在线中文字幕| 国产精品女久久久久av爽| 国产精品一级片在线看| 综合久| 成人欧美一区二区三区黑人一| 色五月婷婷五月天| 嗯嗯啊啊用力视频免费| 嫩草影院永久在线制服丝袜| 大但人体久久久久| 亚洲一区二区AV| 91P0RNY大屁股人妻| 26UUU欧美激情一区二区| 性色av网站| 五月婷婷色| 亚洲综合码| 韩日自拍| 超碰色综合| 草草影院最新网址| 99精品久久久久久久婷婷蜜桃| 99色视频| 激情欧美日韩女同久久| 国产青青综合伊人| 亚洲成人激情小说视频| 日本视频在线观看污污污| 久久丁香| 午夜后入| 91天天综合日韩欧美| 91人妻最真实刺激绿帽| 日本在线不卡一二区| 丰满少妇人妻久久久久久| 亚洲日韩欧美一区二区| 91中文字幕| 欧美视频一区二区在线| 美女露胸露屁股| 免费超碰97久久| 91老熟女视频| 高清在线偷拍自拍视频| 精品亚洲俞拍视频一区| 欧美日韩亚洲天堂| 日韩黄色一区二区三区| 99热免费精品| 91综合网站| 日韩欧美字幕亚洲一区二区| 91天天综合网,天天综合网| 欧美性第1页| 一本大道不卡一二三区| 欧美大香蕉在线观看| 亚洲天堂一二| xxx0国产在线播放| 97se综合网| 一本色道综合久久欧美日韩精品| 青娱乐久久艹| 我中文字幕6区| 精品三级在线专区| 91久久国产综合久久| 精品高清牛人盗摄一区二区三区中文字幕A片免费在线观看 | 欧美 亚洲| 亚洲免费人妻在| 欧美少妇性乱| 欧美偷拍区| 欧美一级欧美三级在线观看 | 久久天天性久久伊人| 性生活性生大爱77AV国产| 青青伊人这里只有精品| 亚洲在线a| 日本三级韩三级99久久| 破处bbq| 中日韩久久久| 激情黄色五月天| 制度丝袜99| 中文字幕十五区| 在线看的av| 久操大香蕉超碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰 | 欧美日韩1234| 男人亚洲91首页在线| 日本Suv精品一区二区| 99在线精品观看99| AV色女综合| 婷婷啪啪| 精品福利| 偷拍亚洲高清图片| 无码直播久久久| 一区二区三区色综合| 99久久这里只有精品| 亚洲限制级| 美国日韩黄片| 精品176精品2| 欧美一级久久久久久久大片动画| 吉川爱美亚洲二区在线| 中文字幕aⅴ在线视频| 久久精品视| 国产AV高清AV无码| 国产精品夜夜| 日本曲间由美性生活片| 亚洲欧洲av影音| 天天干天天日天天射黄色片| 天天操天天干一区二区| 欧美91色| 狂操嫩妻视频一区二区三区| 免费岛国一级片| 97干天天| 五月婷婷激情网| 国产精品乱码久久久久| 日韩超碰精品综合| 天天躁日日躁XXXXYY| 蜜臀久久99精品久久久久久酒店| 97久久精品亚洲| 在线有码中文字幕| 青青青草原| 天堂九九九九九九九九九| 内射小黄片| 久9综合在线| 看黑人AV不卡| 色一色综合网| 国产偷拍网站| 呻吟 欧美 日本 中出| 吻戏激情性巴克| 密乳AV免费观看| 久久国产精品m码| 丰满搜索结果 -第18页- 久久高清无码| 欧美性爱三区二区| 91视频在线观看18| 搡老女人老91妇女熟女| 亚洲欧洲小说图片视频 | 91欧美高清| 成年女人黄网站| 精品一区二区三区麻豆| 日韩精品人妻中文字有码在线 | 91色射| 不卡九肏| 韩日精品四区| a天堂视频| 欧美极品美女aaaaaa级黄片| 99在线精品观看视频中文| 九九成人精品| 日本精品一区三区| 乱伦系列一区二区| 日韩三A大片在线观看| 中文字幕制服诱惑| AV在线播放网址| 少妇极品熟妇人妻无码| 校园春色之综合网| 五月天激情影院| 老熟女乱子伦中文字幕一区二区| 91综合在线| 欧美se综合| 997色在线| 欧美亚洲宗合色性图| 91N五十路| 97精品97| 久久久久一本一区二区青青蜜月| 天天综合色电影| 久久婷五月| 91人妻Pr| 日本国产成人亚洲精品无码| 国产高清成人mv在线观看| 日韩欧美午夜一区二区| 草草草视频在线免费看| 亚洲熟女综合一区二区| 风韵犹存大大大大香蕉| 日本在线999| 亚州色图欧美色图| 深夜激情 | www.超碰| 天天干天天做| 麻豆人妻精品一区二区| 97色色色| 久久一二三四五六七八九区区区 | 大香蕉手机在线| 国产精品高朝久久久久久久| 狠狠操狠狠燥| 狠狠躁久久躁| AV有码在线| 人人妻人人澡人人爽人人精品浪潮| 亚洲丨在线| 色色九区| 2024黄色视频| 18禁止看精品中文字幕| 亚洲无无码αⅴ每日更新| 欧美成年人性爱视频免费观看| 曰韩人妻中文字幕在线| 日本伦乱九九九综合| 中文字幕日韩专区精品系列| 影音先锋乱伦资源| 日韩久久.一级黄色片| 亚洲国产一级精品毛一级精品看免费视频| 亚洲色 国产 欧美 日韩| 麻豆啪啪啪视频| 综合色播| 日本不卡三级网在线播放| 精品乱子一区二区三区99| 欧美熟女妇同| 日韩专区久久久| 夜夜爽夜夜高潮夜夜爽| 亚洲成人激情小说视频| 中日亚韩免费视频| 十八禁啪啦拍视频无遮挡| 五月天色综合| 久久偷拍人| 97热视频在线观看| 天天干18禁| 久久透逼视频| 人人色人人操在线| 色呦呦、国产精品| 毛片麻豆91糖心精品毛情片| 91精品人妻一品二品三品| 亚洲婷婷丁香在线| 日本视频在线观看污污污| 国产亚洲一黄| 亚洲男人的天堂在线看| 日日摸日日弄日日拍| 亚洲av青草久久一区二区| 69少妇一区二区| 色婷婷五月综合| 97超碰亚洲| 97亚洲精品超碰| 少妇xx精品| 国内精品999| 天天干夜夜肏| 欧美精品精品一区二区| 欧美日韩操逼嗦吊| 青草香蕉网| 久久久久白虎| 亚洲最新中文字幕免费| 天天干天天日天天射黄色| 丝袜天堂网| 日韩强奸av| 色噜噜婷婷| 在线免费试看60秒| 亚洲中字幕日本一区二区三区| 精品性爱一二三区| 亚洲精品骚逼| 97爱| 色九九综合| 亚洲诱惑天堂| 天天爽夜夜爽夜夜爽精| 成人资源中文字幕在线观看天天| 97爱碰| 日小BB小视频| 男人天堂站| 外国免费性情大片| 福利在线黄片| 天综合网欧美| 日韩成人精品| 不卡人妻少妇精品毛片一区23区视频| 国产精品另类| 欧美成人一区二区三区在线播放 | Av手机版天堂网| 高凊专区人人操| 2017天天插| 婷婷视频网| 干b网| 国产 v乱码一区二| 欧美色综合图片| 黄色AAAAA欧美| ai欧美亚洲小说| 中字幕人妻一区二区三区| 亚洲熟女国产综合另类| 亚洲色图亚洲| 天天欧美欧美亚洲网| 欧美姓爱综合网| 亚洲日产专区婷婷| 日韩一区二区精彩视频| 日日干日日操五月天伦理视频| 1区2区3区视频| 蜜桃视频精品一区二区| 综合久久9| 内射白嫩美女| 日韩欧美性爱电影在线观看| 国产在线不卡导航| 日韩精品中文字幕人妻| 久久久久久久久九九久孕交| 日韩无码视频黄色| 青久操| 国模不卡| 亚洲骚男同com| 99久视频| 激情综合网激情综合| 夜夜狼人妻| 综合国产影视三级| 九9热伊人| 五月天婷婷久久| 成人久久久| 日han少妇无码| 黄色AAAAAAAAAAA大片| 色婷婷一区二区三区久久午夜| 亚洲一本色道中文无码aV天美| 色综合1991| 六月婷婷五月丁香| 高清有码一区二区| 偷拍色图| 95人妻爽爽人人做人人澡| 中文乱码字字幕在线第5页| 色噜噜人妻丝袜AV资源| 国产精品久久久久久片| 欧美熟妇色| 一本正道久久熟女| 操操逼操操逼操操逼逼| 97资源站国产精品| 偷拍 精品 另类 四区| 国产精品人人爽人人做可爱福利| 情色五月天就去干| 黑操B| 日韩欧美成人性爱在线| 无码粉嫩白虎一线天b区| 国产日韩精品一区二区三区| 天堂无码精品国产久| 97超碰9| 亚洲欧洲无码97久久精品| 干婷婷综合网| 立川理惠被中出无码| 国产欧美后入| 天天操天天射青青草| 精品亚洲黄色片 国产精品导航一区二区| 亚洲人妻色图| 九九热这里只有在线精品视 伊人草 成人菠萝蜜视频在线观看 | 爽爽淫人网| 亚洲性爱免费电影| 天天干人人乐| 天天摸天天舔天天操| 五月丁香激情综合| 欧美性爱1080p| 超碰成人人人爽人人爽| 伊人在线大香蕉视频久久| 国产久久久9999| 亚洲色欲天天人妻无码系列专区| 国产精品成久久久久午夜午夜| 色97国产69香蕉| 91网站18在线| 日韩草久视频| 欧美成人黄网色网站| 欧美A片中文字幕| 丝袜综合网| 中文字幕欧美日本乱码一线二线 | 日韩人妻有码免费视频| 久久超碰日韩精品| 夜夜嗨一区| 亚洲老司机123专区| 宅男91视频在线播放| 91五月天| 在线观看精品国产免费| 国内精品久久人妻性色av| 丁香九月婷婷| 揉揉日日日日| 亚洲素人综合| 九九人妻| 秋霞福利网| 欧美韩国你懂得在线 | 成人久久无码www| 91无人区卡一卡二卡三乱码入口最新版:能让用户有更多选择的选择-经典说说-爱 | 亚洲精品不卡一二三区| 九X超碰| 亚洲欧美中日韩| 999日韩中文精品观看视频。| 国产亚洲色婷婷久久99精品91| 精品亚洲黄色片 国产精品导航一区二区| 亚洲 无码 偷拍| 亚洲情色欧美| 91天天| 国产成人亚洲精品无| 蜜臀久久99精品久久久久久| 麻豆91熟妇人妻中文字幕茄子| 欧洲亚洲人妻无码久久三区四区| 久射吧| 九九热只有精品| 在线洲亚线| 亚州欧美在线| 亚洲中文字幕熟女少妇一区二区| 蜜屁av| 超碰地址久久| 日韩三级伊人| 中文操逼字幕| 国产亚洲色婷婷久久99精品91 - 百度| 亚洲情色综合| 国产精品懂色tv影视免费观看| 亚洲阿v天堂在线| 26uuu最新| 91视频伊人| www亚洲免费| 在线观看岛国有码| 国产一区二区啪啪视频| 国产高潮AA片免费看| AV九九| 玖玖97综合| 日韩超碰精品综合| 精国久久一区二区三区98| 日韩精品系列| 91亚洲图片| www久久国产精品| 岛国网址国产 | 色av中文字幕| 91精品国产乱码| 999色欧美中文字幕| 女生91网站| 一个国产在线综合网站| 一级A片女人高潮叫床| 久久婷五月| 99国产在线绯色一区| 精品一国2| 亚洲av资源| 人人操人人摸avav| 在免费jIzzjIzz在线视频| 色婷婷狠狠| 亚洲天堂自拍| 噜噜噜亚洲精| 国产又猛又粗又爽又黄| 俺去俺来也在线www| 婷婷四五区| 手机久操欧美综合色码| 91国产丝袜白虎| 欧美视频一| 国产18精品亚洲精品| 日韩性色b| 日韩人妻丝袜美腿中文| 天天影视亚洲| 色官网色综合| 久久99国产综合精品女同| 日韩久草| 大肥女高潮bbwbbwhd视频| 欧美黄片欧美黄片xxx| 精品国产嫩穴视频| 国产欧美日产一区二区三区 - 国产欧美日| 中文久久久| 黄在线| 欧美日韩淫加| 偷偷人人精品女女久久| 国产精品国产自产高清AV| 91人妻爽爽人人做人人澡| 亚洲男人天堂2013| 2024黄色视频| 五月综合色| 久久骚| 国产又黄又爽又刺激久久久久久 | 亚洲开心网| 日本在线视频导航| 大香网伊人久久综合网eew| 天天操天天舔| 自拍偷拍2025在线观看| 欧美亚洲美少妇一区二区| 欧美AB在线| 99操逼| 超碰综合97在线| 亚洲伊人a线观看视频| 极品白嫩福利在线| 96久久久久久久| 日本亚洲熟女视频| 色www精品视频在线观看| a片在线播放| 日韩在线女优天天干| 日韩十八禁| 丁香五月性| 色综九九九一区| 1禁看欧美黄片免费看| 日本一天色道久久久精品视频| 色婷婷国产精品一区在线观看| 久草五月| 久久线上视频免费看| 欧洲熟妇xxXx欧美老妇裸体| 日韩不卡一二三四| 亚洲1区2区三区高清中文字幕| 久久色一区二区| 日本人妻中文字幕精品| 亚洲色图 欧美热图 清纯唯美 另类自拍 | 五月天欧美色图| 操B在线观看| 欧美最大综合网| 99久久精品无码一区二区| 国产一区二区三区久久精品太古里| 天天做天天爱夜夜爽毛片试看| 久久久9品一区二区三区| 9久精品| 婷婷伊人一区| 婷婷av在线中文字幕| 欧美在线啊啊啊 | 玖玖爱综合| 五月天久久综合网| 日韩啪啪啪视频| 久操com| 亚洲综合色在线| 亚洲欧美经典一区二区| 91精品国产91熟女| 成人五月香网在线| 91欧洲国产成人久久精品网站| 久久一区无码| 澳门黄片一香蕉视频| 97欧美色资源| 热99这里只有精品| 狠狠入| 亚州操操穴网| av天堂精品久久| 欧美黑人日韩少妇色情| www超碰| 久久永久无码人妻视频| 欧美精品偷拍| 大香蕉一线视频| 伊香蕉综合久久久久久久噜噜噜| 中文字暮97| 国产精品日韩在线一区| 91少妇通奸网站| 国内外色色色色色成人视频| 激情综合网亚洲| 欧美亚洲国产日本在线,久久精品国产| 成人乱码一区二区三少妇| 国产精品久久久亚洲第一牛牛_在线观看| 91美女丝袜诱惑视频| 韩美日操逼| 欧美人妻一区二区| 欧美制服另类丝袜| 人人操人人搞人人草| 九九九九精品视频| 亚洲 欧美 小说| 国产久久久久久久久一区二区| 91天天| 青青草原成人| 天天综和| 亚洲国产一区二区三区四区国产| 屁股久久久久久| 一区二区视频你懂的| 丁香五月成人| 三级特黄60分钟播放| 超碰在线免费一区二区三区| 亚洲自拍欧美国产首页网曝| 韩国一级婬片A片AAAAA| 欧美区亚洲区偷拍区| 91精品国产91久久久久久久久久久久| 91九九九馒头| 激情看片网站| 性色一线| 精品人妻av在线播放| 成人怡红院| 久久网亚洲| 成人日韩中文字幕| 97在线精品| 欧美极品性爱天天射| 91情色| 欧美日韩小说| 成人精品欧洲亚洲| 精品久久久久黄少妇| 亚洲黄色影视| 美女写真| 内射老妇BBWX0C0CK| 91第一页| 久久婷婷苹果| 亚洲天堂资源| 偷拍超碰| 麻豆区99999| 天天做天天爽| 精品区国产区一区二区三区| 男女做爰猛烈动高潮A片免费应用 少妇厨房愉情理伦片bd在线观看 不卡中文字幕aⅴ在线 | 亚洲小说视频| 97操综合| 亚洲色丰满少妇高潮| 人妻出轨一区二区三区| 大奶啊啊好爽| 久久婷婷五月天| 新版天堂中文资源8在线| 九九干| 又粗又长又爽在线观看| 国产精品日本无码A片| 黑人综合网| 欧美日韩精品久久久久久久久东北老熟妇| 99re6国产精品99re| 欧美亚洲涩涩| 蜜臀亚洲综合一二三四区| 色婷婷综合久久中文字幕雪峰| 国产suv精品一区二区四| 日韩三级视频一区二区三区| 97在线精品| 五月天激情国产综合婷婷婷| 日本岛国黄色网址| 亚洲精品日韩国产欧美| 最新日韩黄片| 久久久夜夜嗨免费视频| 日日碰狠狠添天天爽超| 亚洲图片欧洲图片aⅴ| 一本一道vs波多野结衣| 久久九九视频九九视频| blacked精品一区国产| 日韩精品99999| 午夜经典| 久久久久久久91| 国产路线专区| 国产精品美女| 国产无码久久高清| 欧美性爱第一页久久| 欧美区亚洲区偷拍区| ,成人免费啪啪视频| 国产AV色黄看到爽|