﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Coundy-文章分类-Java</title><link>http://www.blogjava.net/coundy/category/21238.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 16 May 2007 03:28:52 GMT</lastBuildDate><pubDate>Wed, 16 May 2007 03:28:52 GMT</pubDate><ttl>60</ttl><item><title>一个调试JSP的Eclipse插件的开发</title><link>http://www.blogjava.net/coundy/articles/117628.html</link><dc:creator>Coundy</dc:creator><author>Coundy</author><pubDate>Tue, 15 May 2007 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/coundy/articles/117628.html</guid><wfw:comment>http://www.blogjava.net/coundy/comments/117628.html</wfw:comment><comments>http://www.blogjava.net/coundy/articles/117628.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/coundy/comments/commentRss/117628.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/coundy/services/trackbacks/117628.html</trackback:ping><description><![CDATA[<p>【摘&nbsp;要】<span class=checkoutHeader twffan="done"><strong>本文通过开发一个JSP&nbsp;编辑器插件的示例，介绍了&nbsp;Eclipse&nbsp;中设置&nbsp;JSP&nbsp;断点的方法，以及如何远程调试&nbsp;JSP。作为基础知识，本文的前两部分描述了&nbsp;JAVA&nbsp;Debug&nbsp;和&nbsp;JSR-45&nbsp;的基本原理。</strong></span>&nbsp;</p>
<div class=content twffan="done">　　本文通过开发一个JSP&nbsp;编辑器插件的示例，介绍了&nbsp;Eclipse&nbsp;中设置&nbsp;JSP&nbsp;断点的方法，以及如何远程调试&nbsp;JSP。作为基础知识，本文的前两部分描述了&nbsp;JAVA&nbsp;Debug&nbsp;和&nbsp;JSR-45&nbsp;的基本原理。&nbsp;<br><br>　　环境要求:&nbsp;本文的代码是在&nbsp;Eclipse3.0.0，JDK1.4.2&nbsp;和&nbsp;Tomcat5.0.5&nbsp;上测试过的。<br><br>　　<strong>JAVA&nbsp;调试框架（JPDA）简介</strong><br><br>　　JPDA&nbsp;是一个多层的调试框架，包括&nbsp;JVMDI、JDWP、JDI&nbsp;三个层次。JAVA&nbsp;虚拟机提供了&nbsp;JPDA&nbsp;的实现。其开发工具作为调试客户端，可以方便的与虚拟机通讯，进行调试。Eclipse&nbsp;正是利用&nbsp;JPDA&nbsp;调试&nbsp;JAVA&nbsp;应用，事实上，所有&nbsp;JAVA&nbsp;开发工具都是这样做的。SUN&nbsp;JDK&nbsp;还带了一个比较简单的调试工具以及示例。<br>
<ul>
    <li>JVMDI&nbsp;定义了虚拟机需要实现的本地接口&nbsp;&nbsp;
    <li>JDWP&nbsp;定义了JVM与调试客户端之间的通讯协议&nbsp;<br><br>调试客户端和JVM&nbsp;既可以在同一台机器上，也可以远程调试。JDK&nbsp;会包含一个默认的实现&nbsp;jdwp.dll，JVM&nbsp;允许灵活的使用其他协议代替&nbsp;JDWP。SUN&nbsp;JDK&nbsp;有两种方式传输通讯协议：Socket&nbsp;和共享内存(后者仅仅针对&nbsp;Windows)，一般我们都采用&nbsp;Socket&nbsp;方式。<br><br>你可以用下面的参数，以调试模式启动JVM<br><br>
    <div class=code twffan="done">
    <pre>&nbsp;&nbsp;-Xdebug&nbsp;-Xnoagent&nbsp;-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n&nbsp;
    &nbsp;&nbsp;-Xrunjdwp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JVM&nbsp;加载&nbsp;jdwp.dll&nbsp;&nbsp;
    &nbsp;&nbsp;&nbsp;transport=dt_socket&nbsp;&nbsp;&nbsp;使用&nbsp;Socket&nbsp;传输&nbsp;
    &nbsp;&nbsp;&nbsp;address&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;表示调试端口号&nbsp;
    &nbsp;&nbsp;&nbsp;server=y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;表示&nbsp;JVM&nbsp;作为服务器，建立&nbsp;Socket&nbsp;
    &nbsp;&nbsp;&nbsp;suspend=n&nbsp;&nbsp;&nbsp;&nbsp;表示启动过程中，JVM&nbsp;不会挂起去等待调试客户端连接</pre>
    </div>
    <br>
    <li>JDI&nbsp;则是一组JAVA接口&nbsp;<br><br>如果是一个&nbsp;JAVA&nbsp;的调试客户端，只要实现&nbsp;JDI&nbsp;接口，利用JDWP协议，与虚拟机通讯，就可以调用JVMDI了。<br></li>
</ul>
　　下图为&nbsp;JPDA&nbsp;的基本架构：<br><br>
<div class=code twffan="done">
<pre>&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Components&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Debugger&nbsp;Interface&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/&nbsp;&nbsp;&nbsp;&nbsp;|-----------------------|&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;
&nbsp;debuggee&nbsp;----(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|-----------------------|&nbsp;&nbsp;&lt;-------&nbsp;JVMDI&nbsp;-&nbsp;Java&nbsp;VM&nbsp;Debug&nbsp;Interface&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;back-end&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\&nbsp;&nbsp;&nbsp;&nbsp;|-----------------------|&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;
&nbsp;&nbsp;comm&nbsp;channel&nbsp;-(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&lt;---------------&nbsp;JDWP&nbsp;-&nbsp;Java&nbsp;Debug&nbsp;Wire&nbsp;Protocol&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|---------------------|&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;front-end&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|---------------------|&nbsp;&nbsp;&lt;-------&nbsp;JDI&nbsp;-&nbsp;Java&nbsp;Debug&nbsp;Interface&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UI&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|---------------------|&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</pre>
</div>
<br>　　参见：<a href="http://java.sun.com/j2se/1.4.2/docs/guide/jpda/architecture.html"><u>http://java.sun.com/j2se/1.4.2/docs/guide/jpda/architecture.html</u></a>&nbsp;<br><br>　　Eclipse作为一个基于&nbsp;JAVA&nbsp;的调试客户端，利用&nbsp;org.eclipse.jdt.debug&nbsp;Plugin&nbsp;提供了JDI&nbsp;的具体实现。JDI&nbsp;接口主要包含下面&nbsp;4&nbsp;个包<br>
<pre>com.sun.jdi&nbsp;&nbsp;
com.sun.jdi.connect&nbsp;&nbsp;
com.sun.jdi.event&nbsp;&nbsp;
com.sun.jdi.request&nbsp;</pre>
　　本文不对&nbsp;JDI&nbsp;进行深入阐述，这里重点介绍&nbsp;JDI&nbsp;中与断点相关的接口。<br>
<ul>
    <li>com.sun.jdi&nbsp;<br><br>主要是JVM(VirtualMachine)&nbsp;线程(ThreadReference)&nbsp;调用栈(StackFrame)&nbsp;以及类型、实例的描述。利用这组接口，调试客户端可以用类似类反射的方式，得到所有类型的定义，动态调用&nbsp;Class&nbsp;的方法。&nbsp;&nbsp;
    <li>com.sun.jdi.event&nbsp;<br><br>封装了JVM&nbsp;产生的事件，&nbsp;JVM&nbsp;正是将这些事件通知给调试客户端的。例如&nbsp;BreakpointEvent&nbsp;就是&nbsp;JVM&nbsp;执行到断点的时候，发出的事件；ClassPrepareEvent就是&nbsp;Class&nbsp;被加载时发出的事件。&nbsp;<br><br>
    <li>com.sun.jdi.request&nbsp;<br><br>封装了调试客户端可以向&nbsp;JVM发起的请求。例如&nbsp;BreakpointRequest&nbsp;向&nbsp;JVM&nbsp;发起一个添加断点的请求；ClassPrepareRequest&nbsp;向&nbsp;JVM&nbsp;注册一个类加载请求，JVM&nbsp;在加载指定&nbsp;Class&nbsp;的时候，就会发出一个&nbsp;ClassPrepareEvent&nbsp;事件。&nbsp;&nbsp; </li>
</ul>
　　<strong>JSR-45规范</strong><br><br>　　JSR-45(Debugging&nbsp;Support&nbsp;for&nbsp;Other&nbsp;Languages)为那些非&nbsp;JAVA&nbsp;语言写成，却需要编译成&nbsp;JAVA&nbsp;代码，运行在&nbsp;JVM&nbsp;中的程序，提供了一个进行调试的标准机制。也许字面的意思有点不好理解，什么算是非&nbsp;JAVA&nbsp;语言呢？其实&nbsp;JSP&nbsp;就是一个再好不过的例子，JSR-45&nbsp;的样例就是一个&nbsp;JSP。<br><br>　　JSP的调试一直依赖于具体应用服务器的实现，没有一个统一的模式，JSR-45&nbsp;针对这种情况，提供了一个标准的模式。我们知道，JAVA&nbsp;的调试中，主要根据行号作为标志，进行定位。但是&nbsp;JSP&nbsp;被编译为&nbsp;JAVA&nbsp;代码之后，JAVA&nbsp;行号与&nbsp;JSP&nbsp;行号无法一一对应，怎样解决呢？<br><br>　　JSR-45&nbsp;是这样规定的：JSP&nbsp;被编译成&nbsp;JAVA&nbsp;代码时，同时生成一份&nbsp;JSP&nbsp;文件名和行号与&nbsp;JAVA&nbsp;行号之间的对应表(SMAP)。JVM&nbsp;在接受到调试客户端请求后，可以根据这个对应表(SMAP)，从&nbsp;JSP&nbsp;的行号转换到&nbsp;JAVA&nbsp;代码的行号；JVM&nbsp;发出事件通知前,&nbsp;也根据对应表(SMAP)进行转化，直接将&nbsp;JSP&nbsp;的文件名和行号通知调试客户端。<br><br>　　我们用&nbsp;Tomcat&nbsp;5.0&nbsp;做个测试，有两个&nbsp;JSP，Hello.jsp&nbsp;和&nbsp;greeting.jsp，前者&nbsp;include&nbsp;后者。Tomcat会将他们编译成&nbsp;JAVA&nbsp;代码(Hello_jsp.java)，JAVA&nbsp;Class(Hello_jsp.class)&nbsp;以及&nbsp;JSP&nbsp;文件名/行号和&nbsp;JAVA&nbsp;行号之间的对应表(SMAP)。<br><br>　　Hello.jsp:&nbsp;<br><br>
<div class=code twffan="done">
<pre>&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&lt;HTML&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&lt;HEAD&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&lt;TITLE&gt;Hello&nbsp;Example&lt;/TITLE&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&lt;/HEAD&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&lt;BODY&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&lt;%@&nbsp;include&nbsp;file="greeting.jsp"&nbsp;%&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&lt;/BODY&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&lt;/HTML&gt;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</pre>
</div>
<br>　　greeting.jsp:&nbsp;<br><br>1&nbsp;Hello&nbsp;There!&lt;P&gt;&nbsp;2&nbsp;Goodbye&nbsp;on&nbsp;&lt;%=&nbsp;new&nbsp;java.util.Date()&nbsp;%&gt;&nbsp;<br><br>　　JSP&nbsp;编译后产生的Hello_jsp.java&nbsp;如下:<br><br>
<div class=code twffan="done">
<pre>Hello_jsp.java:&nbsp;
1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;package&nbsp;org.apache.jsp;&nbsp;
2&nbsp;
3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;javax.servlet.*;&nbsp;
4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;javax.servlet.http.*;&nbsp;
5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;javax.servlet.jsp.*;&nbsp;
6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;final&nbsp;class&nbsp;Hello_jsp&nbsp;extends&nbsp;org.apache.jasper.runtime.HttpJspBase&nbsp;
8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;implements&nbsp;org.apache.jasper.runtime.JspSourceDependent&nbsp;{&nbsp;
9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;java.util.Vector&nbsp;_jspx_dependants;&nbsp;
11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;{&nbsp;
13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_jspx_dependants&nbsp;=&nbsp;new&nbsp;java.util.Vector(1);&nbsp;
14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_jspx_dependants.add("/greeting.jsp");&nbsp;
15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;
16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;java.util.List&nbsp;getDependants()&nbsp;{&nbsp;
18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;_jspx_dependants;&nbsp;
19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;
20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
21&nbsp;&nbsp;public&nbsp;void&nbsp;_jspService(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response)&nbsp;
22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws&nbsp;java.io.IOException,&nbsp;ServletException&nbsp;{&nbsp;
23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JspFactory&nbsp;_jspxFactory&nbsp;=&nbsp;null;&nbsp;
25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PageContext&nbsp;pageContext&nbsp;=&nbsp;null;&nbsp;
26&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpSession&nbsp;session&nbsp;=&nbsp;null;&nbsp;
27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServletContext&nbsp;application&nbsp;=&nbsp;null;&nbsp;
28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServletConfig&nbsp;config&nbsp;=&nbsp;null;&nbsp;
29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JspWriter&nbsp;out&nbsp;=&nbsp;null;&nbsp;
30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;page&nbsp;=&nbsp;this;&nbsp;
31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JspWriter&nbsp;_jspx_out&nbsp;=&nbsp;null;&nbsp;
32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
34&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;
35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_jspxFactory&nbsp;=&nbsp;JspFactory.getDefaultFactory();&nbsp;
36&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.setContentType("text/html");&nbsp;
37&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pageContext&nbsp;=&nbsp;_jspxFactory.getPageContext(this,&nbsp;request,&nbsp;response,&nbsp;
38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;null,&nbsp;true,&nbsp;8192,&nbsp;true);&nbsp;
39&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;application&nbsp;=&nbsp;pageContext.getServletContext();&nbsp;
40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config&nbsp;=&nbsp;pageContext.getServletConfig();&nbsp;
41&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session&nbsp;=&nbsp;pageContext.getSession();&nbsp;
42&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out&nbsp;=&nbsp;pageContext.getOut();&nbsp;
43&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_jspx_out&nbsp;=&nbsp;out;&nbsp;
44&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
45&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&lt;HTML&gt;&nbsp;&nbsp;&nbsp;&nbsp;\r\n");&nbsp;
46&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&lt;HEAD&gt;&nbsp;&nbsp;&nbsp;&nbsp;\r\n");&nbsp;
47&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&lt;TITLE&gt;Hello&nbsp;Example");&nbsp;
48&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&lt;/TITLE&gt;&nbsp;&nbsp;&nbsp;&nbsp;\r\n");&nbsp;
49&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&lt;/HEAD&gt;&nbsp;&nbsp;&nbsp;&nbsp;\r\n");&nbsp;
50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&lt;BODY&gt;&nbsp;&nbsp;&nbsp;&nbsp;\r\n");&nbsp;
51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("Hello&nbsp;There!");&nbsp;
52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&lt;P&gt;&nbsp;&nbsp;&nbsp;&nbsp;\r\nGoodbye&nbsp;on&nbsp;");&nbsp;
53&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(String.valueOf(&nbsp;new&nbsp;java.util.Date()&nbsp;));&nbsp;
54&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&nbsp;&nbsp;\r\n");&nbsp;
55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&nbsp;&nbsp;&nbsp;&nbsp;\r\n");&nbsp;
56&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&lt;/BODY&gt;&nbsp;&nbsp;&nbsp;&nbsp;\r\n");&nbsp;
57&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write("&lt;/HTML&gt;&nbsp;&nbsp;\r\n");&nbsp;
58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Throwable&nbsp;t)&nbsp;{&nbsp;
59&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!(t&nbsp;instanceof&nbsp;javax.servlet.jsp.SkipPageException)){&nbsp;
60&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out&nbsp;=&nbsp;_jspx_out;&nbsp;
61&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(out&nbsp;!=&nbsp;null&nbsp;&amp;&amp;&nbsp;out.getBufferSize()&nbsp;!=&nbsp;0)&nbsp;
62&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.clearBuffer();&nbsp;
63&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(pageContext&nbsp;!=&nbsp;null)&nbsp;pageContext.handlePageException(t);&nbsp;
64&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;
65&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;finally&nbsp;{&nbsp;
66&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(_jspxFactory&nbsp;!=&nbsp;null)&nbsp;_jspxFactory.releasePageContext&nbsp;(&nbsp;pageContext);&nbsp;
67&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;
68&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;
69&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</pre>
</div>
<br>　　Tomcat&nbsp;又将这个&nbsp;JAVA&nbsp;代码编译为&nbsp;Hello_jsp.class，他们位于：&nbsp;$Tomcat_install_path$\work\Standalone\localhost\_&nbsp;目录下。但是&nbsp;JSP&nbsp;文件名/行号和&nbsp;JAVA&nbsp;行号的对应表(以下简称SMAP)&nbsp;在哪里呢？答案是，它保存在&nbsp;Class&nbsp;中。如果用&nbsp;UltraEdit&nbsp;打开这个&nbsp;Class&nbsp;文件，就可以找到&nbsp;SourceDebugExtension&nbsp;属性，这个属性用来保存&nbsp;SMAP。<br><br>　　JVM&nbsp;规范定义了&nbsp;ClassFile&nbsp;中可以包含&nbsp;SourceDebugExtension&nbsp;属性，保存&nbsp;SMAP：<br><br>
<div class=code twffan="done">
<pre>SourceDebugExtension_attribute&nbsp;{&nbsp;
&nbsp;&nbsp;u2&nbsp;attribute_name_index;&nbsp;
&nbsp;&nbsp;u4&nbsp;attribute_length;&nbsp;
&nbsp;&nbsp;u1&nbsp;debug_extension[attribute_length];&nbsp;
}&nbsp;
</pre>
</div>
<br>　　我用&nbsp;javassist&nbsp;做了一个测试(javassist可是一个好东东，它可以动态改变Class的结构，JBOSS&nbsp;的&nbsp;AOP就利用了javassist，这里我们只使用它读取ClassFile的属性)<br><br>
<div class=code twffan="done">
<pre>&nbsp;
public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;Exception{&nbsp;
&nbsp;&nbsp;&nbsp;String[]files&nbsp;=&nbsp;{&nbsp;
　　　"E:\\Tomcat5_0_5\\work\\Catalina\\localhost\\_\\org\\apache\\jsp\\Hello_jsp.class",&nbsp;
&nbsp;&nbsp;&nbsp;};&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
　for(int&nbsp;k&nbsp;=&nbsp;0;&nbsp;k&nbsp;&lt;&nbsp;files.length;&nbsp;k++){&nbsp;
&nbsp;&nbsp;　&nbsp;String&nbsp;file&nbsp;=&nbsp;files[k];&nbsp;
&nbsp;&nbsp;　&nbsp;System.out.println("Class&nbsp;:&nbsp;"&nbsp;+&nbsp;file);&nbsp;
&nbsp;&nbsp;　&nbsp;ClassFile&nbsp;classFile&nbsp;=&nbsp;new&nbsp;ClassFile(new&nbsp;DataInputStream(new&nbsp;FileInputStream(file)));&nbsp;
&nbsp;&nbsp;　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;　&nbsp;AttributeInfo&nbsp;attributeInfo&nbsp;=&nbsp;classFile.getAttribute("SourceDebugExtension");&nbsp;
&nbsp;&nbsp;　&nbsp;System.out.println("attribute&nbsp;name&nbsp;:"&nbsp;+&nbsp;attributeInfo.getName()&nbsp;+&nbsp;"]\n\n");&nbsp;
&nbsp;&nbsp;　&nbsp;byte[]bytes&nbsp;=&nbsp;attributeInfo.get();&nbsp;
&nbsp;&nbsp;　&nbsp;String&nbsp;str&nbsp;=&nbsp;new&nbsp;String(bytes);&nbsp;
&nbsp;&nbsp;　&nbsp;System.out.println(str);&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;}&nbsp;
}&nbsp;
</pre>
</div>
<br>　　这段代码显示了SourceDebugExtension&nbsp;属性，你可以看到SMAP&nbsp;的内容。编译JSP后，SMAP&nbsp;就被写入&nbsp;Class&nbsp;中,&nbsp;你也可以利用&nbsp;javassist&nbsp;修改&nbsp;ClassFile&nbsp;的属性。<br><br>　　下面就是&nbsp;Hello_jsp.class&nbsp;中保存的&nbsp;SMAP&nbsp;内容:<br><br>
<div class=code twffan="done">
<pre>SMAP&nbsp;
E:\Tomcat5_0_5\work\Catalina\localhost\_\org\apache\jsp\Hello_jsp.java&nbsp;
JSP&nbsp;
*S&nbsp;JSP&nbsp;
*F&nbsp;
+&nbsp;0&nbsp;Hello.jsp&nbsp;
/Hello.jsp&nbsp;
+&nbsp;1&nbsp;greeting.jsp&nbsp;
/greeting.jsp&nbsp;
*L&nbsp;
1:45&nbsp;
2:46&nbsp;
3:47&nbsp;
3:48&nbsp;
4:49&nbsp;
5:50&nbsp;
1#1:51&nbsp;
1:52&nbsp;
2:53&nbsp;
7#0:56&nbsp;
8:57&nbsp;
*E</pre>
</div>
<br>　　首先注明JAVA代码的名称：Hello_jsp.java，然后是&nbsp;stratum&nbsp;名称：&nbsp;JSP。随后是两个JSP文件的名称&nbsp;：Hello.jsp、greeting.jsp。两个JSP文件共10行，产生的Hello_jsp共69行代码。最后也是最重要的内容就是源文件文件名/行号和目标文件行号的对应关系(*L&nbsp;与&nbsp;*E之间的部分)<br><br>　　在规范定义了这样的格式：<br><br>　　源文件行号&nbsp;#&nbsp;源文件代号,重复次数&nbsp;:&nbsp;目标文件开始行号,目标文件行号每次增加的数量&nbsp;<br>(InputStartLine&nbsp;#&nbsp;LineFileID&nbsp;,&nbsp;RepeatCount&nbsp;:&nbsp;OutputStartLine&nbsp;,&nbsp;OutputLineIncrement)<br><br>　　源文件行号(InputStartLine)&nbsp;目标文件开始行号(OutputStartLine)&nbsp;是必须的。下面是对这个SMAP具体的说明：<br><br>
<div class=code twffan="done">
<pre>&nbsp;
1:45&nbsp;&nbsp;2:46&nbsp;&nbsp;3:47&nbsp;&nbsp;3:48&nbsp;&nbsp;4:49&nbsp;&nbsp;5:50(没有源文件代号，默认为Hello.jsp)&nbsp;
　　　　　　　　　　　　　　　　　　　开始行号&nbsp;　　结束行号&nbsp;
Hello.jsp:&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;-&gt;&nbsp;&nbsp;Hello_jsp.java:&nbsp;&nbsp;&nbsp;&nbsp;45&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;-&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;46&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;-&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;47&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;48&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;-&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;49&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;-&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;50&nbsp;
1#1:51&nbsp;&nbsp;1:52&nbsp;&nbsp;2:53(1#1表示&nbsp;greeting.jsp&nbsp;的第1行)&nbsp;
greeting.jsp:&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;-&gt;&nbsp;&nbsp;Hello_jsp.java:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;52&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;-&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;53&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
7#0:56&nbsp;&nbsp;8:57(7#0表示&nbsp;Hello.jsp&nbsp;的第7行)&nbsp;
Hello.jsp:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;-&gt;&nbsp;&nbsp;Hello_jsp.java:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;56&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;-&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;57&nbsp;
</pre>
</div>
　　<strong>开发一个JSP编辑器</strong><br><br>　　Eclipse&nbsp;提供了&nbsp;TextEditor，作为文本编辑器的父类。由于&nbsp;Editor&nbsp;的开发不是本文的重点，不做具体论述。我们可以利用&nbsp;Eclipse&nbsp;的&nbsp;Plugin&nbsp;项目向导，生成一个简单的&nbsp;JSP&nbsp;编辑器：<br><br>　　(1)点击&nbsp;File&nbsp;菜单，New&nbsp;-&gt;&nbsp;Project&nbsp;-&gt;&nbsp;Plug-in&nbsp;Project&nbsp;；<br><br>　　(2)输入项目名称&nbsp;JSP_DEBUG，下一步；<br><br>　　(3)输入&nbsp;plugin&nbsp;ID&nbsp;：&nbsp;com.jsp.debug&nbsp;<br>　　　　Plugin&nbsp;Class&nbsp;name&nbsp;：&nbsp;com.jsp.debug.JSP_DebugPlugin<br><br>　　(4)选择用模板创建<br><br>　　使用&nbsp;Plug-in&nbsp;with&nbsp;editor，输入<br><br>　　Java&nbsp;Package&nbsp;Name&nbsp;：com.jsp.editors<br><br>　　Editor&nbsp;Class&nbsp;Name&nbsp;：JSPEditor<br><br>　　File&nbsp;extension&nbsp;：jsp<br><br>　　一个&nbsp;jsp&nbsp;editor&nbsp;就产生了。<br><br>　　运行这个Plugin，新建一个JAVA项目，新建一个&nbsp;Hello.jsp&nbsp;和&nbsp;greeting.jsp，在&nbsp;Navigator&nbsp;视图双击&nbsp;jsp，这个editor就打开了。<br><br>　　<strong>在JSP编辑器中设置断点</strong><br><br>　　在编辑器中添加断点的操作方式有两种，一种是在编辑器左侧垂直标尺上双击，另一种是在左侧垂直标尺上点击鼠标右键，选择菜单"添加/删除断点"。<br><br>　　在&nbsp;Eclipse&nbsp;的实现中，添加断点实际上就是为&nbsp;IFile&nbsp;添加一个marker&nbsp;，类型是IBreakpoint.BREAKPOINT_MARKER，然后将断点注册到&nbsp;BreakpointManager。<br><br>　　BreakpointManager&nbsp;将产生一个&nbsp;BreakpointRequest，通知正在运行的JVM&nbsp;Target，如果此时还没有启动&nbsp;JVM，会在&nbsp;JVM&nbsp;启动的时候，将所有断点一起通知&nbsp;JVM&nbsp;Target。<br><br>　　添加断点使用一个&nbsp;AbstractRulerActionDelegate，重载&nbsp;createAction&nbsp;方法，返回一个&nbsp;IAction&nbsp;ManageBreakpointRulerAction动作：<br><br>
<div class=code twffan="done">
<pre>public&nbsp;class&nbsp;ManageBreakpointRulerActionDelegate&nbsp;extends&nbsp;AbstractRulerActionDelegate{&nbsp;
&nbsp;protected&nbsp;IAction&nbsp;createAction(ITextEditor&nbsp;editor,&nbsp;IVerticalRulerInfo&nbsp;rulerInfo)&nbsp;{&nbsp;
&nbsp;&nbsp;return&nbsp;new&nbsp;ManageBreakpointRulerAction(rulerInfo,&nbsp;editor);&nbsp;
&nbsp;}&nbsp;
}&nbsp;
</pre>
</div>
<br>　　为了将&nbsp;ManageBreakpointRulerActionDelegate&nbsp;添加到文本编辑器左侧标尺的鼠标右键菜单，并且能够处理左侧标尺的鼠标双击事件，在&nbsp;plugin.xml&nbsp;中加入定义。<br><br>　　处理双击事件：<br><br>
<div class=code twffan="done">
<pre>&lt;extension&nbsp;&nbsp;point="org.eclipse.ui.editorActions"&gt;&nbsp;
　&lt;editorContribution&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;targetID="com.jiaoly.editors.JSPEditor"&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"&gt;&nbsp;
　　　&lt;action&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;label="添加/删除断点"&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;actionID="RulerDoubleClick"&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"&gt;&nbsp;
　　　&lt;/action&gt;&nbsp;
　&lt;/editorContribution&gt;&nbsp;
&lt;/extension&gt;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</pre>
</div>
<br>　　添加右键菜单：<br><br>
<div class=code twffan="done">
<pre>&lt;extension&nbsp;point="org.eclipse.ui.popupMenus"&gt;&nbsp;
&nbsp;&lt;viewerContribution&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;targetID="#TextRulerContext"&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"&gt;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;action&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;label="添加/删除断点"&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;menubarPath="addition"&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"&gt;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/action&gt;&nbsp;
&nbsp;&lt;/viewerContribution&gt;&nbsp;
&lt;/extension&gt;&nbsp;
</pre>
</div>
<br>　　ManageBreakpointRulerAction&nbsp;是实际添加断点的Action，实现了&nbsp;IUpdate&nbsp;接口，这个Action的工作，就是判断当前选中行是否存在断点类型的&nbsp;Marker，如果不存在创建一个，如果存在，将它删除。<br><br>
<div class=code twffan="done">
<pre>public&nbsp;class&nbsp;ManageBreakpointRulerAction&nbsp;extends&nbsp;Action&nbsp;implements&nbsp;IUpdate{&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;IVerticalRulerInfo&nbsp;rulerInfo;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;ITextEditor&nbsp;textEditor;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;BPmarkerType&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//当点Marker的类型&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;List&nbsp;allMarkers;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//当前鼠标点击行所有的Marker&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;addBP;&nbsp;&nbsp;&nbsp;//Action&nbsp;的显示名称&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
public&nbsp;ManageBreakpointRulerAction(IVerticalRulerInfo&nbsp;ruler,&nbsp;ITextEditor&nbsp;editor){&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.rulerInfo&nbsp;=&nbsp;ruler;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.textEditor&nbsp;=&nbsp;editor;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BPmarkerType&nbsp;=&nbsp;IBreakpoint.BREAKPOINT_MARKER;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addBP&nbsp;=&nbsp;"添加/删除断点";&nbsp;//$NON-NLS-1$&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setText(this.addBP);&nbsp;
}&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
public&nbsp;void&nbsp;update()&nbsp;{&nbsp;
&nbsp;&nbsp;this.allMarkers&nbsp;=&nbsp;this.fetchBPMarkerList();&nbsp;&nbsp;
}&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
public&nbsp;void&nbsp;run(){&nbsp;
&nbsp;if(this.allMarkers.isEmpty())&nbsp;
&nbsp;&nbsp;&nbsp;this.addMarker();&nbsp;
&nbsp;else&nbsp;
&nbsp;&nbsp;&nbsp;this.removeMarkers(this.allMarkers);&nbsp;
}&nbsp;
}&nbsp;
</pre>
</div>
</div>
<img src ="http://www.blogjava.net/coundy/aggbug/117628.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/coundy/" target="_blank">Coundy</a> 2007-05-15 15:50 <a href="http://www.blogjava.net/coundy/articles/117628.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>