日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
Tomcat深入解析與性能優(yōu)化

                                                                                                                       

我們提供的服務有:成都網站設計、成都網站建設、外貿網站建設、微信公眾號開發(fā)、網站優(yōu)化、網站認證、陽曲ssl等。為上千余家企事業(yè)單位解決了網站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術的陽曲網站制作公司

 Java 2019 年生態(tài)圈使用報告

2020 Java 生態(tài)系統(tǒng)報告

從軟件架構的發(fā)展角度來看,軟件架構大致經歷了如下幾個階段:

從 Java Web 角度來說,架構大致經歷了:

從當前企業(yè)使用的架構角度來說,使用SSM架構項目比較多,SSH基本被淘汰(大部分是老項目維護),很大一部分企業(yè)轉向微服務架構了。

基于Spring 生態(tài)來說,大部分中小型企業(yè)都基本使用SpringBoot,SpringBoot本身集成了 tomcat、jetty和undertwo 容器,那么我們?yōu)槭裁葱枰〞r間來研究tomcat呢?

  1. 當前tomcat依然是主流java web容器,研究它符合java 技術生態(tài)發(fā)展;
  2. 在java web項目調優(yōu)中,如ssm項目中,在優(yōu)化項目時,jvm和tomcat同樣重要,都需要優(yōu)化;
  3. 盡管springboot內置了tomcat容器,且配置了默認的tomcat參數(shù),但當默認的tomcat參數(shù)滿足不了項目優(yōu)化要求時,就需要優(yōu)化人員手動進行相關的參數(shù)優(yōu)化,因此研究tomcat非常必要;
  4. 熟悉tomcat架構,是后續(xù)進行項目優(yōu)化的基礎,也是必備條件。

Tomcat架構說明
知識點:

  1. Tomcat目錄結構
  2. Tomcat簡要架構
  3. Tomcat各組件及關系
  4. Tomcat server.xml配置詳解
  5. Tomcat啟動參數(shù)說明(啟動腳本)

Tomcat 是一個基于JAVA的WEB容器,其實現(xiàn)了JAVA EE中的 Servlet 與 jsp 規(guī)范,與Nginx Apache 服務器不同在于一般用于動態(tài)請求處理。在架構設計上采用面向組件的方式設計。即整體功能是通過組件的方式拼裝完成。另外每個組件都可以被替換以保證靈活性。

通過Tomcat官方可以看到,目前已經更新到Tomcat 10了,但當前大部分企業(yè)使用的Tomcat 為8或者9版本

Tomcat 目錄結構

  • bin:可執(zhí)行文件,.sh結尾的表示linux可執(zhí)行文件,.bat結尾的表示windows可執(zhí)行文件
  • conf:配置文件
  • lib:tomcat相關jar包
  • temp:臨時文件
  • webapps:存放項目
  • work:工作目錄

bin目錄

bin目錄存放可執(zhí)行文件,簡要結束常用命令

這里主要解釋如下通用的命令,其他命令就不一一介紹

  • catalina.sh 真正啟動Tomcat文件,可以在里面設置jvm參數(shù)
  • startup.sh 程序項目命令文件
  • version.sh 查看tomcat版本相關信息命令文件
  • shutdown.sh 關閉程序命令

conf目錄

conf文件夾用來存放tomcat相關配置文件

1.catalina.policy

項目安全文件,用來防止欺騙代碼或JSP執(zhí)行帶有像System.exit(0)這樣的命令的可能影響容器的破壞性代碼. 只有當Tomcat用-security命令行參數(shù)啟動時這個文件才會被使用,即啟動tomcat時, startup.sh -security 。

上圖中,tomcat容器下部署兩個項目,項目1和項目2。由于項目1中有代碼System.exit(0),當訪問該代碼時,該代碼會導致整個tomcat停止,從而也導致項目2停止。

為了解決因項目1存在欺騙代碼或不安全代碼導致?lián)p害Tomcat容器,從而影響其他項目正常運行的問題,啟動tomcat容器時,加上-security參數(shù)就,即startup.sh -security,如此即使項目1中有代碼System.exit(0),也只會僅僅停止項目1,而不會影響Tomcat容器,然而起作用的配置文件就是catalina.policy文件。

2.catalina.properties

配置tomcat啟動相關信息文件

3.context.xml

監(jiān)視并加載資源文件,當監(jiān)視的文件發(fā)生發(fā)生變化時,自動加載

4.jaspic-providers.xml 和 jaspic-providers.xsd

這兩個文件不常用

5.logging.properties

該文件為tomcat日志文件,包括配置tomcat輸出格式,日志級別等

6.server.xml

tomcat核心架構主件文件,下面會詳細解析。

7.tomcat-users.xml和tomcat-users.xsd

tomcat用戶文件,如配置遠程登陸賬號

tomcat-users.xsd 為tomcat-users.xml描述和約束文件

8.web.xml

tomcat全局配置文件。

lib目錄

lib文件夾主要用來存放tomcat依賴jar包,如下為 tomcat 的lib文件夾下的相關jar包。

每個jar包功能,這里就不講解了,這里主要分析ecj-4.13.jar,這個jar包起到將.java編譯成.class字節(jié)碼作用。

假設要編譯MyTest.java,那么jdk會執(zhí)行兩步:

  • 第一步:將MyTest.java編譯成MyTest.class

javac MyTest.java

  • 第二步:執(zhí)行MyTest.class

java MyTest.class

  • 那么,使用ecj-4.13.jar如執(zhí)行MyTest.java呢?

java -jar ecj-4.13.jar MyTest.java

logs目錄

該文件夾表示tomcat日志文件,大致包括如下六類文件:

temp目錄

temp目錄用戶存放tomcat在運行過程中產生的臨時文件。(清空不會對tomcat運行帶來影響)。

webapps目錄

webapps目錄用來存放應用程序,當tomcat啟動時會去加載webapps目錄下的應用程序??梢砸晕募A、war包、jar包的形式發(fā)布應用。

當然,你也可以把應用程序放置在磁盤的任意位置,在配置文件中映射好就行。

work目錄

work目錄用來存放tomcat在運行時的編譯后文件,例如JSP編譯后的文件。

清空work目錄,然后重啟tomcat,可以達到清除緩存的作用。

Tomcat 簡要架構

Tomcat 各組件及關系

  • Server 和 Service
  • Connector 連接器
  • HTTP 1.1
  • SSL https
  • AJP( Apache JServ Protocol) apache 私有協(xié)議,用于apache 反向代理Tomcat
  • Container
  • Engine 引擎 catalina
  • Host 虛擬機 基于域名 分發(fā)請求
  • Context 隔離各個WEB應用 每個Context的 ClassLoader都是獨立
  • Component
  • Manager (管理器)
  • logger (日志管理)
  • loader (載入器)
  • pipeline (管道)
  • valve (管道中的閥)

Tomcat server.xml 配置詳解
Server 的基本基本配置:

 
 
 
 
  1.  
  2.      
  3.       
  4.     
  5.                
  6.           
  7.           
  8.           
  9.                        
  10.              
  11.              
  12.                   
  13.                      
  14.                      
  15.                 
  16.          
  17.      
  18.  

server
root元素:server 的頂級配置

主要屬性:

port:執(zhí)行關閉命令的端口號

shutdown:關閉命令

  • 演示shutdown的用法
 
 
 
 
  1. #基于telent 執(zhí)行SHUTDOWN 命令即可關閉 
  2. telent 127.0.0.1 8005 
  3. SHUTDOWN 

service

服務:將多個connector 與一個Engine組合成一個服務,可以配置多個服務。

Connector

連接器:用于接收 指定協(xié)議下的連接 并指定給唯一的Engine 進行處理。

主要屬性:

  • protocol 監(jiān)聽的協(xié)議,默認是http/1.1
  • port 指定服務器端要創(chuàng)建的端口號
  • minThread 服務器啟動時創(chuàng)建的處理請求的線程數(shù)
  • maxThread 最大可以創(chuàng)建的處理請求的線程數(shù)
  • enableLookups 如果為true,則可以通過調用request.getRemoteHost()進行DNS查詢來得到遠程客戶端的實際主機名,若為false則不進行DNS查詢,而是返回其ip地址
  • redirectPort 指定服務器正在處理http請求時收到了一個SSL傳輸請求后重定向的端口號
  • acceptCount 指定當所有可以使用的處理請求的線程數(shù)都被使用時,可以放到處理隊列中的請求數(shù),超過這個數(shù)的請求將不予處理,默認100;
  • address 綁定客戶端特定地址,127.0.0.1
  • bufferSize 每個請求的緩沖區(qū)大小 bufferSize * maxThreads
  • compression 是否啟用文檔壓縮
  • compressionMinSize 文檔壓縮的最小大小
  • compressableMimeTypes text/html,text/xml,text/plain
  • connectionTimeout 客戶端發(fā)起鏈接到服務端接收為止,指定超時的時間數(shù)(以毫秒為單位)
  • connectionUploadTimeout upload情況下連接超時時間
  • disableUploadTimeout 如果為true則使用 connectionTimeout
  • keepAliveTimeout 當長鏈接閑置 指定時間主動關閉 鏈接 ,前提是客戶端請求頭 帶上這個 head"connection" " keep-alive"
  • maxKeepAliveRequests 最大的 長連接數(shù) 默認最大100
  • maxSpareThreads BIO 模式下 最多線閑置線程數(shù)
  • minSpareThreads BIO 模式下 最小線閑置線程數(shù)
  • SSLEnabled 是否開啟 sll 驗證,在Https 訪問時需要開啟。
  • 演示配置多個Connector
 
 
 
 
  1.  
  2.                 connectionTimeout="20000" 
  3.                 redirectPort="8862" 
  4.                 URIEncoding="UTF-8" 
  5.                 useBodyEncodingForURI="true" 
  6.                 compression="on" compressionMinSize="2048" 
  7. compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript" 
  8.                 maxThreads="1024" minSpareThreads="200" 
  9.                 acceptCount="800" 
  10.                 enableLookups="false" 
  11.         /> 

Engine

引擎:用于處理連接的執(zhí)行器,默認的引擎是catalina。一個service 中只能配置一個Engine。

主要屬性:name 引擎名稱 defaultHost 默認host

Host
虛擬機:基于域名匹配至指定虛擬機。類似于nginx 當中的server,默認的虛擬機是localhost.

演示配置多個Host

 
 
 
 
  1.             unpackWARs="true" autoDeploy="true"> 
  2.         
  3.                pattern="%h %l %u %t "%r" %s %b" /> 
  4.  

Context

應用上下文:一個host 下可以配置多個Context ,每個Context 都有其獨立的classPath。相互隔離,以免造成ClassPath 沖突。

  • 演示配置多個Context
 
 
 
 
  1.  

Valve

閥門:可以理解成request 的過濾器,具體配置要基于具體的Valve 接口的子類。以下即為一個訪問日志的Valve.

 
 
 
 
  1.               prefix="www.luban.com.access_log" suffix=".txt" 
  2.               pattern="%h %l %u %t "%r" %s %b" /> 

Tomcat啟動參數(shù)說明

我們平時啟動Tomcat過程是怎么樣的?

  1. 復制WAR包至Tomcat webapp 目錄。
  2. 執(zhí)行starut.bat 腳本啟動。
  3. 啟動過程中war 包會被自動解壓裝載。

但是我們在Eclipse 或idea 中啟動WEB項目的時候 也是把War包復雜至webapps 目錄解壓嗎?顯然不是,其真正做法是在Tomcat程序文件之外創(chuàng)建了一個部署目錄,在一般生產環(huán)境中也是這么做的 即:Tomcat 程序目錄和部署目錄分開 。

我們只需要在啟動時指定CATALINA_HOME 與 CATALINA_BASE 參數(shù)即可實現(xiàn)。

可以編寫一個腳本 來實現(xiàn)自定義配置:

更新 啟動 腳本:

 
 
 
 
  1. #!/bin/bash -e 
  2. export now_time=$(date +%Y-%m-%d_%H-%M-%S)echo "deploy time:$now_time"app=$1version=$2mkdir -p war/#從svn下載程序至 war目錄war=war/${app}_${version}.warecho "$war"svn export svn://192.168.0.253/release/${app}_${version}.war $wardeploy_war() {#解壓版本至當前目錄target_dir=war/${app}_${version}_${now_time}unzip -q $war -d $target_dirrm -f appwarln -sf $target_dir appwartarget_ln=`pwd`/appwarecho ' 
  3.  
  4. ' > conf/Catalina/localhost/ROOT.xml 
  5. #重啟Tomcat服務./tomcat.sh restart}deploy_war``` 

自動部署腳本:

 
 
 
 
  1. #!/bin/bash -e 
  2. export now_time=$(date +%Y-%m-%d_%H-%M-%S)echo "deploy time:$now_time"app=$1version=$2mkdir -p war/#從svn下載程序至 war目錄war=war/${app}_${version}.warecho "$war"svn export svn://192.168.0.253/release/${app}_${version}.war $wardeploy_war() {#解壓版本至當前目錄target_dir=war/${app}_${version}_${now_time}unzip -q $war -d $target_dirrm -f appwarln -sf $target_dir appwartarget_ln=`pwd`/appwarecho ' 
  3.  
  4. ' > conf/Catalina/localhost/ROOT.xml 
  5. #重啟Tomcat服務./tomcat.sh restart}deploy_war``` 

Tomcat 網絡通信模型剖析
Tomcat 支持四種線程模型介紹

什么是IO?
IO是指為數(shù)據(jù)傳輸所提供的輸入輸出流,其輸入輸出對象可以是:文件、網絡服務、內存等。

什么是IO模型?

提問:

假設應用在從硬盤中讀取一個大文件過程中,此時CPU會與硬盤一樣處于高負荷狀態(tài)么?

演示:

  • 演示觀察大文件的讀寫過程當中CPU 有沒有發(fā)生大波動。

演示結果:CPU 沒有太高的增長

通常情況下IO操作是比較耗時的,所以為了高效的使用硬件,應用程序可以用一個專門線程進行IO操作,而另外一個線程則利用CPU的空閑去做其它計算。這種為提高應用執(zhí)行效率而采用的IO操作方法即為IO模型。

各IO模型簡要說明
BIO

阻塞式IO,即Tomcat使用傳統(tǒng)的java.io進行操作。該模式下每個請求都會創(chuàng)建一個線程,對性能開銷大,不適合高并發(fā)場景。優(yōu)點是穩(wěn)定,適合連接數(shù)目小且固定架構。

NIO

非阻塞式IO,jdk1.4 之后實現(xiàn)的新IO。該模式基于多路復用選擇器監(jiān)測連接狀態(tài)在通知線程處理,從而達到非阻塞的目的。比傳統(tǒng)BIO能更好的支持并發(fā)性能。Tomcat 8.0之后默認采用該模式

APR

全稱是 Apache Portable Runtime/Apache可移植運行庫),是Apache HTTP服務器的支持庫。可以簡單地理解為,Tomcat將以JNI的形式調用Apache HTTP服務器的核心動態(tài)鏈接庫來處理文件讀取或網絡傳輸操作。使用需要編譯安裝APR 庫

AIO

異步非阻塞式IO,jdk1.7后之支持 。與nio不同在于不需要多路復用選擇器,而是請求處理線程執(zhí)行完成進行回調調制,已繼續(xù)執(zhí)行后續(xù)操作。Tomcat 8之后支持。

使用指定IO模型的配置方式:

配置 server.xml 文件當中的 修改即可。

默認配置 8.0 protocol=“HTTP/1.1” 8.0 之前是 BIO, 8.0 之后是 NIO

BIO
protocol=“org.apache.coyote.http11.Http11Protocol”

NIO
protocol=“org.apache.coyote.http11.Http11NioProtocol”

AIO
protocol=“org.apache.coyote.http11.Http11Nio2Protocol”

APR
protocol=“org.apache.coyote.http11.Http11AprProtocol”

Tomcat BIO、NIO實現(xiàn)過程源碼解析

BIO 與NIO區(qū)別
分別演示在高并發(fā)場景下BIO與NIO的線程數(shù)的變化?

BIO 配置

 
 
 
 
  1.                connectionTimeout="20000" 
  2.                redirectPort="8443" 
  3.                compression="on" compressionMinSize="1024" 
  4.                compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript" 
  5.                maxThreads="500" minSpareThreads="1"/> 

NIO配置

 
 
 
 
  1.               connectionTimeout="20000" 
  2.               redirectPort="8443" 
  3.               compression="on" compressionMinSize="1024" 
  4.               compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript" 
  5.               maxThreads="500" minSpareThreads="1"/> 

演示數(shù)據(jù):

生成環(huán)境重要因素:

  1. 網絡
  2. 程序執(zhí)行業(yè)務用時

源代碼地址:https://github.com/org-hejianhui/bit-bigdata-transmission

BIO 線程模型

BIO 源碼

線程組:

Accept 線程組 acceptorThreadCount 默認1個

exec 線程組 maxThread

JIoEndpoint

Acceptor extends Runnable

SocketProcessor extends Runnable

NIO 線程模型

NIO 線程模型

Accept 線程組 默認兩個輪詢器

Poller Selector PollerEvent輪詢線程狀態(tài)

SocketProcessor

BIO

線程數(shù)量 會受到 客戶端阻塞、網絡延遲、業(yè)務處理慢===>線程數(shù)會更多。

NIO

線程數(shù)量 會受到業(yè)務處理慢===>線程數(shù)會更多。

Tomcat connector 并發(fā)參數(shù)解讀

Tomcat 類加載機制源碼解析

類加載的本質

是用來加載 Class 的。它負責將 Class 的字節(jié)碼形式轉換成內存形式的 Class 對象。字節(jié)碼可以來自于磁盤文件 .class,也可以是 jar 包里的 .class,也可以來自遠程服務器提供的字節(jié)流,字節(jié)碼的本質就是一個字節(jié)數(shù)組 []byte,它有特定的復雜的內部格式。

JVM 運行實例中會存在多個 ClassLoader,不同的 ClassLoader 會從不同的地方加載字節(jié)碼文件。它可以從不同的文件目錄加載,也可以從不同的 jar 文件中加載,也可以從網絡上不同的靜態(tài)文件服務器來下載字節(jié)碼再加載。

jvm里ClassLoader的層次結構

類加載器層次結構

BootstrapClassLoader(啟動類加載器)

稱為啟動類加載器,是Java類加載層次中最頂層的類加載器,負責加載JDK中的核心類庫,如:rt.jar、resources.jar、charsets.jar等,可通過如下程序獲得該類加載器從哪些地方加載了相關的jar或class文件:

 
 
 
 
  1. URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs(); 
  2. for (URL url : urLs) { 
  3.     System.out.println(url.toExternalForm()); 

程序執(zhí)行結果如下:

 
 
 
 
  1. file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/resources.jar 
  2. file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/rt.jar 
  3. file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/sunrsasign.jar 
  4. file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jsse.jar 
  5. file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jce.jar 
  6. file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/charsets.jar 
  7. file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jfr.jar 
  8. file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/classes 

從rt.jar中選擇String類,看一下String類的類加載器是什么

 
 
 
 
  1. ClassLoader classLoader = String.class.getClassLoader(); 
  2. System.out.println(classLoader); 

執(zhí)行結果如下:

 
 
 
 
  1. null 

可知由于BootstrapClassLoader對Java不可見,所以返回了null,我們也可以通過某一個類的加載器是否為null來作為判斷該類是不是使用BootstrapClassLoader進行加載的依據(jù)。

ExtensionClassLoader

ExtClassLoader稱為擴展類加載器,主要負責加載Java的擴展類庫,默認加載JAVA_HOME/jre/lib/ext/目錄下的所有jar包或者由java.ext.dirs系統(tǒng)屬性指定的jar包.放入這個目錄下的jar包對AppClassLoader加載器都是可見的(因為ExtClassLoader是AppClassLoader的父加載器,并且Java類加載器采用了委托機制)。

ExtClassLoader的類掃描路徑通過執(zhí)行下面代碼來看一下:

 
 
 
 
  1. String extDirs = System.getProperty("java.ext.dirs"); 
  2. for (String path : extDirs.split(";")) { 
  3. System.out.println(path);} 

執(zhí)行結果如下(Mac系統(tǒng)):

 
 
 
 
  1. /Users/hjh/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java 

jre/lib/ext路徑下內容為:

從上面的路徑中隨意選擇一個類,來看看它的類加載器是什么:

 
 
 
 
  1. sun.misc.Launcher$ExtClassLoader@4439f31e 
  2. null 

從上面的程序運行結果可知ExtClassLoader的父加載器為null,之前說過BootstrapClassLoader對Java不可見,所以返回了null。ExtClassLoader的父加載器返回的是null,那是否說明ExtClassLoader的父加載器是BootstrapClassLoader?

 
 
 
 
  1. Bootstrap ClassLoader是由C/C++編寫的,它本身是虛擬機的一部分,所以它并不是一個JAVA類,也就是無法在java代碼中獲取它的引用,JVM啟動時通過Bootstrap類加載器加載rt.jar等核心jar包中的class文件,之前的int.class,String.class都是由它加載。然后呢,我們前面已經分析了,JVM初始化sun.misc.Launcher并創(chuàng)建Extension ClassLoader和AppClassLoader實例。并將ExtClassLoader設置為AppClassLoader的父加載器。Bootstrap沒有父加載器,但是它卻可以作用一個ClassLoader的父加載器。比如ExtClassLoader。這也可以解釋之前通過ExtClassLoader的getParent方法獲取為Null的現(xiàn)象 

AppClassLoader

才是直接面向我們用戶的加載器,它會加載 Classpath 環(huán)境變量里定義的路徑中的 jar 包和目錄。我們自己編寫的代碼以及使用的第三方 jar 包通常都是由它來加載的。

加載System.getProperty("java.class.path")所指定的路徑或jar。在使用Java運行程序時,也可以加上-cp來覆蓋原有的Classpath設置,例如: java -cp ./lavasoft/classes HelloWorld

 
 
 
 
  1. public class AppClassLoaderTest { 
  2.     public static void main(String[] args) { 
  3.         System.out.println(ClassLoader.getSystemClassLoader()); 
  4.     }} 

輸出結果如下:

 
 
 
 
  1. sun.misc.Launcher$AppClassLoader@18b4aac2 

以上結論說明調用ClassLoader.getSystemClassLoader()可以獲得AppClassLoader類加載器。

 
 
 
 
  1. protected ClassLoader() { 
  2.     this(checkCreateClassLoader(), getSystemClassLoader()); 

通過查看ClassLoader的源碼發(fā)現(xiàn)并且在沒有特定說明的情況下,用戶自定義的任何類加載器都將該類加載器作為自定義類加載器的父加載器。

通過執(zhí)行上面的代碼即可獲得classpath的加載路徑。

在上面的main函數(shù)的類的加載就是使用AppClassLoader加載器進行加載的,可以通過執(zhí)行下面的代碼得出這個結論

 
 
 
 
  1. public class AppClassLoaderTest { 
  2.     public static void main(String[] args) { 
  3.         ClassLoader classLoader = Test.class.getClassLoader(); 
  4.         System.out.println(classLoader);        System.out.println(classLoader.getParent());    }    private static class Test { 
  5.     }} 

執(zhí)行結果如下:

 
 
 
 
  1. sun.misc.Launcher$AppClassLoader@18b4aac2 
  2. sun.misc.Launcher$ExtClassLoader@2d209079 

從上面的運行結果可以得知AppClassLoader的父加載器是ExtClassLoader

Tomcat的 類加載順序

在Tomcat中,默認的行為是先嘗試在Bootstrap和Extension中進行類型加載,如果加載不到則在Webapp ClassLoader中進行加載,如果還是找不到則在Common中進行查找。

NoClassDefFoundError

NoClassDefFoundError是在開發(fā)JavaEE程序中常見的一種問題。該問題會隨著你所使用的JavaEE中間件環(huán)境的復雜度以及應用本身的體量變得更加復雜,尤其是現(xiàn)在的JavaEE服務器具有大量的類加載器。

在JavaDoc中對NoClassDefFoundError的產生是由于JVM或者類加載器實例嘗試加載類型的定義,但是該定義卻沒有找到,影響了執(zhí)行路徑。換句話說,在編譯時這個類是能夠被找到的,但是在執(zhí)行時卻沒有找到。

這一刻IDE是沒有出錯提醒的,但是在運行時卻出現(xiàn)了錯誤。

NoSuchMethodError

在另一個場景中,我們可能遇到了另一個錯誤,也就是NoSuchMethodError。

NoSuchMethodError代表這個類型確實存在,但是一個不正確的版本被加載了。

ClassCastException

ClassCastException,在一個類加載器的情況下,一般出現(xiàn)這種錯誤都會是在轉型操作時,比如:A a = (A) method();,很容易判斷出來method()方法返回的類型不是類型A,但是在 JavaEE 多個類加載器的環(huán)境下就會出現(xiàn)一些難以定位的情況。
 


網站欄目:Tomcat深入解析與性能優(yōu)化
網頁路徑:http://m.5511xx.com/article/ccdhopp.html