Jerry在2018年开始用中文在微信公众号平台上写作之前,在SAP官方社区上总共写了639篇英文博客。
其中有一篇写于2013年介绍ABAP调试技巧的博客:
Six kinds of debugging tips to find the source code where the message is raised
从2016年至今,在SAP社区上有超过十五万的阅读量。
实际的阅读量远远大于这个数字,因为2016年社区改版之后,文章阅读量清零了。
SAP社区在2016年改版前,有一个所谓的Gamification游戏化机制,博客每收到一个赞之后,作者会得到2点积分。这篇博客当时给Jerry赢得了不少社区积分。
该博客以一个实际例子,向大家介绍了Jerry多年ABAP编程生涯积累的6种错误消息调试方法。事实上Jerry实际工作中靠着这六种方法,对于我遇到形形色色的错误消息,几乎没有遇到调试不出抛出消息准确代码位置的情况,个人觉得这些方法还是相当管用的。
具体场景:在SE38里随便输入一个并不存在的程序名,点击Display按钮,显示一个提示消息。我们的任务是通过调试或者使用Netweaver提供的其他工具找到抛出这个消息的ABAP代码的准确位置。
古龙的代表作之一《七种武器》,介绍了七件令人闻风丧胆的精妙兵器,央视的《天下足球》系列也曾用这七种武器来类比足坛上那些绝世神锋们。作为古龙的粉丝,Jerry也将这七种方法用古大师的七种武器来命名,算是向他致敬。
在我国古代,剑被称作“百兵之君”,常常被当作一种高贵的装饰品,从皇帝到文人都喜欢佩剑以显示身份。在金庸和古龙的名著里,大多数江湖人物使用的兵器都是剑。
下面是Jerry用来镇bug的龙泉剑:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xe0Z7DER-1575963182475)(https://user-images.githubusercontent.com/5669954/70371257-ba59bf80-190b-11ea-8876-bdad09cc6d31.png)]
正如剑是江湖儿女使用得最多的兵器一样,我想每一位ABAP从业人员应该都用过SAPGUI里自带的Where Used List功能。
鼠标单击SE38里显示的提示消息,查看这条消息的技术明细:DS017,其中DS代表Message Class的ID,017是这条消息在Message Class里的编号。
事务码SE91, 打开DS message class,定位到第17条消息,点击这个图标使用Where Used List功能。
结果发现SAP标准程序里抛出这个消息的地方太多了。。。
这种情况下只得一条一条看了。注意我们在SE38里看到的消息显示前面有个绿灯,因此说明ABAP代码抛出这条消息时,是以类型S(Successful)投递的。这样我们只看结果列表里MESSAGE s017这种记录,对于MESSAGE E017直接忽略,因为后者抛出的消息前面显示的是红灯。
很快找到了这一条记录,但我还不能100%确认。此时双击进去,设置一个断点,然后回到SE38,再点一次Display按钮。
此时断点触发,说明ABAP include LWBABAPF00的第813行就是我要找的抛出这个提示消息的准确位置。
刀同样是一件历史非常悠久的武器,早在原始社会,古人类就用石头、蚌壳、兽骨打制成各种形状的刀。古人不仅将刀作为劳动工具,还随身携带,作为防身自卫的武器。
方法2介绍的watch point是和刀同样具有悠久历史的工具。有多古老?它伴随着SAPGUI问世的时候,Jerry的有些同事还没出生。
金庸古龙小说里,使用刀的名家也不少。金毛狮王谢逊从崆峒派那里偷了一本《七伤拳:从入门到精通》,除了七伤拳外,使用的武器就是屠龙刀。古龙小说里使刀的宗师就更多了,白天羽,傅红雪,以及手持圆月弯刀,能释放“小楼一夜听春雨”终极大招的丁鹏:
通过ABAP的关键字MESSAGE抛出消息时,系统变量SY-MSGID会自动被填充消息所属的Message Class,在Jerry这个例子里为DS,而SY-MSGNO被填充为抛出消息的编号,这个例子里为017. 因此,通过在调试器里创建watch point并维护相应的触发条件。在程序运行时,一旦触发条件满足,watch point触发,此时执行到的ABAP语句即为消息弹出的准确位置。
在命令输入栏里键入/h打开调试模式,点击Display按钮,弹出调试器:
在调试器的此处创建一个watch point:
条件维护如下,然后按F8继续程序的执行,之后调试器会自动在抛出消息的ABAP代码处停下来。
Jerry每次使用ABAP调试器里的观察点定位到我想查找的消息出处时,会感觉到丁鹏用圆月弯刀施展出“小楼一夜听春雨”将对手劈成两半的快感。
枪,百兵之王,枪长而锋利尖锐,使用灵便,枪头刃可刺可斩,可刺穿盔甲。枪在十八般武艺中比较难学,不易掌握,俗语:“年棍,月刀,久练枪”。
“一寸长,一寸强”,正因为枪的威力比棍棒等钝器强,所以我国古代很多名将都用枪,比如《三国演义》中的赵云,马超,姜维等等:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1U58um3z-1575963182484)(https://user-images.githubusercontent.com/5669954/70371220-aada7680-190b-11ea-9ed1-d7f33d65f1a9.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4GZxYkVL-1575963182486)(https://user-images.githubusercontent.com/5669954/70371222-ab730d00-190b-11ea-921a-caaa7dac4bfe.png)]
枪在这些高武力值的武将手中施展开来,小兵们望风披靡;ABAP动态断点一出,错误消息则无所遁形。
在调试器此处创建类型为ABAP Commands的动态断点,命令设置为MESSAGE. 这样,ABAP调试器会自动在所有出现了MESSAGE关键字的地方停下来。
也可以在菜单Breakpoints->Breakpoint at处创建很多其他类型的断点,相当有用。
从方法4开始介绍的消息定位方法,已经不再局限于使用ABAP调试器,而是灵活运用SAP Netweaver里提供的各种有用工具。
这双环不论套住了什么,就立刻紧紧地缠住绝不脱手,就好像一个多情的女人一样,所以名叫多情环。
Jerry在学会ABAP代码静态扫描的技能后,也被代码扫描工具深深迷住了,再也摆脱不了对它的依赖。
事务码SE93里输入SE38,找到SE38实现的ABAP程序名和所处的开发包名称。
方法4的理论依据是,既然我们在SE38里看到了DS017这条消息,那么SE38的实现代码里,必定会出现MESSAGE S017这行代码。因此在方法4里我们改变思路,不再采用动态调试的办法,而选择和它相反的思路。
使用源代码扫描工具程序RS_ABAP_SOURCE_SCAN查找SE38实现代码里所有出现了MESSAGE S017的ABAP代码位置:
不到一秒钟,就找到了准确的位置:
另一个事务码CODE_SCANNER也提供了类似的ABAP代码扫描功能,界面和RS_ABAP_SOURCE_SCAN略微有点差异。
《孔雀翎》是《七种武器》系列里Jerry最喜欢的一部,而使用SAT进行ABAP消息定位也是Jerry最喜欢的方法。
孔雀翎是个由纯金铸成、闪闪发光的圆筒,上面有两道枢纽,按下枢纽,筒里的暗器便飞射而出,据说这些暗器发出来时,美丽得就像孔雀开屏一样,辉煌灿烂,然而,就在你被这种惊人的生灵感动得目瞪神迷时,它已经要了你的性命。
李寻欢手中的小李飞刀,号称“例不虚发”,然而还是有miss的时候,在对决大欢喜女菩萨之时,没能做到一击必杀。孔雀翎则不同,在古龙笔下的设定里,它是一件命中率100%的暗器,孔雀翎面前没有任何人能逃生。
可惜最后被主人弄丢了,囧。
Jerry回忆自己的消息分析排错生涯,似乎想不起一种我使用了SAT但没能成功找到消息出处的情况出现,这说明SAT同孔雀翎一样,在查找ABAP消息抛出位置的领域里威力极大。
进入事务码SAT,创建一个新的跟踪Variant,Aggregation(聚合)记得设置为None,否则后续查看结果时将得不到期望看到的完整树形结构。
在Transaction字段里输入SE38,点击Execute按钮,这样就在跟踪模式下启动了SE38.
接着和以前一样,点击Display按钮,看到提示消息后,返回到SAT界面。这样SE38从启动到弹出提示消息,再到退出这整个过程所执行的ABAP代码都被SAT记录下来了。此时会看到一个进度条,表明SAT在格式化所记录内容的进度:
等到100%完成后,来到SAT的结果展示页面里,点击Call Hierarchy标签页,SE38执行的所有ABAP statement罗列如下。使用SAT自带的搜索按钮,输入MESSAGE S017, 执行即可得到结果。双击后就能进入对应的ABAP代码。
虽然SAT最主要的用途是用来做应用性能分析和优化的,但在Jerry介绍的这个场景里,它也起到了辅助消息定位的作用。
除此之外说句题外话,SAT的Processing Blocks界面以树形结构显示了ABAP代码的一层层调用关系,对于我们分析和学习复杂应用的执行逻辑也非常有帮助。
看下古龙原文对离别钩的介绍。
“离别钩也是种武器,也是钩。”
“既然是钩,为什么要叫做离别?”
“因为这柄钩,无论钩住什么都会造成离别。如果它钩住你的手,你的手就要和腕离别;如果它钩住你的脚,你的脚就要和腿离别。”
“如果它钩住我的咽喉,我就和这个世界离别了?”
“是的。”
“你为什么要用如此残酷的武器?”
“因为我不愿被人强迫与我所爱的人离别。”
“我明白你的意思了。”
“你真的明白?”
“你用离别钩,只不过为了要相聚。”
“是的。”
Jerry想提醒大家的是,ST05虽然同离别钩一样,能有效帮助大家的消息定位工作,但如果你在客户生产系统里打开了ST05的性能分析开关,之后忘记了关掉,那说不定你可能不得不同你的工作离别了。
ABAP从业人员在怀疑应用程序的性能瓶颈出现在数据库层面时,往往都会在事务码ST05里将数据库跟踪开关打开,在跟踪模式下重新运行应用,拿到跟踪结果以此来分析数据库的性能。
在这个例子里,Jerry用ST05跟踪SE38这个事务码的执行,能得到过程中访问过的所有数据库表的名称,和访问它们的性能。
为什么Jerry要弄清楚SE38到底访问了哪些数据库表?根据经验推断,我们在SE38里输入程序的名称点击Display按钮后,SE38的实现必定会从某个数据库表(即Netweaver里存储所有ABAP程序名称的数据库表)里根据该名称进行搜索,如果搜索未命中,说明该程序并不存在,从而抛一条消息给用户。
换言之,SE38里根据用户输入去数据库表里使用OPEN SQL进行查询,和抛出提示消息,这两处代码的位置一定相邻。因此我们只要找到了SE38里查询报表名称的数据库表的位置,那么距离抛出提示消息的代码位置也不远了。
对于SE38里访问数据库表的性能,Jerry是毫不关心的,直接忽略。在ST05的结果列表里,我只盯着Object Name里显示的数据库表名称,PROGDIR在里面太显眼了。这张表存放的就是所有ABAP程序的名称,右边的就是访问该表的ABAP OPEN SQL:
SELECT WHERE ''NAME" = ‘ASDASDD’ AND “STATE” = ‘A’.
我之前在ST05跟踪模式下随便输了个程序名ASDASDD, 所以SE38试图到表PROGDIR里查找一个名叫ASDASDD且状态为激活状态(A-Activated)的程序。
点击上图的Display按钮,就能看到访问数据库表PRODDIR的代码了,位于第774行:
鼠标稍稍往下滑动一下,第813行就是我们要找到抛出提示消息的代码位置。两个挨得确实够近吧?
其他六种武器都是金属制成,唯独拳头,乃血肉之躯构成。可能因为这种原因,拳在金庸的小说里出镜率不高,七伤拳算是比较著名的拳术之一。
五行之气调阴阳,损心伤肺摧肝肠。 藏离精失意恍惚,三焦齐逆兮魂魄飞扬!
人体内有阴阳二气、肺属金、肝属木、肾属水、心属火、脾属土五行,所谓「七伤」,便是这七种伤害。
掌握了七伤拳的人,可以同时发出或刚猛或阴柔的不同劲力,摧伤敌人脏腑,拳力复杂,吞吐闪烁,变幻万端,威力惊人。但这套神妙的拳法,伤敌力强,伤己也重,每练一次,内脏便受一次损伤,这就是“一练七伤,七者皆伤。先伤己,后伤敌”的来历。
同样,当遇到我们难以定位的消息时,我们可以直接使用搜索引擎,或者向自己认识的专家求助。
Jerry试着在百度里搜索DS 017,还真找到一篇相关文章:
来自简书社区名叫“三月行者”的朋友,真的很感谢他不辞辛劳地把我那篇英文博客翻译成了中文:
这是他的简书地址:https://www.jianshu.com/p/4aae58102043
使用七伤拳的武者,固然可以发出或刚猛、或阴柔、或刚中有柔,或柔中有刚,或横出,或直送,或内缩这七种不同的内劲,达到迅速克敌制胜的效果,然而自身也会受到七伤拳的反噬。
同样,使用搜索引擎或者求助专家,固然可以迅速解决眼前的问题,但可能失去了利用这个问题提升自己能力的机会,所以大家使用这种方法之前一定要慎重考虑。
《宋史·岳飞传》:“阵而后战,兵法之常;运用之妙,存乎一心。” ABAP Netweaver里给我们提供了大量的工具,祝愿大家都能够灵活运用这些工具,充分挖掘它们的潜力,来解决实际问题。感谢大家阅读。
更多阅读
Jerry的ABAP, Java和JavaScript乱炖
ABAP开发人员未来应该学些什么
Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现
Jerry的ABAP原创技术文章合集
300行ABAP代码实现一个最简单的区块链原型
使用Java+SAP云平台+SAP Cloud Connector调用ABAP On-Premise系统里的函数
在SAP云平台的CloudFoundry环境下消费ABAP On-Premise OData服务
ABAP vs Java, 蛙泳 vs 自由泳
聊聊C语言和ABAP
动手使用ABAP Channel开发一些小工具,提升日常工作效率
我用ABAP做过的那些无聊的事情
不喜欢SAP GUI?那试试用Eclipse进行ABAP开发吧
使用Visual Studio Code编写和激活ABAP代码
你的ABAP程序给佛祖开过光么?来试试Jerry这个小技巧
在SAP云平台ABAP编程环境上编写第一段ABAP程序
SAP官方发布的ABAP编程规范
ABAP Code Inspector那些隐藏的功能,您都知道吗?
还在用ABAP进行SAP产品的二次开发?来了解下这种全新的二次开发理念吧
ABAP Netweaver体内的那些寄生式编程语言
从SAP社区上的一篇博客开始,聊聊SAP产品命名背后的那份情怀
云端的ABAP Restful服务开发
如何在SAP云平台ABAP编程环境里把CDS view暴露成OData服务
使用abapGit在ABAP On-Premises系统和SAP云平台ABAP环境之间进行代码传输
30分钟用Restful ABAP Programming模型开发一个支持增删改查的Fiori应用
Jerry带您了解Restful ABAP Programming模型系列之二:Action和Validation的实现
Jerry带您了解Restful ABAP Programming模型系列之三:云端ABAP应用调试
SAP云平台上的ABAP编程环境里如何消费第三方服务
ABAP开发者上云的时候到了 - 现在大家可以免费使用SAP云平台ABAP环境的试用版了
学而不思则罔 - SAP云平台ABAP编程环境的由来和适用场景
SAP云平台里的三叉戟应用
如何基于Restful ABAP Programming模型开发并部署一个支持增删改查的Fiori应用
SAP 2019 TechEd Key Note解读:云时代下SAP从业人员如何做二次开发?
有哪些ABAP关键字和语法,到了ABAP云环境上就没办法用了?
ABAP开发环境终于支持以驼峰命名法自动格式化ABAP变量名了
利用ABAP 740的新关键字REDUCE完成一个实际工作任务
一段让人瑟瑟发抖的ABAP代码
昨日万圣节ABAP怪兽级代码谜团,公布答案啦
介绍一种在ABAP内核态进行内表高效拷贝的方法
使用SAP Cloud Application Programming模型开发OData的一个实际例子
当ABAP遇见普罗米修斯
使用ABAP绘制可伸缩矢量图
ABAP开发环境语法高亮的那些事儿
要获取更多Jerry的原创文章,请关注公众号"汪子熙":