天天看点

ABAP调试器的一些高级用法

ABAP调试器的一些高级用法

✦图|网络侵权必删✦文|AZSAP ✦编辑|AZSAP

如果说ABAP开发顾问是驰骋沙场的士兵,那么ABAP调试器无疑就是这些战士手中的武器了。战士们熟悉自己手中枪械的性能和参数,能够提高自己在战场上的生存指数。

相应的,ABAP顾问如果能花费一些时间更深入了解自己每天都几乎会使用到的调试器,可以提高ABAP问题排查的效率,在面对一些比较复杂问题时,能够更加从容。

ABAP调试器的一些高级用法

根据二八定律(帕累托法则), ABAP开发顾问80%的时候只使用到了ABAP调试器20%的功能,便足以胜任日常的排错工作。但假设您想让自己的ABAP技艺更上一层楼,那么花费些时间去研究ABAP调试器一些高级技巧,或许是一个好的选择。

本文会介绍ABAP调试器一些不被大众注意到的功能,这些功能倘若善加利用,会大大提升ABAP问题排查的效率。

本文的读者是对ABAP调试器已经有所了解,但是想更进一步的ABAP开发顾问们。

1

ABAP调试器的条件断点

可以说任意一个ABAP程序里都免不了出现内表的身影,而内表最常见的操作就是循环(LOOP), 在循环体内对内表每一行元素逐一处理。

在问题排查时,我们经常面临的一个需求就是单步调试内表某一次具体循环的执行逻辑。

我们使用一个很简单的报表来模拟这种需求。

ABAP调试器的一些高级用法

上图变量lt_data是包含了1000个整数的内表。

假设我只希望单步调试LOOP的第22次循环,即上图第15行代码的断点,只有当LOOP执行到第22次时才会触发。

最笨的办法,就是在第14行设置断点,然后进行21次单步调试,走完前21次循环,然后进入第22次,也就是我们需要仔细调试的循环体。这种办法无疑太低效了。如果需求不是调试第22次循环而是第999次,难道我们要重复进行前998次不必要的单步调试?

下面介绍3种不同的条件断点解决方案。

1

方案1:使用ABAP调试器自带的条件断点功能

假设上图的例子里,我希望循环体内的第15行,当<data>等于22时触发断点。

在此处创建一个新的动态断点:

ABAP调试器的一些高级用法

维护该断点触发的条件,下图语义是:当第15行的<data> = 22时,期望触发断点。

ABAP调试器的一些高级用法

我们来测试一下。执行程序,设在第14行的断点触发。然后按F8,当<data>的值在循环体内被赋以22时,我们设置的条件断点触发了:

ABAP调试器的一些高级用法

2

方案2:使用ABAP调试器的观察点

使用下图的菜单创建观察点:

ABAP调试器的一些高级用法

我们同样需要维护观察点的触发条件。因为ABAP帮助文档告诉我们,每次LOOP循环体执行时,系统变量sy-tabix都会递增1。那么当sy-tabix等于22时,说明循环体已经执行了我们期望的次数。因此将观察点触发的条件设置为sy-tabix = 22即可。

ABAP调试器的一些高级用法

3

方案3:使用ABAP调试器脚本

这种方案较之前两种方案来说最复杂,但也最灵活。

切换到ABAP调试器的Script标签页,创建一个新的脚本:

ABAP调试器的一些高级用法

我们不用从零开始开发脚本。点击Script向导按钮, 双击选项Variable Value(for Simple Variable):

ABAP调试器的一些高级用法

这个向导会根据我们刚才选择的脚本模板,自动生成一些脚本源代码,也就是下图红色方框内的代码。

ABAP调试器的一些高级用法

我们需要做的事情就是编写第51行到第53行的代码:

IF lv_result = 22.

   me->break().

ENDIF.

这段ABAP脚本的作用是,先使用从第42行代码开始的ABAP调试器脚本API获取ABAP程序里名称为<DATA>的变量值,存放到临时变量lv_result里。如果lv_result的值为22,说明循环体已经执行了第22次,因此使用ABAP调试脚本API,即break方法触发断点。

点击按钮"Save As"保存这段脚本并给其取个名字,例如ZJERRY_TEST。

再次启动您的程序,加载刚才保存的调试器脚本ZJERRY_TEST。

ABAP调试器的一些高级用法

然后点击下面的Start Script按钮:

ABAP调试器的一些高级用法

断点同样会自动停下来:

ABAP调试器的一些高级用法

由于ABAP调试器脚本允许做一些简单的ABAP编程,因此我们可以充分发挥我们的想象力,使用脚本来提高我们调试的效率。

2

ABAP调试器脚本调试实例

看一个用ABAP调试器脚本提高调试效率的实际例子。

SAP CRM开发顾问,在调试器里想查看一个BOL实例的属性(Attribute)时,需要总共双击5次鼠标才能完成。

ABAP调试器的一些高级用法

实际上,我们可以把这五次鼠标双击操作完成的事情,用ABAP调试器脚本来实现,这样只需要执行一次脚本,就能将BOL实例的属性显示在ABAP调试器里,显示效果如下图:

ABAP调试器的一些高级用法

详细步骤,参考Jerry Wang的SAP社区博客:

Use ABAP debugger script to view BOL entity content in an efficient way

​​https://blogs.sap.com/2016/11/03/use-abap-debugger-script-to-view-bol-entity-content-in-an-efficient-way/​​

使用异常断点快速定位抛出异常的ABAP代码位置

我们还是以一个实际的调试案例来介绍这个调试技巧。

下图是SAP CRM的WebUI,大家能发现第一行记录的最后一列Associated Object为空。经过确认,在后台数据库表里存在该列对应的记录,那么引起这个问题的根源一定是从数据库读出该条记录后进行渲染时发生了异常。

ABAP调试器的一些高级用法

因为使用事务码ST22没有查找到对应的dump记录,说明运行时抛出的异常被框架捕捉到了。然而UI并没有任何错误消息显示,在这种没有任何线索的情况下,如何才能高效找出准确的抛出异常的ABAP代码位置?

我们知道CRM WebClient UI表格的每一列的渲染代码的入口都是形如GET_<属性名>的方法,因此在表格最后一列对应的GET方法里设置断点。

ABAP调试器的一些高级用法

断点触发后,最笨的办法就是从GET方法开始单步调试,直至找到抛出异常的那一行代码为止。这样做无疑很费时。

幸运的是,ABAP调试器针对这种情况已经给我们提供了强大的支持。在调试器里创建一个类型为Exception的断点,Exception类型设置为CX_ROOT。这样,运行时凡是有异常发生,断点会自动触发。

ABAP调试器的一些高级用法

我们设置好类型为CX_ROOT的断点后,不需要单步调试,直接按F8继续程序的执行,最后断点会自动停到有CX_ROOT异常发生的地方。

下图说明了第一行最后一列没有内容显示的原因,从技术上来说是因为运行时发生了一个CX_SY_NO_HANDLER异常,即Java里的NullPointer(空指针)异常。

ABAP调试器的一些高级用法

但直到此时,我们仅仅找到了这个异常被捕捉的地方,而并不是抛出异常的原始位置。

不用担心,点击调试器里的按钮"Display Trigger Location", ABAP调试器就会自动把抛出异常的代码所在的方法显示出来。这样,我们只需要在该方法设置断点,单步调试即可。这种方式避免了我们花费大量时间去单步调试和问题根源没有任何联系的框架代码。

ABAP调试器的一些高级用法

快速定位到抛出指定消息的代码位置

如果代码运行过程中抛出了一个消息,我们想查找到底是哪行代码抛出的该消息,有很多种办法可以实现该目的。

很多朋友喜欢通过单击消息,在弹出窗口点击"Technical Information"查看消息的ID和序号:

ABAP调试器的一些高级用法

然后到事务码SE93里通过Where Used List静态查找的方式,获得一个抛出该消息的所有ABAP代码清单。

这种方法确实能奏效,但有时您会发现有大量的ABAP代码都会抛出该消息,这种情况下要么您耐心地在这些ABAP代码里都设置上断点,然后在运行时观察到底哪一个断点触发了;要么根据自己的经验把清单里的一些结果筛掉。

实际上,ABAP调试器早就为我们提供了这种调试场景的支持。使用下图菜单,创建一个基于特定消息的动态断点:

ABAP调试器的一些高级用法

此处维护好消息的ID,序号和类型:

ABAP调试器的一些高级用法

一旦运行时确实有代码抛出这个特定的消息,断点会自动触发,停在抛出消息的那一行,根本不需要我们手动调试:

ABAP调试器的一些高级用法

3

ABAP宏的调试

很多高级语言的宏都是无法调试的,然而ABAP是个例外。

要打开ABAP宏的调试界面,首先点击Services按钮:

ABAP调试器的一些高级用法

在弹出窗口点击ABAP Byte Code(Debug Marco)即可。

ABAP调试器的一些高级用法

比如我写了一个名为insert_table的宏,在宏的实现体里,第12行先检查传入宏的第一个参数长度是否大于等于5, 如果确实是,将该参数插入一个由第二个参数指定的内表里。

ABAP调试器的一些高级用法

当我们使用上述宏调试菜单开始调试后,首先调试的是STRLEN指令,即上述代码第12行的strlen(&1)操作。而下图23行的IF,CHECK指令,对应的就是宏实现体12行的CHECK strlen(&1) >= 5。

ABAP调试器的一些高级用法

关于这个ABAP宏调试例子的详细讲解,参考Jerry Wang的SAP博客:

Single step debugging on Macro

​​https://blogs.sap.com/2013/11/17/single-step-debugging-on-macro/​​

ABAP调试器和其他辅助工具的联合使用

事务码SAT是ABAP顾问经常使用的一个性能分析工具。

大家用的最多的就是直接在SAP GUI里使用事务码,报表和函数三种启动方式来测量一段ABAP程序的性能。

ABAP调试器的一些高级用法

但是如果需要分析的这段ABAP代码只能够通过浏览器在前端启动,此时就不能直接在后台SAT事务码里打开性能跟踪模式了。

这种情况下就需要ABAP调试器和SAT协同工作了。在ABAP调试器里打开SAT的跟踪模式。

在调试器此处双击,打开调试器里的SAT界面:

ABAP调试器的一些高级用法

双击这个小灯,开启SAT的跟踪模式:

ABAP调试器的一些高级用法

开启之后,SAT选项前面的小灯从红色变成绿色,提示您SAT已经进入跟踪模式:

ABAP调试器的一些高级用法

在调试器里运行完需要进行性能分析的代码之后,再双击小灯以关闭跟踪模式,之后就会自动生成一个包含了SAT性能分析的文件。下列图标提示了该结果文件的成功生成。

ABAP调试器的一些高级用法

关于ABAP调试器和SAT的配合使用的更详细描述,请参考Jerry Wang的SAP社区博客:

Do SAT trace on applications which could not be launched by SAT

​​https://blogs.sap.com/2015/07/11/do-sat-trace-on-applications-which-could-not-be-launched-by-sat/​​

类似这种在调试器里即时打开/关闭某个功能的跟踪状态的用法还有很多,又比如内存分析的打开/关闭:

ABAP调试器的一些高级用法

通过上述菜单创建的内存分析结果文件,可以直接在事务码S_MEMORY_INSPECTOR里打开并查看。

最后,授人以鱼不如授人以渔。ABAP调试器本身就自带了很多调试技巧的说明文档,可通过这个菜单访问:

ABAP调试器的一些高级用法

推荐每位ABAP开发顾问都花一点点时间浏览这些文档:

ABAP调试器的一些高级用法
ABAP调试器的一些高级用法

您在每天工作中还使用过什么其他有用的ABAP调试器技巧呢?欢迎留言,与大家分享。感谢阅读。

继续阅读