??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲爱爱视频,www.中文字幕久久久,欧美精品一区二区不卡http://www.aygfsteel.com/coundy/category/21238.htmlzh-cnWed, 16 May 2007 03:28:52 GMTWed, 16 May 2007 03:28:52 GMT60一个调试JSP的Eclipse插g的开?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/coundy/articles/117628.html</guid><wfw:comment>http://www.aygfsteel.com/coundy/comments/117628.html</wfw:comment><comments>http://www.aygfsteel.com/coundy/articles/117628.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/coundy/comments/commentRss/117628.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/coundy/services/trackbacks/117628.html</trackback:ping><description><![CDATA[<p>【摘 要?span class=checkoutHeader twffan="done"><strong>本文通过开发一个JSP ~辑器插件的CZQ介l了 Eclipse 中设|?nbsp;JSP 断点的方法,以及(qing)如何q程调试 JSP。作为基知识Q本文的前两部分描述?nbsp;JAVA Debug ?nbsp;JSR-45 的基本原理?/strong></span> </p> <div id="wmqeeuq" class=content twffan="done">  本文通过开发一个JSP ~辑器插件的CZQ介l了 Eclipse 中设|?nbsp;JSP 断点的方法,以及(qing)如何q程调试 JSP。作为基知识Q本文的前两部分描述?nbsp;JAVA Debug ?nbsp;JSR-45 的基本原理?nbsp;<br><br>  环境要求: 本文的代码是?nbsp;Eclipse3.0.0QJDK1.4.2 ?nbsp;Tomcat5.0.5 上测试过的?br><br>  <strong>JAVA 调试框架QJPDAQ简?/strong><br><br>  JPDA 是一个多层的调试框架Q包?nbsp;JVMDI、JDWP、JDI 三个层次。JAVA 虚拟机提供了 JPDA 的实现。其开发工具作试客L(fng)Q可以方便的与虚拟机通讯Q进行调试。Eclipse 正是利用 JPDA 调试 JAVA 应用Q事实上Q所?nbsp;JAVA 开发工具都是这样做的。SUN JDK q带了一个比较简单的调试工具以及(qing)CZ?br> <ul> <li>JVMDI 定义了虚拟机需要实现的本地接口   <li>JDWP 定义了JVM与调试客L(fng)之间的通讯协议 <br><br>调试客户端和JVM 既可以在同一台机器上Q也可以q程调试。JDK ?x)包含一个默认的实现 jdwp.dllQJVM 允许灉|的用其他协议代?nbsp;JDWP。SUN JDK 有两U方式传输通讯协议QSocket 和共享内?后者仅仅针?nbsp;Windows)Q一般我们都采用 Socket 方式?br><br>你可以用下面的参敎ͼ以调试模式启动JVM<br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>  -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n    -Xrunjdwp     JVM 加蝲 jdwp.dll      transport=dt_socket   使用 Socket 传输     address      表示调试端口?nbsp;    server=y     表示 JVM 作ؓ(f)服务器,建立 Socket     suspend=n    表示启动q程中,JVM 不会(x)挂vȝ待调试客L(fng)q接</pre> </div> <br> <li>JDI 则是一lJAVA接口 <br><br>如果是一?nbsp;JAVA 的调试客L(fng)Q只要实?nbsp;JDI 接口Q利用JDWP协议Q与虚拟机通讯Q就可以调用JVMDI了?br></li> </ul>   下图?nbsp;JPDA 的基本架构:(x)<br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>                            Components                        Debugger Interface                                 /    |-----------------------|                 /     |     VM       |   debuggee ----(      |-----------------------|  <------- JVMDI - Java VM Debug Interface                 \     |   back-end     |                  \    |-----------------------|                  /           |    comm channel -(           |  <--------------- JDWP - Java Debug Wire Protocol                  \           |                       |---------------------|                       | front-end      |                       |---------------------|  <------- JDI - Java Debug Interface                       |      UI      |                       |---------------------|               </pre> </div> <br>  参见Q?a ><u>http://java.sun.com/j2se/1.4.2/docs/guide/jpda/architecture.html</u></a> <br><br>  Eclipse作ؓ(f)一个基?nbsp;JAVA 的调试客L(fng)Q利?nbsp;org.eclipse.jdt.debug Plugin 提供了JDI 的具体实现。JDI 接口主要包含下面 4 个包<br> <pre>com.sun.jdi   com.sun.jdi.connect   com.sun.jdi.event   com.sun.jdi.request </pre>   本文不对 JDI q行深入阐述Q这里重点介l?nbsp;JDI 中与断点相关的接口?br> <ul> <li>com.sun.jdi <br><br>主要是JVM(VirtualMachine) U程(ThreadReference) 调用?StackFrame) 以及(qing)cd、实例的描述。利用这l接口,调试客户端可以用cMcd的方式Q得到所有类型的定义Q动态调?nbsp;Class 的方法?nbsp;  <li>com.sun.jdi.event <br><br>装了JVM 产生的事Ӟ JVM 正是这些事仉知l调试客L(fng)的。例?nbsp;BreakpointEvent 是 JVM 执行到断点的时候,发出的事ӞClassPrepareEvent是 Class 被加载时发出的事件?nbsp;<br><br> <li>com.sun.jdi.request <br><br>装了调试客L(fng)可以?nbsp;JVM发v的请求。例?nbsp;BreakpointRequest ?nbsp;JVM 发v一个添加断点的hQClassPrepareRequest ?nbsp;JVM 注册一个类加蝲hQJVM 在加载指?nbsp;Class 的时候,׃(x)发出一?nbsp;ClassPrepareEvent 事g?nbsp;  </li> </ul>   <strong>JSR-45规范</strong><br><br>  JSR-45(Debugging Support for Other Languages)为那些非 JAVA 语言写成Q却需要编译成 JAVA 代码Q运行在 JVM 中的E序Q提供了一个进行调试的标准机制。也许字面的意思有点不好理解,什么算是非 JAVA 语言呢?其实 JSP 是一个再好不q的例子QJSR-45 的样例就是一?nbsp;JSP?br><br>  JSP的调试一直依赖于具体应用服务器的实现Q没有一个统一的模式,JSR-45 针对q种情况Q提供了一个标准的模式。我们知道,JAVA 的调试中Q主要根据行号作为标志,q行定位。但?nbsp;JSP 被编译ؓ(f) JAVA 代码之后QJAVA 行号?nbsp;JSP 行号无法一一对应Q怎样解决呢?<br><br>  JSR-45 是这栯定的QJSP 被编译成 JAVA 代码Ӟ同时生成一?nbsp;JSP 文g名和行号?nbsp;JAVA 行号之间的对应表(SMAP)。JVM 在接受到调试客户端请求后Q可以根据这个对应表(SMAP)Q从 JSP 的行可{换到 JAVA 代码的行PJVM 发出事g通知? 也根据对应表(SMAP)q行转化Q直接将 JSP 的文件名和行号通知调试客户端?br><br>  我们?nbsp;Tomcat 5.0 做个试Q有两个 JSPQHello.jsp ?nbsp;greeting.jspQ前?nbsp;include 后者。Tomcat?x)将他们~译?nbsp;JAVA 代码(Hello_jsp.java)QJAVA Class(Hello_jsp.class) 以及(qing) JSP 文g?行号?nbsp;JAVA 行号之间的对应表(SMAP)?br><br>  Hello.jsp: <br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>            1    <HTML>                2    <HEAD>                3    <TITLE>Hello Example</TITLE>                4    </HEAD>                5    <BODY>                6    <%@ include file="greeting.jsp" %>                7    </BODY>                8    </HTML>              </pre> </div> <br>  greeting.jsp: <br><br>1 Hello There!<P> 2 Goodbye on <%= new java.util.Date() %> <br><br>  JSP ~译后生的Hello_jsp.java 如下:<br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>Hello_jsp.java:  1      package org.apache.jsp;  2  3      import javax.servlet.*;  4      import javax.servlet.http.*;  5      import javax.servlet.jsp.*;  6        7      public final class Hello_jsp extends org.apache.jasper.runtime.HttpJspBase  8          implements org.apache.jasper.runtime.JspSourceDependent {  9        10        private static java.util.Vector _jspx_dependants;  11        12        static {  13          _jspx_dependants = new java.util.Vector(1);  14          _jspx_dependants.add("/greeting.jsp");  15        }  16        17        public java.util.List getDependants() {  18          return _jspx_dependants;  19        }  20        21  public void _jspService(HttpServletRequest request, HttpServletResponse response)  22              throws java.io.IOException, ServletException {  23        24          JspFactory _jspxFactory = null;  25          PageContext pageContext = null;  26          HttpSession session = null;  27          ServletContext application = null;  28          ServletConfig config = null;  29          JspWriter out = null;  30          Object page = this;  31          JspWriter _jspx_out = null;  32        33        34          try {  35            _jspxFactory = JspFactory.getDefaultFactory();  36            response.setContentType("text/html");  37            pageContext = _jspxFactory.getPageContext(this, request, response,  38               null, true, 8192, true);  39            application = pageContext.getServletContext();  40            config = pageContext.getServletConfig();  41            session = pageContext.getSession();  42            out = pageContext.getOut();  43            _jspx_out = out;  44        45            out.write("<HTML>    \r\n");  46            out.write("<HEAD>    \r\n");  47            out.write("<TITLE>Hello Example");  48            out.write("</TITLE>    \r\n");  49            out.write("</HEAD>    \r\n");  50            out.write("<BODY>    \r\n");  51            out.write("Hello There!");  52            out.write("<P>    \r\nGoodbye on ");  53            out.write(String.valueOf( new java.util.Date() ));  54            out.write("  \r\n");  55            out.write("    \r\n");  56            out.write("</BODY>    \r\n");  57            out.write("</HTML>  \r\n");  58          } catch (Throwable t) {  59            if (!(t instanceof javax.servlet.jsp.SkipPageException)){  60              out = _jspx_out;  61              if (out != null && out.getBufferSize() != 0)  62                out.clearBuffer();  63              if (pageContext != null) pageContext.handlePageException(t);  64            }  65          } finally {  66     if (_jspxFactory != null) _jspxFactory.releasePageContext ( pageContext);  67          }  68        }  69      }</pre> </div> <br>  Tomcat 又将q个 JAVA 代码~译?nbsp;Hello_jsp.classQ他们位于:(x) $Tomcat_install_path$\work\Standalone\localhost\_ 目录下。但?nbsp;JSP 文g?行号?nbsp;JAVA 行号的对应表(以下USMAP) 在哪里呢Q答案是Q它保存?nbsp;Class 中。如果用 UltraEdit 打开q个 Class 文gQ就可以扑ֈ SourceDebugExtension 属性,q个属性用来保?nbsp;SMAP?br><br>  JVM 规范定义?nbsp;ClassFile 中可以包?nbsp;SourceDebugExtension 属性,保存 SMAPQ?br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>SourceDebugExtension_attribute {    u2 attribute_name_index;    u4 attribute_length;    u1 debug_extension[attribute_length];  }  </pre> </div> <br>  我用 javassist 做了一个测?javassist可是一个好东东Q它可以动态改变Class的结构,JBOSS ?nbsp;AOP利用了javassistQ这里我们只使用它读取ClassFile的属?<br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>  public static void main(String[] args) throws Exception{     String[]files = {     "E:\\Tomcat5_0_5\\work\\Catalina\\localhost\\_\\org\\apache\\jsp\\Hello_jsp.class",     };                     for(int k = 0; k < files.length; k++){      String file = files[k];      System.out.println("Class : " + file);      ClassFile classFile = new ClassFile(new DataInputStream(new FileInputStream(file)));                   AttributeInfo attributeInfo = classFile.getAttribute("SourceDebugExtension");      System.out.println("attribute name :" + attributeInfo.getName() + "]\n\n");      byte[]bytes = attributeInfo.get();      String str = new String(bytes);      System.out.println(str);        }  }  </pre> </div> <br>  q段代码昄了SourceDebugExtension 属性,你可以看到SMAP 的内宏V编译JSP后,SMAP p写入 Class ? 你也可以利用 javassist 修改 ClassFile 的属性?br><br>  下面是 Hello_jsp.class 中保存的 SMAP 内容:<br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>SMAP  E:\Tomcat5_0_5\work\Catalina\localhost\_\org\apache\jsp\Hello_jsp.java  JSP  *S JSP  *F  + 0 Hello.jsp  /Hello.jsp  + 1 greeting.jsp  /greeting.jsp  *L  1:45  2:46  3:47  3:48  4:49  5:50  1#1:51  1:52  2:53  7#0:56  8:57  *E</pre> </div> <br>  首先注明JAVA代码的名Uͼ(x)Hello_jsp.javaQ然后是 stratum 名称Q?nbsp;JSP。随后是两个JSP文g的名U?nbsp;QHello.jsp、greeting.jsp。两个JSP文g?0行,产生的Hello_jsp?9行代码。最后也是最重要的内容就是源文g文g?行号和目标文件行L(fng)对应关系(*L ?nbsp;*E之间的部?<br><br>  在规范定义了q样的格式:(x)<br><br>  源文件行?nbsp;# 源文件代?重复ơ数 : 目标文g开始行?目标文g行号每次增加的数?nbsp;<br>(InputStartLine # LineFileID , RepeatCount : OutputStartLine , OutputLineIncrement)<br><br>  源文件行?InputStartLine) 目标文g开始行?OutputStartLine) 是必ȝ。下面是对这个SMAP具体的说明:(x)<br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>  1:45  2:46  3:47  3:48  4:49  5:50(没有源文件代P默认为Hello.jsp)                     开始行?nbsp;  l束行号  Hello.jsp:    1 ->  Hello_jsp.java:    45                2 ->                     46                3 ->                     47           48                4 ->                     49                5 ->                     50  1#1:51  1:52  2:53(1#1表示 greeting.jsp 的第1?  greeting.jsp:    1 ->  Hello_jsp.java:       51           52                   2 ->                     53             7#0:56  8:57(7#0表示 Hello.jsp 的第7?  Hello.jsp:     7 ->  Hello_jsp.java:       56                 8 ->                     57  </pre> </div>   <strong>开发一个JSP~辑?/strong><br><br>  Eclipse 提供?nbsp;TextEditorQ作为文本编辑器的父cR由?nbsp;Editor 的开发不是本文的重点Q不做具体论q。我们可以利?nbsp;Eclipse ?nbsp;Plugin 目向导Q生成一个简单的 JSP ~辑器:(x)<br><br>  (1)点击 File 菜单QNew -> Project -> Plug-in Project Q?br><br>  (2)输入目名称 JSP_DEBUGQ下一步;<br><br>  (3)输入 plugin ID Q?nbsp;com.jsp.debug <br>    Plugin Class name Q?nbsp;com.jsp.debug.JSP_DebugPlugin<br><br>  (4)选择用模板创?br><br>  使用 Plug-in with editorQ输?br><br>  Java Package Name Qcom.jsp.editors<br><br>  Editor Class Name QJSPEditor<br><br>  File extension Qjsp<br><br>  一?nbsp;jsp editor ׃生了?br><br>  q行q个PluginQ新Z个JAVA目Q新Z?nbsp;Hello.jsp ?nbsp;greeting.jspQ在 Navigator 视图双击 jspQ这个editor打开了?br><br>  <strong>在JSP~辑器中讄断点</strong><br><br>  在编辑器中添加断点的操作方式有两U,一U是在编辑器左侧垂直标尺上双击,另一U是在左侧垂直标Z点击鼠标右键Q选择菜单"d/删除断点"?br><br>  ?nbsp;Eclipse 的实CQ添加断点实际上是?nbsp;IFile d一个marker Q类型是IBreakpoint.BREAKPOINT_MARKERQ然后将断点注册?nbsp;BreakpointManager?br><br>  BreakpointManager 生一?nbsp;BreakpointRequestQ通知正在q行的JVM TargetQ如果此时还没有启动 JVMQ会(x)?nbsp;JVM 启动的时候,所有断点一起通知 JVM Target?br><br>  d断点使用一?nbsp;AbstractRulerActionDelegateQ重?nbsp;createAction Ҏ(gu)Q返回一?nbsp;IAction ManageBreakpointRulerAction动作Q?br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>public class ManageBreakpointRulerActionDelegate extends AbstractRulerActionDelegate{   protected IAction createAction(ITextEditor editor, IVerticalRulerInfo rulerInfo) {    return new ManageBreakpointRulerAction(rulerInfo, editor);   }  }  </pre> </div> <br>  Z?nbsp;ManageBreakpointRulerActionDelegate d到文本编辑器左侧标尺的鼠标右键菜单,q且能够处理左侧标尺的鼠标双MӞ?nbsp;plugin.xml 中加入定义?br><br>  处理双击事gQ?br><br> <div id="wmqeeuq" class=code twffan="done"> <pre><extension  point="org.eclipse.ui.editorActions">   <editorContribution        targetID="com.jiaoly.editors.JSPEditor"        id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate">     <action           label="d/删除断点"           class="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"           actionID="RulerDoubleClick"           id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate">     </action>   </editorContribution>  </extension>         </pre> </div> <br>  d右键菜单Q?br><br> <div id="wmqeeuq" class=code twffan="done"> <pre><extension point="org.eclipse.ui.popupMenus">   <viewerContribution       targetID="#TextRulerContext"       id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate">       <action         label="d/删除断点"         class="com.jiaoly.debug.ManageBreakpointRulerActionDelegate"         menubarPath="addition"         id="com.jiaoly.debug.ManageBreakpointRulerActionDelegate">      </action>   </viewerContribution>  </extension>  </pre> </div> <br>  ManageBreakpointRulerAction 是实际添加断点的ActionQ实C IUpdate 接口Q这个Action的工作,是判断当前选中行是否存在断点类型的 MarkerQ如果不存在创徏一个,如果存在Q将它删除?br><br> <div id="wmqeeuq" class=code twffan="done"> <pre>public class ManageBreakpointRulerAction extends Action implements IUpdate{              private IVerticalRulerInfo rulerInfo;       private ITextEditor textEditor;             private String BPmarkerType ;     //当点Marker的类?nbsp;      private List allMarkers;       //当前鼠标点击行所有的Marker       private String addBP;   //Action 的显C名U?nbsp;       public ManageBreakpointRulerAction(IVerticalRulerInfo ruler, ITextEditor editor){       this.rulerInfo = ruler;       this.textEditor = editor;       BPmarkerType = IBreakpoint.BREAKPOINT_MARKER;       addBP = "d/删除断点"; //$NON-NLS-1$       setText(this.addBP);  }        public void update() {    this.allMarkers = this.fetchBPMarkerList();   }        public void run(){   if(this.allMarkers.isEmpty())     this.addMarker();   else     this.removeMarkers(this.allMarkers);  }  }  </pre> </div> </div> <img src ="http://www.aygfsteel.com/coundy/aggbug/117628.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/coundy/" target="_blank">Coundy</a> 2007-05-15 15:50 <a href="http://www.aygfsteel.com/coundy/articles/117628.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank">齭</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">³</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank">Ԫ</a>| <a href="http://" target="_blank">鶴</a>| <a href="http://" target="_blank">Ϸ</a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ׯ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">޵</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ʯ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">׺</a>| <a href="http://" target="_blank">÷</a>| <a href="http://" target="_blank">Ϫ</a>| <a href="http://" target="_blank">е</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">߷</a>| <a href="http://" target="_blank">ǿ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">̳</a>| <a href="http://" target="_blank">˷</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͷ</a>| <a href="http://" target="_blank">°Ͷ</a>| <a href="http://" target="_blank">Ĵʡ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">⳵</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>