亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

Tomcat深入解析與性能優化

 

前言

 

在 JAVA 應用中,常用的 Web 服務器一般由 Tomcat、weblogic、jetty、undertwo等。但從 Java 2019和2020 生態使用報告可以看到,tomcat的用戶量對比明顯較大,當然這也基于它開源和免費的特點。

 

Java 2019 年生態圈使用報告

Tomcat深入解析與性能優化

 

2020 Java 生態系統報告

Tomcat深入解析與性能優化

 

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

Tomcat深入解析與性能優化

 

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

Tomcat深入解析與性能優化

 

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

 

基于Spring 生態來說,大部分中小型企業都基本使用SpringBoot,SpringBoot本身集成了 tomcat、jetty和undertwo 容器,那么我們為什么需要花時間來研究tomcat呢?

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

Tomcat架構說明


知識點:

 

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

 

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

Tomcat深入解析與性能優化

 

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

Tomcat深入解析與性能優化

 

Tomcat 目錄結構

Tomcat深入解析與性能優化

 

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

bin目錄

 

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

Tomcat深入解析與性能優化

 

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

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

 

conf目錄

 

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

Tomcat深入解析與性能優化

 

1.catalina.policy

 

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

Tomcat深入解析與性能優化

 

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

 

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

 

2.catalina.properties

 

配置tomcat啟動相關信息文件

 

3.context.xml

 

監視并加載資源文件,當監視的文件發生發生變化時,自動加載

Tomcat深入解析與性能優化

 

 

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包。

Tomcat深入解析與性能優化

 

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

 

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

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

javac MyTest.java

  • 第二步:執行MyTest.class

java MyTest.class

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

java -jar ecj-4.13.jar MyTest.java

 

logs目錄

 

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

Tomcat深入解析與性能優化

 


Tomcat深入解析與性能優化

 

temp目錄

 

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

 

webapps目錄

 

webapps目錄用來存放應用程序,當tomcat啟動時會去加載webapps目錄下的應用程序。可以以文件夾、war包、jar包的形式發布應用。

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

 

work目錄

 

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

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

 

Tomcat 簡要架構

 

Tomcat深入解析與性能優化

 

Tomcat 各組件及關系

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

 

Tomcat深入解析與性能優化

 

Tomcat server.xml 配置詳解


Server 的基本基本配置:

<Server>
    <Listener /><!-- 監聽器 -->
    <GlobaNamingResources> <!-- 全局資源 -->
    </GlobaNamingResources
    <Service>          <!-- 服務 用于 綁定 連接器與 Engine -->
        <Connector 8080/> <!-- 連接器-->
        <Connector 8010 /> <!-- 連接器-->
        <Connector 8030/> <!-- 連接器-->
        
        <Engine>      <!-- 執行引擎-->
            <Logger />
            <Realm />
               <host "www.test.com" appBase="">  <!-- 虛擬主機-->
                   <Logger /> <!-- 日志配置-->
                   <Context "/applction" path=""/> <!-- 上下文配置-->
               </host>
        </Engine>
    </Service>
</Server>

 

server

root元素:server 的頂級配置

主要屬性:

port:執行關閉命令的端口號

shutdown:關閉命令

 

  • 演示shutdown的用法
#基于telent 執行SHUTDOWN 命令即可關閉
telent 127.0.0.1 8005
SHUTDOWN

 

service

 

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

 

Connector

 

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

 

主要屬性:

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

 

  • 演示配置多個Connector
 <Connector port="8860" protocol="org.apache.coyote.http11.Http11NioProtocol"
                connectionTimeout="20000"
                redirectPort="8862"
                URIEncoding="UTF-8"
                useBodyEncodingForURI="true"
                compression="on" compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/JavaScript,text/css,application/x-json,application/json,application/x-javascript"
                maxThreads="1024" minSpareThreads="200"
                acceptCount="800"
                enableLookups="false"
        />

 

Engine

 

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

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

 

Host

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

  • 演示配置多個Host
<Host name="www.test.com"  appBase="/usr/www/test"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"               prefix="www.luban.com.access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />
</Host>

 

Context

 

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

 

  • 演示配置多個Context
<Context docBase="hello" path="/h" reloadable="true"/>

 

Valve

 

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

 

 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="www.luban.com.access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

 

Tomcat啟動參數說明

 

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

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

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

我們只需要在啟動時指定CATALINA_HOME 與 CATALINA_BASE 參數即可實現。

Tomcat深入解析與性能優化

 

可以編寫一個腳本 來實現自定義配置:

更新 啟動 腳本

#!/bin/bash -e
export now_time=$(date +%Y-%m-%d_%H-%M-%S)
echo "deploy time:$now_time"

app=$1
version=$2
mkdir -p war/
#從svn下載程序至 war目錄
war=war/${app}_${version}.war
echo "$war"
svn export svn://192.168.0.253/release/${app}_${version}.war $war

deploy_war() {
#解壓版本至當前目錄
target_dir=war/${app}_${version}_${now_time}
unzip -q $war -d $target_dir
rm -f appwar
ln -sf $target_dir appwar
target_ln=`pwd`/appwar
echo '<?xml version="1.0" encoding="UTF-8" ?>
<Context docBase="'$target_ln'" allowLinking="false">
</Context>' > conf/Catalina/localhost/ROOT.xml
#重啟Tomcat服務
./tomcat.sh restart
}

deploy_war
```

 

自動部署腳本

#!/bin/bash -e
export now_time=$(date +%Y-%m-%d_%H-%M-%S)
echo "deploy time:$now_time"

app=$1
version=$2
mkdir -p war/
#從svn下載程序至 war目錄
war=war/${app}_${version}.war
echo "$war"
svn export svn://192.168.0.253/release/${app}_${version}.war $war

deploy_war() {
#解壓版本至當前目錄
target_dir=war/${app}_${version}_${now_time}
unzip -q $war -d $target_dir
rm -f appwar
ln -sf $target_dir appwar
target_ln=`pwd`/appwar
echo '<?xml version="1.0" encoding="UTF-8" ?>
<Context docBase="'$target_ln'" allowLinking="false">
</Context>' > conf/Catalina/localhost/ROOT.xml
#重啟Tomcat服務
./tomcat.sh restart
}

deploy_war
```

 

Tomcat 網絡通信模型剖析


Tomcat 支持四種線程模型介紹

 

什么是IO?

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

Tomcat深入解析與性能優化

 

什么是IO模型?

 

提問:

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

 

演示:

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

 

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

 

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

 

各IO模型簡要說明

BIO

阻塞式IO,即Tomcat使用傳統的java.io進行操作。該模式下每個請求都會創建一個線程,對性能開銷大,不適合高并發場景。優點是穩定,適合連接數目小且固定架構。

NIO

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

APR

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

AIO

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

Tomcat深入解析與性能優化

 

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

 

配置 server.xml 文件當中的 <Connector protocol="HTTP/1.1"> 修改即可。

默認配置 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實現過程源碼解析

 

BIO 與NIO區別

分別演示在高并發場景下BIO與NIO的線程數的變化?

Tomcat深入解析與性能優化

 

BIO 配置

<Connector port="8080" protocol="org.apache.coyote.http11.Http11Protocol"
               connectionTimeout="20000"
               redirectPort="8443"
               compression="on" compressionMinSize="1024"
               compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript"
               maxThreads="500" minSpareThreads="1"/>

 

NIO配置

 <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
               connectionTimeout="20000"
               redirectPort="8443"
               compression="on" compressionMinSize="1024"
               compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/x-json,application/json,application/x-javascript"
               maxThreads="500" minSpareThreads="1"/>

 

演示數據:

Tomcat深入解析與性能優化

 

生成環境重要因素:

  1. 網絡
  2. 程序執行業務用時

 

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

 

BIO 線程模型

Tomcat深入解析與性能優化

 

BIO 源碼

 

線程組:

Accept 線程組 acceptorThreadCount 默認1個

exec 線程組 maxThread

JIoEndpoint

Acceptor extends Runnable

SocketProcessor extends Runnable

Tomcat深入解析與性能優化

 

NIO 線程模型

Tomcat深入解析與性能優化

 

NIO 線程模型

 

Accept 線程組 默認兩個輪詢器

Poller Selector PollerEvent輪詢線程狀態

SocketProcessor

Tomcat深入解析與性能優化

 

 

BIO

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

 

NIO

線程數量 會受到業務處理慢===>線程數會更多。

 

Tomcat connector 并發參數解讀

 

Tomcat深入解析與性能優化

 

Tomcat 類加載機制源碼解析

 

類加載的本質

 

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

 

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

 

jvm里ClassLoader的層次結構

Tomcat深入解析與性能優化

 

類加載器層次結構

 

BootstrapClassLoader(啟動類加載器)

 

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

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

程序執行結果如下:

file:/Library/Java/JavaVirtualmachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/sunrsasign.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/classes

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

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

執行結果如下:

null

 

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

 

ExtensionClassLoader

 

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

 

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

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

執行結果如下(Mac系統):

/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路徑下內容為:

Tomcat深入解析與性能優化

 

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

sun.misc.Launcher$ExtClassLoader@4439f31e
null

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

 

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

 

AppClassLoader

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

 

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

 

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

 

輸出結果如下:

sun.misc.Launcher$AppClassLoader@18b4aac2

 

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

protected ClassLoader() {
    this(checkCreateClassLoader(), getSystemClassLoader());
}

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

 

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

 

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

public class AppClassLoaderTest {

    public static void main(String[] args) {
        ClassLoader classLoader = Test.class.getClassLoader();
        System.out.println(classLoader);
        System.out.println(classLoader.getParent());
    }

    private static class Test {

    }

}

 

執行結果如下:

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

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

 

Tomcat的 類加載順序

 

Tomcat深入解析與性能優化

 

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

 

NoClassDefFoundError

 

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

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

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

 

NoSuchMethodError

 

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

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

 

ClassCastException

 

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

 

部分圖片來源于網絡,版權歸原作者,侵刪。

分享到:
標簽:Tomcat
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定