背景
了解tomcat
生命周期,了解一个http的生命周期
步骤
- 1 拉取tomcat 代码
git clone https://github.com/apache/tomcat
相关的编译后的安装目录在${tomcat.source}/build.propertiesfile
里面
- 2 安装
ant
我的是ubuntu所以直接通过包管理安装
sudo apt install ant
- 3 修改复制build.properties 文件 这里面会有相关的属性,和下载代码相关的路径需要在这里配置
cp build.properties.default build.properties
我们需要将调试符号编译时生成,如果是一个java程序,则是javac -g
, 也就是在编译的时候添加到javac
中.
在tomcat的源代码中的build.xml
中很容易看到compile.debug
这个环境变量
<javac srcdir="java" destdir="${tomcat.classes}"
debug="${compile.debug}" <--! 这里会有compile.debug 环境变量 ->
deprecation="${compile.deprecation}"
release="${compile.release}"
encoding="ISO-8859-1"
includeAntRuntime="true" >
<!-- Uncomment this to show unchecked warnings:
<compilerarg value="-Xlint:unchecked"/>
那么这个环境变量是在哪里控制的呢?
打开 build.properties
,就能看到,所以默认下载下来的tomcat 就是开了-g
选项的,不需要修改
# ----- Build control flags -----
compile.debug=true
- 4 执行构建命令
ant
ant
编译好的相关代码会在 , source_code
就是你的源代码
{source_code}/output/build/bin
切换目录到{source_code}/output/build/bin
./startup.sh
Using CATALINA_BASE: /home/dai/tomcat/output/build
Using CATALINA_HOME: /home/dai/tomcat/output/build
Using CATALINA_TMPDIR: /home/dai/tomcat/output/build/temp
Using JRE_HOME: /usr
Using CLASSPATH: /home/dai/tomcat/output/build/bin/bootstrap.jar:/home/dai/tomcat/output/build/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.
查看tomcat 的命令 , 就是以下内容:
ps aux | grep tomcat
/usr/bin/java -Djava.util.logging.config.file=/home/dai/tomcat/output/build/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED -classpath /home/dai/tomcat/output/build/bin/bootstrap.jar:/home/dai/tomcat/output/build/bin/tomcat-juli.jar -Dcatalina.base=/home/dai/tomcat/output/build -Dcatalina.home=/home/dai/tomcat/output/build -Djava.io.tmpdir=/home/dai/tomcat/output/build/temp org.apache.catalina.startup.Bootstrap start
请求tomcat
在浏览器输入 http://127.0.0.1:8080/
debug tomcat
断点到main函数
在上面步骤用ps aux | grep "tomcat"
获取执行的命令 , 然后在前面/usr/bin/java 紧接着的地方加上参数-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000
,让程序断点在main函数
参数说明:
- suspend 代表是否暂停
- address: 指定地址 , 也可以只指定端口,我这里是8000 端口
- -agentlib:jdwp=transport 协议 ,一般本地用socket 通讯 , 也可以共享内存什么的 。 我这里是
dt_socket
/usr/bin/java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000 -Djava.util.logging.config.file=/home/dai/tomcat/output/build/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED -classpath /home/dai/tomcat/output/build/bin/bootstrap.jar:/home/dai/tomcat/output/build/bin/tomcat-juli.jar -Dcatalina.base=/home/dai/tomcat/output/build -Dcatalina.home=/home/dai/tomcat/output/build -Djava.io.tmpdir=/home/dai/tomcat/output/build/temp org.apache.catalina.startup.Bootstrap start
jdb 开启调试
jdb -attach 8000 -sourcepath /home/dai/tomcat/java/
### 在 org.apache.catalina.startup.Bootstrap.main 打断点
main[1] stop in org.apache.catalina.startup.Bootstrap.main
Deferring breakpoint org.apache.catalina.startup.Bootstrap.main.
It will be set after the class is loaded.
#### 使用run开始执行
main[1] run
使用list
列出代码 然后就会断点到main
函数
Breakpoint hit: "thread=main", org.apache.catalina.startup.Bootstrap.main(), line=442 bci=0
442 synchronized (daemonLock) {
main[1] list
438 * @param args Command line arguments to be processed
439 */
440 public static void main(String args[]) {
441
442 => synchronized (daemonLock) {
443 if (daemon == null) {
444 // Don't set daemon until init() has completed
445 Bootstrap bootstrap = new Bootstrap();
446 try {
447 bootstrap.init();
main[1]
servelet 请求路径
http-nio-8080-exec-1[1] where
[1] HelloWorldExample.doGet (HelloWorldExample.java:41)
[2] jakarta.servlet.http.HttpServlet.service (HttpServlet.java:705)
[3] jakarta.servlet.http.HttpServlet.service (HttpServlet.java:814)
[4] org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:223)
[5] org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:158)
[6] org.apache.tomcat.websocket.server.WsFilter.doFilter (WsFilter.java:53)
[7] org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:185)
[8] org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:158)
[9] org.apache.catalina.filters.HttpHeaderSecurityFilter.doFilter (HttpHeaderSecurityFilter.java:126)
[10] org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:185)
[11] org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:158)
[12] org.apache.catalina.core.StandardWrapperValve.invoke (StandardWrapperValve.java:177)
[13] org.apache.catalina.core.StandardContextValve.invoke (StandardContextValve.java:97)
[14] org.apache.catalina.authenticator.AuthenticatorBase.invoke (AuthenticatorBase.java:542)
[15] org.apache.catalina.core.StandardHostValve.invoke (StandardHostValve.java:119)
[16] org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:92)
[17] org.apache.catalina.valves.AbstractAccessLogValve.invoke (AbstractAccessLogValve.java:690)
[18] org.apache.catalina.core.StandardEngineValve.invoke (StandardEngineValve.java:78)
[19] org.apache.catalina.connector.CoyoteAdapter.service (CoyoteAdapter.java:357)
[20] org.apache.coyote.http11.Http11Processor.service (Http11Processor.java:400)
[21] org.apache.coyote.AbstractProcessorLight.process (AbstractProcessorLight.java:65)
[22] org.apache.coyote.AbstractProtocol$ConnectionHandler.process (AbstractProtocol.java:859)
[23] org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun (NioEndpoint.java:1,734)
[24] org.apache.tomcat.util.net.SocketProcessorBase.run (SocketProcessorBase.java:52)
[25] org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1,191)
[26] org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:659)
[27] org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run (TaskThread.java:61)
[28] java.lang.Thread.run (Thread.java:833)