[ Coding七十二绝技 ] 如何利用Java异常快速分析源码 (2)

现在我们要主动让它出来,让它来告诉我们一些真相。

[ Coding七十二绝技 ] 如何利用Java异常快速分析源码

怎么让springboot启动加载tomcat时出错,都在jar包里,也改不了代码啊,直接调试源码?还是debug。不急。

我来告诉大家一个最简单的方式,利用端口。也就是将tomcat的启动端口改成一个已经被使用的端口,比如说你电脑现在运行着一个mysql服务,那我就让tomcat监听3306端口,这样启动一定会报端口被占用异常。

来,我们试一下。将springboot配置文件中的服务端口改成3306,启动。

[ Coding七十二绝技 ] 如何利用Java异常快速分析源码

哇哦,想要的异常出来了,多么熟悉的画面。

[ Coding七十二绝技 ] 如何利用Java异常快速分析源码

先大概解释下这个异常信息,总体包含两段异常信息。

第一段是springboot启动时内部的异常栈信息,第二段是Tomcat内部加载的异常栈信息。
两者关系就是,因为Tomcat端口被占用,抛出了端口被占用异常,进而导致springboot启动异常。两段异常的衔接点就在整个异常信息的第一行和最后一行,即Connector.java:1008 Connector.java:1005 处。

图中蓝色标出的类是我们程序的运行起点。点进去看实际上就是run方法处出了异常。

@SpringBootApplication
public class FragmentExceptionApplicatioin {

    public static void main(String[] args) {
        SpringApplication.run(FragmentExceptionApplicatioin.class, args);
    }
}

既然是分析springboot是如何加载tomcat的,那么主要分析第一段就OK了,第二段异常信息暂时就可以忽略。

下面我们仔细分析分析。回想前情铺垫里 [ 1 ][ 3 ] 部分的内容,再加上这个异常堆栈信息,我们就从这个中找到程序的执行顺序,进而分析出核心执行流程。找到源码内部的执行逻辑。

来一步步看下
经过上面的分析,实际上我们找到了程序运行的起点,即springboot的run方法。且称为起始位置。
下面要找到终点,就是最上面的那一行,且称为终点位置。

at org.apache.catalina.connector.Connector.startInternal(Connector.java:1008) ~[tomcat-embed-core-9.0.21.jar:9.0.21]

有了起点和终点,我们知道,两点之间,线段最短。哦,跑题了。
是有了起点和终点,执行过程不就在中间吗。

再一点点看,分析类图可以看到AbstractApplicationContext和ServletWebServerApplicationContext是父子类,所以将出现AbstractApplicationContext的地方都替换为为ServletWebServerApplicationContext,最终结合上面的异常栈,我们可以绘制出这么一张时序图。


[ Coding七十二绝技 ] 如何利用Java异常快速分析源码


可以清楚的看到启动时加载的过程。如何?清不清楚。

 

简单组织语言表述一下主体流程,细节暂不展开描述。

应用启动的run方法调用了SpringApplication的一系列重载run方法之后
调用了SpringApplication的刷新上下文方法和刷新方法
再调用ServletWebServerApplicationContext的刷新方法
ServletWebServerApplicationContext刷新方法再调用内部的finishRefresh方法
finishRefresh调用内部的startWebServer方法
startWebServer内部调用TomcatWebServer的start方法启动

友情提醒
分析一个陌生框架的源码,切勿一头扎进细节,保你进去出来后一脸懵逼。应该先找到程序的执行主线,而找到主线的方法一个是官方文档的相关介绍,一个是debug,而最直接有效的莫过于利用异常栈。

大家可以找一款框架亲自试试看。
从此再也不怕面试官问我某某框架的执行原理了。

分析源码时有了这个主线,再去分析里面的细节就容易得多了。再也不怕debug进去后不知调用深浅,迷失在源码当中

功法进阶

上面只是小试牛刀,下面再看一个例子,通过异常分析下springmvc的执行过程。

呀,这可怎么搞,上面造个启动异常,端口重用还想了半天,这个异常要怎么造。异常出在哪里才能看到完整的异常栈呢?

不急,根据上面的两点之间线段最短原理,那自然是找到程序执行的起始位置和终点位置了。

这个场景控制器起点貌似在调用端呀。比如pc端?移动端发了个请求过来,那里是起点呀,我去那里搞么。

要这么复杂,我也就不写这篇文章了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpypwy.html