成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Tomcat深入解析與性能優(yōu)化

開(kāi)發(fā)
在 Java 應(yīng)用中,常用的 Web 服務(wù)器一般由 tomcat、weblogic、jetty、undertwo等。但從 Java 2019和2020 生態(tài)使用報(bào)告可以看到,tomcat的用戶量對(duì)比明顯較大,當(dāng)然這也基于它開(kāi)源和免費(fèi)的特點(diǎn)。

 

                                                                                                                        [[344921]]

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

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

從軟件架構(gòu)的發(fā)展角度來(lái)看,軟件架構(gòu)大致經(jīng)歷了如下幾個(gè)階段:

從 Java Web 角度來(lái)說(shuō),架構(gòu)大致經(jīng)歷了:

從當(dāng)前企業(yè)使用的架構(gòu)角度來(lái)說(shuō),使用SSM架構(gòu)項(xiàng)目比較多,SSH基本被淘汰(大部分是老項(xiàng)目維護(hù)),很大一部分企業(yè)轉(zhuǎn)向微服務(wù)架構(gòu)了。

 

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

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

Tomcat架構(gòu)說(shuō)明
知識(shí)點(diǎn):

 

  1. Tomcat目錄結(jié)構(gòu)
  2. Tomcat簡(jiǎn)要架構(gòu)
  3. Tomcat各組件及關(guān)系
  4. Tomcat server.xml配置詳解
  5. Tomcat啟動(dòng)參數(shù)說(shuō)明(啟動(dòng)腳本)

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

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

Tomcat 目錄結(jié)構(gòu)

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

bin目錄

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

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

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

conf目錄

conf文件夾用來(lái)存放tomcat相關(guān)配置文件

1.catalina.policy

 

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

上圖中,tomcat容器下部署兩個(gè)項(xiàng)目,項(xiàng)目1和項(xiàng)目2。由于項(xiàng)目1中有代碼System.exit(0),當(dāng)訪問(wèn)該代碼時(shí),該代碼會(huì)導(dǎo)致整個(gè)tomcat停止,從而也導(dǎo)致項(xiàng)目2停止。

 

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

 

2.catalina.properties

 

配置tomcat啟動(dòng)相關(guān)信息文件

 

3.context.xml

 

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

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

 

這兩個(gè)文件不常用

5.logging.properties

 

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

 

6.server.xml

 

tomcat核心架構(gòu)主件文件,下面會(huì)詳細(xì)解析。

 

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

 

tomcat用戶文件,如配置遠(yuǎn)程登陸賬號(hào)

 

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

 

8.web.xml

 

tomcat全局配置文件。

lib目錄

lib文件夾主要用來(lái)存放tomcat依賴jar包,如下為 tomcat 的lib文件夾下的相關(guān)jar包。

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

 

假設(shè)要編譯MyTest.java,那么jdk會(huì)執(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在運(yùn)行過(guò)程中產(chǎn)生的臨時(shí)文件。(清空不會(huì)對(duì)tomcat運(yùn)行帶來(lái)影響)。

 

webapps目錄

webapps目錄用來(lái)存放應(yīng)用程序,當(dāng)tomcat啟動(dòng)時(shí)會(huì)去加載webapps目錄下的應(yīng)用程序??梢砸晕募A、war包、jar包的形式發(fā)布應(yīng)用。

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

 

work目錄

work目錄用來(lái)存放tomcat在運(yùn)行時(shí)的編譯后文件,例如JSP編譯后的文件。

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

 

Tomcat 簡(jiǎn)要架構(gòu)

Tomcat 各組件及關(guān)系

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

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

  1. <Server> 
  2.     <Listener /><!-- 監(jiān)聽(tīng)器 --> 
  3.     <GlobaNamingResources> <!-- 全局資源 --> 
  4.     </GlobaNamingResources 
  5.     <Service>          <!-- 服務(wù) 用于 綁定 連接器與 Engine --> 
  6.         <Connector 8080/> <!-- 連接器--> 
  7.         <Connector 8010 /> <!-- 連接器--> 
  8.         <Connector 8030/> <!-- 連接器--> 
  9.                 <Engine>      <!-- 執(zhí)行引擎--> 
  10.             <Logger /> 
  11.             <Realm /> 
  12.                <host "www.test.com" appBase="">  <!-- 虛擬主機(jī)--> 
  13.                    <Logger /> <!-- 日志配置--> 
  14.                    <Context "/applction" path=""/> <!-- 上下文配置--> 
  15.                </host> 
  16.         </Engine> 
  17.     </Service> 
  18. </Server> 

server
root元素:server 的頂級(jí)配置

主要屬性:

port:執(zhí)行關(guān)閉命令的端口號(hào)

shutdown:關(guān)閉命令

 

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

service

服務(wù):將多個(gè)connector 與一個(gè)Engine組合成一個(gè)服務(wù),可以配置多個(gè)服務(wù)。

 

Connector

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

 

主要屬性:

  • protocol 監(jiān)聽(tīng)的協(xié)議,默認(rèn)是http/1.1
  • port 指定服務(wù)器端要?jiǎng)?chuàng)建的端口號(hào)
  • minThread 服務(wù)器啟動(dòng)時(shí)創(chuàng)建的處理請(qǐng)求的線程數(shù)
  • maxThread 最大可以創(chuàng)建的處理請(qǐng)求的線程數(shù)
  • enableLookups 如果為true,則可以通過(guò)調(diào)用request.getRemoteHost()進(jìn)行DNS查詢來(lái)得到遠(yuǎn)程客戶端的實(shí)際主機(jī)名,若為false則不進(jìn)行DNS查詢,而是返回其ip地址
  • redirectPort 指定服務(wù)器正在處理http請(qǐng)求時(shí)收到了一個(gè)SSL傳輸請(qǐng)求后重定向的端口號(hào)
  • acceptCount 指定當(dāng)所有可以使用的處理請(qǐng)求的線程數(shù)都被使用時(shí),可以放到處理隊(duì)列中的請(qǐng)求數(shù),超過(guò)這個(gè)數(shù)的請(qǐng)求將不予處理,默認(rèn)100;
  • address 綁定客戶端特定地址,127.0.0.1
  • bufferSize 每個(gè)請(qǐng)求的緩沖區(qū)大小 bufferSize * maxThreads
  • compression 是否啟用文檔壓縮
  • compressionMinSize 文檔壓縮的最小大小
  • compressableMimeTypes text/html,text/xml,text/plain
  • connectionTimeout 客戶端發(fā)起鏈接到服務(wù)端接收為止,指定超時(shí)的時(shí)間數(shù)(以毫秒為單位)
  • connectionUploadTimeout upload情況下連接超時(shí)時(shí)間
  • disableUploadTimeout 如果為true則使用 connectionTimeout
  • keepAliveTimeout 當(dāng)長(zhǎng)鏈接閑置 指定時(shí)間主動(dòng)關(guān)閉 鏈接 ,前提是客戶端請(qǐng)求頭 帶上這個(gè) head"connection" " keep-alive"
  • maxKeepAliveRequests 最大的 長(zhǎng)連接數(shù) 默認(rèn)最大100
  • maxSpareThreads BIO 模式下 最多線閑置線程數(shù)
  • minSpareThreads BIO 模式下 最小線閑置線程數(shù)
  • SSLEnabled 是否開(kāi)啟 sll 驗(yàn)證,在Https 訪問(wèn)時(shí)需要開(kāi)啟。
  • 演示配置多個(gè)Connector
  1.  <Connector port="8860" protocol="org.apache.coyote.http11.Http11NioProtocol" 
  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í)行器,默認(rèn)的引擎是catalina。一個(gè)service 中只能配置一個(gè)Engine。

主要屬性:name 引擎名稱 defaultHost 默認(rèn)host

 

Host
虛擬機(jī):基于域名匹配至指定虛擬機(jī)。類似于nginx 當(dāng)中的server,默認(rèn)的虛擬機(jī)是localhost.

演示配置多個(gè)Host

  1. <Host name="www.test.com"  appBase="/usr/www/test" 
  2.             unpackWARs="true" autoDeploy="true"
  3.         <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"               prefix="www.luban.com.access_log" suffix=".txt" 
  4.                pattern="%h %l %u %t "%r" %s %b" /> 
  5. </Host> 

Context

應(yīng)用上下文:一個(gè)host 下可以配置多個(gè)Context ,每個(gè)Context 都有其獨(dú)立的classPath。相互隔離,以免造成ClassPath 沖突。

 

  • 演示配置多個(gè)Context
  1. <Context docBase="hello" path="/h" reloadable="true"/> 

Valve

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

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

Tomcat啟動(dòng)參數(shù)說(shuō)明

我們平時(shí)啟動(dòng)Tomcat過(guò)程是怎么樣的?

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

但是我們?cè)贓clipse 或idea 中啟動(dòng)WEB項(xiàng)目的時(shí)候 也是把War包復(fù)雜至webapps 目錄解壓?jiǎn)幔匡@然不是,其真正做法是在Tomcat程序文件之外創(chuàng)建了一個(gè)部署目錄,在一般生產(chǎn)環(huán)境中也是這么做的 即:Tomcat 程序目錄和部署目錄分開(kāi) 。

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

可以編寫一個(gè)腳本 來(lái)實(shí)現(xiàn)自定義配置:

更新 啟動(dòng) 腳本:

  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() {#解壓版本至當(dāng)前目錄target_dir=war/${app}_${version}_${now_time}unzip -q $war -d $target_dirrm -f appwarln -sf $target_dir appwartarget_ln=`pwd`/appwarecho '<?xml version="1.0" encoding="UTF-8" ?> 
  3. <Context docBase="'$target_ln'" allowLinking="false"
  4. </Context>' > conf/Catalina/localhost/ROOT.xml 
  5. #重啟Tomcat服務(wù)./tomcat.sh restart}deploy_war``` 

自動(dòng)部署腳本:

  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() {#解壓版本至當(dāng)前目錄target_dir=war/${app}_${version}_${now_time}unzip -q $war -d $target_dirrm -f appwarln -sf $target_dir appwartarget_ln=`pwd`/appwarecho '<?xml version="1.0" encoding="UTF-8" ?> 
  3. <Context docBase="'$target_ln'" allowLinking="false"
  4. </Context>' > conf/Catalina/localhost/ROOT.xml 
  5. #重啟Tomcat服務(wù)./tomcat.sh restart}deploy_war``` 

Tomcat 網(wǎng)絡(luò)通信模型剖析
Tomcat 支持四種線程模型介紹

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

什么是IO模型?

提問(wèn):

假設(shè)應(yīng)用在從硬盤中讀取一個(gè)大文件過(guò)程中,此時(shí)CPU會(huì)與硬盤一樣處于高負(fù)荷狀態(tài)么?

 

演示:

  • 演示觀察大文件的讀寫過(guò)程當(dāng)中CPU 有沒(méi)有發(fā)生大波動(dòng)。

演示結(jié)果:CPU 沒(méi)有太高的增長(zhǎng)

 

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

 

各IO模型簡(jiǎn)要說(shuō)明
BIO

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

NIO

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

APR

全稱是 Apache Portable Runtime/Apache可移植運(yùn)行庫(kù)),是Apache HTTP服務(wù)器的支持庫(kù)??梢院?jiǎn)單地理解為,Tomcat將以JNI的形式調(diào)用Apache HTTP服務(wù)器的核心動(dòng)態(tài)鏈接庫(kù)來(lái)處理文件讀取或網(wǎng)絡(luò)傳輸操作。使用需要編譯安裝APR 庫(kù)

AIO

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

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

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

默認(rèn)配置 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實(shí)現(xiàn)過(guò)程源碼解析

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

BIO 配置

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

NIO配置

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

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

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

  1. 網(wǎng)絡(luò)
  2. 程序執(zhí)行業(yè)務(wù)用時(shí)

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

 

BIO 線程模型

BIO 源碼

 

線程組:

Accept 線程組 acceptorThreadCount 默認(rèn)1個(gè)

exec 線程組 maxThread

JIoEndpoint

Acceptor extends Runnable

SocketProcessor extends Runnable

NIO 線程模型

NIO 線程模型

 

Accept 線程組 默認(rèn)兩個(gè)輪詢器

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

SocketProcessor

BIO

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

 

NIO

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

 

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

Tomcat 類加載機(jī)制源碼解析

類加載的本質(zhì)

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

 

JVM 運(yùn)行實(shí)例中會(huì)存在多個(gè) ClassLoader,不同的 ClassLoader 會(huì)從不同的地方加載字節(jié)碼文件。它可以從不同的文件目錄加載,也可以從不同的 jar 文件中加載,也可以從網(wǎng)絡(luò)上不同的靜態(tài)文件服務(wù)器來(lái)下載字節(jié)碼再加載。

 

jvm里ClassLoader的層次結(jié)構(gòu)

類加載器層次結(jié)構(gòu)

 

BootstrapClassLoader(啟動(dòng)類加載器)

 

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

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

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

  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í)行結(jié)果如下:

  1. null 

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

 

ExtensionClassLoader

 

ExtClassLoader稱為擴(kuò)展類加載器,主要負(fù)責(zé)加載Java的擴(kuò)展類庫(kù),默認(rèn)加載JAVA_HOME/jre/lib/ext/目錄下的所有jar包或者由java.ext.dirs系統(tǒng)屬性指定的jar包.放入這個(gè)目錄下的jar包對(duì)AppClassLoader加載器都是可見(jiàn)的(因?yàn)镋xtClassLoader是AppClassLoader的父加載器,并且Java類加載器采用了委托機(jī)制)。

 

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

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

執(zhí)行結(jié)果如下(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路徑下內(nèi)容為:

從上面的路徑中隨意選擇一個(gè)類,來(lái)看看它的類加載器是什么:

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

從上面的程序運(yùn)行結(jié)果可知ExtClassLoader的父加載器為null,之前說(shuō)過(guò)BootstrapClassLoader對(duì)Java不可見(jiàn),所以返回了null。ExtClassLoader的父加載器返回的是null,那是否說(shuō)明ExtClassLoader的父加載器是BootstrapClassLoader?

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

AppClassLoader

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

 

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

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

輸出結(jié)果如下:

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

以上結(jié)論說(shuō)明調(diào)用ClassLoader.getSystemClassLoader()可以獲得AppClassLoader類加載器。

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

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

 

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

 

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

  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í)行結(jié)果如下:

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

從上面的運(yùn)行結(jié)果可以得知AppClassLoader的父加載器是ExtClassLoader

 

Tomcat的 類加載順序

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

 

NoClassDefFoundError

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

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

這一刻IDE是沒(méi)有出錯(cuò)提醒的,但是在運(yùn)行時(shí)卻出現(xiàn)了錯(cuò)誤。

 

NoSuchMethodError

在另一個(gè)場(chǎng)景中,我們可能遇到了另一個(gè)錯(cuò)誤,也就是NoSuchMethodError。

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

 

ClassCastException

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

 

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2023-05-10 10:30:02

性能優(yōu)化Tomcat

2023-01-30 08:30:09

Tomcat性能優(yōu)化

2023-10-11 08:36:42

復(fù)合查詢腳本查詢

2013-07-23 09:51:32

Tomcat性能優(yōu)化服務(wù)器性能優(yōu)化

2016-11-01 10:59:04

web代理緩存

2023-10-10 08:52:36

射與分析相開(kāi)源

2014-06-05 10:22:06

Tomcat 7

2023-04-17 16:33:27

云計(jì)算工具云性能測(cè)試

2018-01-31 18:32:06

數(shù)據(jù)庫(kù)Oracle優(yōu)化工具

2010-06-07 09:11:43

jQuery

2012-07-06 09:51:34

2024-10-09 23:32:50

2013-12-17 17:05:20

iOS性能優(yōu)化

2024-11-05 16:29:57

2019-08-12 15:44:41

DockerTomcat

2010-05-24 14:59:29

Hadoop集群

2022-10-28 13:41:51

字節(jié)SDK監(jiān)控

2024-02-28 07:50:06

代碼管理工具開(kāi)發(fā)

2023-10-12 08:57:23

故障排除監(jiān)控

2024-04-16 14:57:51

人工智能深度學(xué)習(xí)
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 久久久噜噜噜久久中文字幕色伊伊 | 国产亚洲欧美在线 | 亚洲一区在线日韩在线深爱 | 欧美婷婷 | 女同videos另类| 少妇黄色 | 国产精品99久久久久久动医院 | 色吊丝2288sds中文字幕 | 亚洲一区二区精品视频 | 中文字幕日韩欧美 | 久久99精品久久久久婷婷 | 欧美三级不卡 | 在线a视频 | 性高朝久久久久久久3小时 av一区二区三区四区 | 欧美精品一区二区三区在线播放 | 亚洲一区日韩 | 99精品99| av电影一区| 国产亚洲精品一区二区三区 | 黄色小视频大全 | 久久91精品久久久久久9鸭 | 久久1区 | 成人影| 亚洲在线一区二区三区 | 日本a∨视频 | 91久久精品日日躁夜夜躁国产 | 日韩一区二区三区视频 | 亚洲网站在线观看 | www.欧美.com | 日日操夜夜操天天操 | 91精品国产乱码麻豆白嫩 | 精品久久香蕉国产线看观看亚洲 | 欧美日韩一区二区在线播放 | 国产精品1区 | www.国产精 | 性一爱一乱一交一视频 | 国产精品福利在线观看 | 中文字幕在线免费观看 | 久久精品中文字幕 | 国产99热 | 天天操夜夜艹 |