读《软件调试》第九章

Tomcat源码学习前的准备工作

注:由于网上的帖子大部分没有配套的图片和错误的分析,所有费了半天劲整理了此篇博客,希望大家少走弯路吧

下面我们就开始我们的Tomcat源码学习之旅。

1. 下载Tomcat6.0的源代码

首先,我们得下载Tomcat6.0的源代码。Tomcat源代码的版本控制工具不是CVS,而是Subversion,如果您的机器上没有安装Subversion,请从http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91 下载并安装这个开源的版本控制工具。当然,如果您想从Eclipse中直接导入Tomcat源代码,请从http://subclipse.tigris.org/update_1.0.x下载Subversion插件,即可导入Tomcat源代码。安装完成后,请在MS-DOS窗口中键入svn
export help,您将会看到:

C:\Documents and Settings\carlwu>svn help export

export: 产生一个无版本控制的目录树副本。

用法: 1、export [-r REV] URL[@PEGREV] [PATH]

2、export [-r REV] PATH1[@PEGREV] [PATH2]

1、从 URL 指定的仓库,导出一个干净的目录树到 PATH。如果有指定

REV 的话,内容即为该版本的,否则就是 HEAD 版本。如果 PATH

被省略的话,URL的最后部份会被用来当成本地的目录名称。

2、在工作副本中,从指定的 PATH1 导出一个干净的目录树到 PATH2。如果

有指定 REV 的话,会从指定的版本导出,否则从工作副本导出。如果

PATH2 被省略的话,PATH1 的最后部份会被用来当成本地的目录名称。

如果没有指定 REV 的话,所有的本地修改都保留,但是未纳入版本控制

的文件不会被复制。

如果指定了 PEGREV ,将从指定的版本本开始查找。

有效选项:。。。。。。

我们看到Subversion给我们提供了非常友好的帮助,并且是中文的,看来中国程序员对这个开源项目有所贡献。接下来,请在MS-DOS下键入:

svn export http://svn.apache.org/repos/asf/tomcat/tc6.0.x/tags/TOMCAT_6_0_0/D:\carl_wu\tomcat\src\

这个命令的意思是把Tomcat6.0的源代码从Subversion库中导入到本机的D:\carl_wu\tomcat\src\目录,命令运行后,您稍等几分钟,就会看到Tomcat的源代码顺利导入到目标目录。下面是源代码的目录机构,从这个目录结构中,我们可以看出该项目的开发者使用的IDE是Eclipse,因为我们看到了熟悉的.project及.classpath文件。如果您打算开发一个Stand alone的Java应用程序,不妨借鉴一下Tomcat的目录结构,把脚本文件放在bin目录,将xml和properties配置文件放在conf目录中,把Java源码文件放在java或者src目录中,资源文件比如说图片文件,ini文件及其它的一些静态资源文件可以放在res目录,测试源代码可以放在test目录中。这是一个典型的Java应用程序的目录机构,笔者以前曾接触到一个来自美国的产品,其源代码目录结构和Tomcat及其相像。

2. 编译并运行

代码下载后,我们接下来就是要编译并运行Tomcat。一提编译,我们不禁会想到可爱的Ant。不错,Tomcat正是以Ant作为编译工具,如果您还没有安装,请从http://ant.apache.org/bindownload.cgi 处下载并安装它。然后,请从Tomcat的源代码文件找到build.properties.default文件,并将该文件复制到build.properties,然后打开build.properties,找到下面这行:

base.path=/usr/share/java

将它改为:

base.path= D:/carl_wu/tomcat/share

在Tomcat编译过程中,Ant会让我们下载一些必要的依赖项目,base.path目录就是用来保存这些项目文件的,我们可以将这个属性指向一个已经存在的目录。修改完base.path后,我们回到MS-DOS窗口,切换到Tomcat源代码所在目录,然后运行ant download命令,正常的情况下如下图所示:

一分钟未到,Ant就告诉我们一个错误并提示我们编译失败,具体错误信息如下:

downloadzip:

[get] Getting: http://sunsite.informatik.rwth-aachen.de/eclipse/downloads/drops/R-3.2-200606291905/eclipse-JDT-3.2.zip

[get] To: D:\carl_wu\tomcat\share\file.zip

[get] Error opening connection java.io.FileNotFoundException: http://sunsite.informatik.rwth-aachen.de:3080/eclipse/downloads/drops/R-3.2-200606291905/eclipse-JDT-3.2.zip

[get] Error opening connection java.io.FileNotFoundException: http://sunsite.informatik.rwth-aachen.de:3080/eclipse/downloads/drops/R-3.2-200606291905/eclipse-JDT-3.2.zip

[get] Error opening connection java.io.FileNotFoundException: http://sunsite.informatik.rwth-aachen.de:3080/eclipse/downloads/drops/R-3.2-200606291905/eclipse-JDT-3.2.zip

[get] Can‘t get http://sunsite.informatik.rwth-aachen.de/eclipse/downloads/drops/R-3.2-200606291905/eclipse-JDT-3.2.zipto
D:\carl_wu\tomcat\share\file.zip

BUILD FAILED

D:\carl_wu\tomcat\src\build.xml:554: The following error occurred while executing this line:

D:\carl_wu\tomcat\src\build.xml:514: Can‘t get http://sunsite.informatik.rwth-aachen.de/eclipse/downloads/drops/R-3.2-200606291905/eclipse-JDT-3.2.zipto
D:\carl_wu\tomcat\share\file.zip

Total time: 41 seconds

这个编译错误非常简单,就是找不到http://sunsite.informatik.rwth-aachen.de/eclipse/downloads/drops/R-3.2-200606291905/eclipse-JDT-3.2.zip文件。有人可能会想,Tomcat的编译和Eclipse的JDT有什么关系?其实不然,Tomcat是在Eclipse下开发的,所以需要Eclipse的JDT(Java
Development tooling)插件来编译Tomat源代码。既然找不到,我们只好自己动手,上Google一搜,马上发现这个文件的有效下载地址为:http://mirror.calvin.edu/eclipse/downloads/drops/R-3.2-200606291905/eclipse-JDT-3.2.zip。我们打开刚才的build.properties文件,将其34行修改为:

jdt.loc= http://mirror.calvin.edu/eclipse/downloads/drops/R-3.2-200606291905/eclipse-JDT-3.2.zip

修改保存build.properties文件后,重新开始ant download任务。这次我们等的时间较长,因为eclipse-JDT-3.2.zip大约有19M,下载需要一段时间。我们可乘此机会去泡杯茶弄点咖啡什么的,等我们品茶回来,发现敬业的蚂蚁Ant告诉我们编译成功,虽然编译器给出几个警告。这时我们可发现刚才创建的base.path目录(D:\carl_wu\tomcat\share)中已经下载了6个依赖项目,它们都是Tomcat编译所必须的。

如果出现错误,请查看你所用的jdk版本是否是1.5

下面就开始真正的编译任务了,请在MS-DOS窗口内键入ant并回车,Ant将在2分钟内编译1000多个源文件并将Tomcat部署到output目录。编译顺利完成后,请打开Tomcat的源代码目录,会发现多了一个output目录,这是Ant的编译后的输出目录。请打开Tomcat源代码的output\build\bin子目录,双击startup.bat文件,我们即可成功启动Tomcat6.0,此时我们的编译工作就算顺利完成了。

编译完成后的目录

3. 导入源代码到Eclipse

3.1 请打开Eclipse,新建一个Java项目,然后点击“Next”按钮,请选择“Create project from existing source”, 并在Directory文本框内填入我们刚才下载的Tomcat源代码目录(i.e. D:\carl_wu\tomcat\src),然后点击“Next”直至结束。

3.2 我们将会看到Eclipse拒绝编译,这是因为Eclipse找不到该项目指定的库文件。请右击该项目,在弹出菜单中选择“Properties”à“Libraries”,然后删除两个以TOMCAT_LIBS开头的两个库文件,只保留一个JRE库文件,然后点击“OK”按钮,这时Eclipse开始编译Tomcat源代码,但是发现一堆错误,这是因为我们没有为该项目添加编译所必须的Jar包。

3.3 准备好Tomcat项目所必须的jar文件,其实,刚才我们运行ant download任务时,已经下载过这些jar文件包。 (根据dos窗口提示来下载缺少的jar)

ant.jar (请在ant安装目录的lib子目录中拷贝)

commons-collections-3.1.jar (从刚才Ant下载的commons-collections-3.1子目录中拷贝)

commons-dbcp-1.2.1.jar(从刚才Ant下载的commons-dbcp-1.2.1子目录中拷贝)

commons-logging-1.1.jar(如果您本机没有这个jar包,请从http://commons.apache.org/downloads/download_logging.cgi处下载)

commons-pool-1.2.jar(从刚才Ant下载的commons-pool-1.2子目录中拷贝)

org.eclipse.jdt.core_3.2.0.v_671.jar(从刚才Ant下载的eclipse\plugins子目录中拷贝)

3.4 当我们准备好这些jar文件后,将这些文件拷贝到某一目录(比如说D:\carl_wu\tomcat\tomcat_lib目录),然后在Eclipse中新建一个User Libraries,我们将这个新建的User Libraries命名为TOMCAT_LIBS,并把这些文件加到TOMCAT_LIBS。然后将我们新建的TOMCAT_LIBS添加到Tomcat6项目。另外,别忘了把JUnit库也加到Tomcat6项目。这时Eclipse开始重新编译,编译过程顺利通过,所有错误均消失,此时Tomcat6项目的目录结构如下:

还有,请把test目录也加入到源代码中,方法是在Eclipse中右击”test”目录,然后在弹出菜单中选择“Build path”à”Use as Source Folder”,之后我们会看到test目录上就多了个源代码的符号,如上图所示。

3.5在Eclipse中运行Tomcat。请找到Tomcat的启动主类org.apache.catalina.startup.Bootstrap,右击这个类,在弹出菜单中选择“Run As…”à”Open Run Dialog…”,然后在弹出的“Run”窗口中填入程序运行参数“start”和JVM运行参数catalina.home,如下面窗口所示:

然后点击“Run”按钮,我们将会看到Tomcat正常启动。恭喜,咱们的Tomcat源码已经成功导入Eclipse,这时,可视化的UML分析工具及Debug工具就能派上用场了。

3.5 调试Tomcat,请打开org.apache.jasper.compiler.Compiler类的源代码,在generateJava()方法的第一行打一个断点,然后在Eclipse的调试状态下运行Tomcat,等Tomcat运行后,打开我们的浏览器,在地址栏中输入http://localhost:8080/examples/jsp/jsp2/el/basic-comparisons.jsp并回车,然后我们可观察到Eclipse此时切换至调试视图:

上面的小实验表明我们可以在Eclipse中通过Debugger观察Tomcat的内部运行机理。另外补充一点,上面的generateJava方法是将jsp动态编译至java class,这个方法只是在第一次请求或者Jsp源码发生变化时执行,如果您再次在浏览器中发送同样的请求,您将看不到上图的Debug界面,因为该方法不再执行。

另外,还有一点很有意思。Tomcat6以前版本的源代码分散在好几个子项目中,他们分别叫做jakarta-servletapi-5,jakarta-tomcat-5,jakarta-tomcat-catalina,jakarta-tomcat-connectors和jakarta-tomcat-jasper,我觉得Tomcat的开发者可能嫌这样做太麻烦了,所以Tomcat6版本中将这些子项目都合并在一起了。但是,这种做法不利于我们阅读理解源代码

读《软件调试》第九章,布布扣,bubuko.com

时间: 2024-11-13 06:13:19

读《软件调试》第九章的相关文章

软件工程——理论、方法与实践 第九章

第九章.软件实现      第九章软件实现的过程包括代码设计.设计审查.代码编写.代码编译和单元测试等基本活动.主要讲 1.程序设计语言,语言的演化和演变: 2.软件编码规范,讲了编写规范的重要性,采用规范编写程序可以增强代码的可读性和可移植性 3.软件编码案例分析,用一段具体的代码,详细介绍了程序注释问题.变量名门问题.内存异常问题.异常处理问题和性能问题: 4.软件代码审查,是为了获得高质量的代码,参照代码检查清单进行的代码走查.

软件工程读书笔记(9)——第九章 软件实现

第九章 软件实现 软件实现是软件产品由概念到实体的一个关键过程,它将详细设计的结果翻译成用某种程序设计语言编写的并且最终可以运行的程序代码. 一.程序设计语言 程序设计语言一直在不断地演化和演变,其发展经历了从机器语言到高级语言的过程. 二.软件编码的规范 以java为例 1.文件命名与组织 一般来说,一个java源文件由若干节(Section)组成,每一节都用空行和相关的注释隔开,文件的长度最好不要超过2000行. 2.代码的版式 ①适当的空行 ②代码行及行内空格 ③分行.对齐与缩进 ④命名规

APUE学习笔记:第九章 进程关系

9.1 引言 本章将更详尽地说明进程组以及POSIX.1引入的会话的概念.还将介绍登陆shell(登录时所调用的)和所有从登陆shell启动的进程之间的关系. 9.1 终端登陆 系统管理员创建通常名为/etc/ttys的文件,其中每个终端设备都有一行,每一行说明设备名传递给getty程序的参数.当系统自举时,内核创建进程ID为1的进程,依旧是init进程.init进程使系统进入多用户状态.init进程读文件/etc/ttys,对每一个允许登陆的终端设备,init调用一次fork,所生成的子进程则

操作系统思考 第九章 线程

第九章 线程 作者:Allen B. Downey 原文:Chapter 9 Threads 译者:飞龙 协议:CC BY-NC-SA 4.0 当我在2.3节提到线程的时候,我说过线程就是一种进程.现在我会更仔细地解释它. 当你创建进程时,操作系统会创建一块新的地址空间,它包含text段.static段.和堆区.它也会创建新的"执行线程",这包括程序计数器和其它硬件状态,以及运行时栈. 我们目前为止看到的进程都是"单线程"的,也就是说每个地址空间中只运行一个执行线程

Android群英传笔记——第九章:Android系统信息和安全机制

Android群英传笔记--第九章:Android系统信息和安全机制 本书也正式的进入尾声了,在android的世界了,不同的软件,硬件信息就像一个国家的经济水平,军事水平,不同的配置参数,代表着一个android帝国的强弱,所以厂商喜欢打配置战,本节就要是讲 Android系统信息的获取 PackageManager的使用 ActivityManager的使用 Android安全机制 一. Android系统信息的获取 由于android手机的开源性,手机的配置各种各样,那些优化大师之类的东西

第九章 C语言在嵌入式中的应用

上章回顾 编码的规范和程序版式 版权管理和申明 头文件结构和作用 程序命名 程序注释和代码布局规范 assert断言函数的应用 与0或NULL值的比较 内存的分配和释放细节,避免内存泄露 常量特性 [email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git 第九章 第九章 C语言在嵌入式中的应用 C语言在嵌入式中的应用 [email protecte

《软件调试的艺术》学习笔记——GDB使用技巧摘要

<软件调试的艺术>学习笔记——GDB使用技巧摘要 <软件调试的艺术>,因为名是The Art of Debugging with GDB, DDD, and Eclipse. 作者是美国的Norman Matloff和Peter Jay Salzman,中文版由张云翻译.是人邮出版社图灵程序设计丛书初版.这里称为"艺术",个人觉得有点过了,但是其中关于gdb以及在gdb基础之上集成的DDD和Eclipse调试技巧的整理确实是做的很好,对于Linux/开源社区下的

现代软件工程讨论第九章-十七章

第九章 9.5.1  PM们的故事 9.5.2  我是做PM 的料么? 在校学生如何为成为PM做准备 你是否觉得你的长处不在于写代码和debug,而是协调.沟通,让一个团队或组织有效运转起来?你是否喜欢表达,善于和各种专业背景的人沟通?你是否经常思考如何改进生活中点点滴滴的小问题?你会思考这样的问题么:新浪微博.豆瓣.qq.微信都可以社交,它们的定位.产品特性.用户群.解决的需求,有什么不同?你是否对以下领域感兴趣,甚至自己找过相关的书来看:心理学.社会学.组织行为学.统计学.商业模式? 如果你

数据库学习笔记:第九章 存储数据:磁盘和文件

第九章 数据以磁盘块为单位存储在磁盘上.块分布于一张或多张盘片的同心环形磁道上.磁道可以在盘片的单面或双面上录制. 同一直径的所有磁道的集合称为柱面. 磁盘块的大小在磁盘初始化时可以被设置成扇区大小的倍数. 每一个记录的表面都有一个磁盘头阵列.读写一块时,磁头必须定位在块头位置. 不能并行读写的主要原因是很难保证所有磁头被精确定位在相应的磁道上. 磁盘控制器是磁盘驱动器与计算机的接口. 当数据被写到扇区时,需要计算校验和并存储在扇区上,当扇区上的数据被独处时,需要再次校验和. 寻道时间是用于移动