中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

住建部網(wǎng)站2015年城市建設統(tǒng)計seo優(yōu)化的優(yōu)點

住建部網(wǎng)站2015年城市建設統(tǒng)計,seo優(yōu)化的優(yōu)點,重慶信息門戶網(wǎng)站,iis網(wǎng)站數(shù)據(jù)庫失敗在前面的文章中,我們分析了 tomcat 類加載器的相關源碼,也了解了 tomcat 支持類的熱加載,意味著 tomcat 要涉及類的重復卸裝/裝載過程,這個過程是很敏感的,一旦處理不當,可能會引起內(nèi)存泄露 卸載類 我們知…

在前面的文章中,我們分析了 tomcat 類加載器的相關源碼,也了解了 tomcat 支持類的熱加載,意味著 tomcat 要涉及類的重復卸裝/裝載過程,這個過程是很敏感的,一旦處理不當,可能會引起內(nèi)存泄露

卸載類

我們知道,class 信息存放在元數(shù)據(jù)區(qū)(1.7是 Perm 區(qū)),這一塊的內(nèi)存相比堆而言,只占據(jù)非常小的空間,但是如果處理不當,還是有可能會導致內(nèi)存溢出。這讓我回想起幾年前的一個故障,線上環(huán)境啟用了 tomcat 的自動 reload 功能,出現(xiàn)過?java.lang.OutOfMemoryError: PermGen space?問題,排查的結(jié)果是因為 tomcat 在自動重載應用的時候,沒有正常卸載類,導致 Perm 區(qū)內(nèi)存沒能被釋放而發(fā)生溢出。tomcat 會盡量避免這類問題的發(fā)生,但是不能百分之百保證不會出現(xiàn),所以還是建議不要隨意開啟?reloadable?功能

卸載類的條件很苛刻,必須同時滿足以下3點:
1、 該類所有的實例已經(jīng)被回收
2、 加載該類的?ClassLoder?已經(jīng)被回收
3、 該類對應的?java.lang.Class?對象沒有任何地方被引用

針對第1點,保證所有的實例被回收,這點不難,tomcat 在 Context 組件中實例化這些對象,持有直接或間接的引用,所以在熱部署的時候,只要回收 Context 組件即可保證實例對象被回收。

在前面的文章中我們分析了 tomcat 類加載器,tomcat 使用?ParallelWebappClassLoader?加載 Class,在熱部署的時候自然也會回收該類加載器。但是要注意的是,ParallelWebappClassLoader?會作為線程上下文的類加載器,因此要避免該類加載器對象在其他地方被引用。其實,這個問題是最隱晦的,jdk 中有些類會持有線程上下文的類加載器,作為一個優(yōu)秀的開源產(chǎn)品,tomcat 為我們解決了很多諸如此類的問題

此外,還要保證類對應的?java.lang.Class?對象沒有任何地方引用,只要 Class 對象作用域限制在?Context?組件的作用范圍便不會發(fā)生泄露,tomcat 也是這么做了,使用?Context?實現(xiàn)了隔離機制

熱加載問題

熱加載會面臨很多問題,有很多坑,需要非常豐富的經(jīng)驗。下面針對 tomcat 中涉及的類加載器泄露、對象泄露、文件鎖等這幾類常見的問題加以分析討論。如果您對熱加載感興趣的話,可以研究下阿里開源的?jarlinks

文件鎖

在 Windows 系統(tǒng)下使用?URLConnection?讀取本地 jar 包的資源時,它會將資源緩存起來,會導致該 jar 包資源被鎖。如果這個時候使用 war 包進行重新部署,需要解壓 war 包再把原來目錄下面的 jar 包刪除,由于 jar 包資源被鎖,導致刪除失敗,重新部署自然也會失敗。我們先來看一段代碼,這段代碼會拋出異常,java.nio.file.FileSystemException: E:\spring-boot-2.0.1.RELEASE.jar: 另一個程序正在使用此文件,進程無法訪問,說明該 jar 包被鎖了

String path = "E://spring-boot-2.0.1.RELEASE.jar";
File file = new File( path );
URL url = file.toURI().toURL();URLConnection uConn = url.openConnection();
uConn.getLastModified();    // 讀取jar包信息

為了解決文件鎖的問題,tomcat 禁用了?URLConnection?的緩存,是在?JreMemoryLeakPreventionListener?中完成的,關鍵代碼如下所示:

// dummy.jar 不存在也沒有關系
URL url = new URL("jar:file://dummy.jar!/");
URLConnection uConn = url.openConnection();

可能有些童鞋會有疑問,tomcat 只是針對該?URLConnection?對象禁用了緩存,而其它的?URLConnection?資源緩存未必被禁用啊。答案是肯定的,因為?URLConnection?的?defaultUseCaches?屬性是靜態(tài)變量

類加載器泄露

其中一種 JRE 內(nèi)存泄露是因為上下文類加載器導致的內(nèi)存泄露。某些 JRE 庫以單例的形式存在,它的生命周期很長甚至會貫穿于整個 java 程序,它們會使用上下文類加載器加載類,并且保留了類加載器的引用,所以會導致被引用的類加載器無法被回收,而 tomcat 重加載 webapp 是創(chuàng)建一個新的類加載器來實現(xiàn)的,舊的類加載器無法被 gc 回收,致使其加載的 Class 也無法被回收,導致內(nèi)存泄露。

DriverManager?就是典型的例子,它利用 jdk 提供的 SPI 機制加載?java.sql.Driver?驅(qū)動,而 jdk 提供的 SPI 機制便是使用上下文類加載器加載 Class 的,如果這類 jdbc 驅(qū)動由?ParallelWebappClassLoader?類加載器加載的話,就會導致該?ClassLoder?無法被回收,自然會出現(xiàn)內(nèi)存泄露

我們來看看 tomcat 是怎么解決的?tomcat 是利用?LifecycleListener?處理?before_init?事件,將上下文類加載器置為系統(tǒng)類加載器,并且完成驅(qū)動的加載過程,最后,為了不影響其它的類加載,再將上下文類加載器重置為?ParallelWebappClassLoader

另外一種 JRE 內(nèi)存泄露是因為當前線程會啟動另外一個線程,這個時候新線程會引用當前線程的上下文類加載器,如果新線程無止盡地運行,那么上下文類加載器就會一直被引用,而無法被回收,導致內(nèi)存泄露。sun.awt.AppContext.getAppContext()?便是典型的例子,它會在內(nèi)部開啟一個?AWT-AppKit?線程,直到圖形化環(huán)境準備就緒,例如?ImageIO.getCacheDirectory()、java.awt.Toolkit.getDefaultToolkit()

針對這種情況,解決思路也是一樣的,只需要將當前上下文類加載器指定為系統(tǒng)類加載器即可,關鍵代碼如下所示:

JreMemoryLeakPreventionListener.java@Override
public void lifecycleEvent(LifecycleEvent event) {if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {ClassLoader loader = Thread.currentThread().getContextClassLoader();try {// 當線程上下文類加載器指定為系統(tǒng)類加載器Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());if (driverManagerProtection) {DriverManager.getDrivers();}// 避免開啟的子線程持有 ParallelWebappClassLoader 引用if (appContextProtection && !JreCompat.isJre8Available()) {ImageIO.getCacheDirectory();}if (awtThreadProtection && !JreCompat.isJre9Available()) {java.awt.Toolkit.getDefaultToolkit();}// 避免持有 ParallelWebappClassLoader 引用if (tokenPollerProtection && !JreCompat.isJre9Available()) {java.security.Security.getProviders();}// 忽略若干代碼......} finally {// 再重置為 ParallelWebappClassLoader,避免影響其它的類的加載Thread.currentThread().setContextClassLoader(loader);}}

ThreadLocal 對象泄露

還有一種內(nèi)存泄露是由于?ThreadLocal?引起的,假如我們在?ThreadLocal?中保存了對象A,而且對象A由?ParallelWebappClassLoader?加載,那么就可以看成線程引用了對象A。由于 tomcat 中處理請求的是線程池,意味著該線程會存活很長一段時間。webapp 熱加載時,會重新實例化一個?ParallelWebappClassLoader?對象,如果線程未銷毀,那么舊的?ParallelWebappClassLoader?也無法被回收,導致內(nèi)存泄露。

解決?ThreadLocal?內(nèi)存泄露最好的辦法,自然是把線程池中的所有的線程銷毀并重新創(chuàng)建。這個過程分為兩步,第一步是將任務隊列堵住,不讓新的任務進來,第二步是將線程池中所有線程停止。

tomcat 解決該 ThreadLocal 對象泄露問題,也是借助了?Lifecycle?完成的,具體的實現(xiàn)類是?ThreadLocalLeakPreventionListener,它會處理?Lifecycle.AFTER_STOP_EVENT?事件,并且銷毀線程池內(nèi)的空閑線程,關鍵代碼如下所示:

http://www.risenshineclean.com/news/62304.html

相關文章:

  • 奉賢區(qū)網(wǎng)站建設收錄網(wǎng)站排名
  • 福田祥菱q雙排小貨車報價及圖片廈門seo推廣外包
  • 天津自己制作網(wǎng)站網(wǎng)站新站整站排名
  • 網(wǎng)站開發(fā)網(wǎng)頁設計游戲代理加盟平臺
  • seo兼職論壇手機優(yōu)化大師官網(wǎng)
  • 怎么快速推廣網(wǎng)站萬網(wǎng)域名交易
  • 建行信用卡網(wǎng)站登錄網(wǎng)站域名查詢系統(tǒng)
  • 那個網(wǎng)站做外貿(mào)好百度大搜是什么
  • dw做的網(wǎng)站鏈接不會跳轉(zhuǎn)什么是搜索引擎優(yōu)化
  • 做期貨網(wǎng)站微營銷平臺系統(tǒng)
  • 西寧網(wǎng)站設計制作公司品牌推廣軟文200字
  • 只做襯衫的網(wǎng)站關鍵詞采集軟件
  • 沈陽網(wǎng)站建設找哪家系統(tǒng)優(yōu)化軟件哪個好
  • 企業(yè)網(wǎng)站建設方案書范本域名批量查詢
  • 網(wǎng)站 續(xù)費商業(yè)策劃公司十大公司
  • 網(wǎng)站后端都需要什么意思網(wǎng)站交換鏈接的常見形式
  • 企業(yè)展示型電商網(wǎng)站模板google關鍵詞規(guī)劃師
  • php和什么語言做網(wǎng)站豬肉價格最新消息
  • 在越南做網(wǎng)站需要什么排超聯(lián)賽積分榜
  • 工業(yè)做網(wǎng)站技能培訓有哪些科目
  • 大連城市建設管理局網(wǎng)站建站公司網(wǎng)站建設
  • 自己的網(wǎng)站首頁背景怎么做最有效的宣傳方式
  • 義烏做網(wǎng)站的公司哪家好廣州seo外包
  • 桂林做網(wǎng)站網(wǎng)絡營銷推廣方案范文
  • 完備的網(wǎng)站建設推廣做網(wǎng)站推廣一般多少錢
  • 長沙小升初有什么做試卷的網(wǎng)站濟南網(wǎng)站優(yōu)化排名推廣
  • 北京做網(wǎng)站公司有哪些百度怎么優(yōu)化網(wǎng)站關鍵詞
  • ssm如何做網(wǎng)站驗證登陸綜合型b2b電子商務平臺網(wǎng)站
  • 如何在網(wǎng)上接做網(wǎng)站的小項目抖音seo
  • 建設導航網(wǎng)站百度投訴電話人工服務總部