远程调试方法、装置、设备及存储介质与流程

文档序号:23697051发布日期:2021-01-23 11:02阅读:98来源:国知局
远程调试方法、装置、设备及存储介质与流程

[0001]
本申请涉及计算机技术领域,具体而言,涉及一种远程调试方法、装置、设备及存储介质。


背景技术:

[0002]
随着计算机技术的快速发展,软件应用的种类越来越多,用户将软件应用安装在用户终端上,以实现不同领域、不同问题的应用需求,例如,购物、游戏、视频等。
[0003]
现有技术中,用户在使用软件应用的过程中往往会出现一些问题,例如,闪退、卡顿、页面白屏等,开发人员为了解决用户问题,需要对用户问题进行复现、排查以定位问题出现的原因,通常采用apm sdk的方法捕捉软件应用运行的异常状态上报,从而定位崩溃和卡顿的问题。
[0004]
然而,上述方法只能定位出性能问题,无法定位出一些非性能问题,非性能问题例如可以为用户反馈的页面白屏、加载失败、游戏图像显示错误等。


技术实现要素:

[0005]
本申请的目的在于,针对上述现有技术中的不足,提供一种远程调试方法、装置、设备及存储介质,以实现对用户问题的定位。
[0006]
为实现上述目的,本申请实施例采用的技术方案如下:
[0007]
第一方面,本申请一实施例提供了一种远程调试方法,所述方法包括:
[0008]
接收调试设备发送的调试指令,所述调试指令为针对目标应用程序的用户问题的调试指令,所述调试指令中包括至少一个断点的标识;
[0009]
若所述目标应用程序运行到所述至少一个断点中的任一断点,获取所述断点的调试信息;
[0010]
向所述调试设备发送所述调试信息,所述调试设备用于根据所述调试信息对所述目标应用程序进行调试。
[0011]
可选地,所述若所述目标应用程序运行到所述至少一个断点中的任一断点,获取所述断点的调试信息,包括:
[0012]
若所述目标应用程序运行到所述断点,获取所述断点对应的执行信息,所述执行信息用于指示所述断点在所述源代码中的位置;
[0013]
根据所述执行信息获取所述断点的调用栈;
[0014]
获取所述调用栈中栈顶变量的参数值,所述栈顶变量为所述调用栈中栈顶的变量;
[0015]
将所述栈顶变量的参数值确定为所述调试信息。
[0016]
可选地,所述获取所述调用栈中栈顶变量的参数值,包括:
[0017]
若所述栈顶变量的数据类型为第一数据类型,采用参数获取指令,获取所述栈顶变量的参数值。
[0018]
可选地,所述获取所述调用栈中栈顶变量的参数值,包括:
[0019]
若所述栈顶变量的数据类型为第二数据类型,采用引用信息获取指令,获取所述栈顶变量的引用信息;
[0020]
根据所述引用信息获取所述栈顶变量对应的字段;
[0021]
采用字段参数获取指令,获取所述字段的参数值;
[0022]
将所述字段的参数值确定为所述栈顶变量的参数值。
[0023]
可选地,所述接收调试设备发送的调试指令之前,还包括:
[0024]
根据接收的调试设备发送的类引用标识获取指令,获取指令获取类引用标识,并向所述调试设备发送所述类引用标识,其中,所述类引用标识获取指令中包括所述用户问题在源代码中对应的类签名;
[0025]
根据接收的调试设备发送的方法标识获取指令,获取所述类引用标识对应的至少一个方法标识,并向所述调试设备发送所述至少一个方法标识,其中,所述方法标识获取指令中包括所述类引用标识;
[0026]
根据接收的调试设备发送的断点标识获取指令,获取至少一个断点的标识,并向所述调试设备发送所述至少一个断点的标识,其中,所述断点标识获取指令中包括所述类引用标识、所述至少一个方法标识中的目标方法标识以及所述目标方法标识对应的预设代码行的标识。
[0027]
可选地,所述执行信息包括以下信息中的至少一个:
[0028]
所述断点对应的事件类型、所述断点在所述至少一个断点中的标识号、所述断点所在的线程号、所述断点在对应调用栈中的位置信息。
[0029]
可选地,所述接收调试设备发送的调试指令,包括:
[0030]
通过所述客户端中的调试器接收所述调试指令,所述调试器用于根据预设交互协议对所述调试指令进行组包,将组包后的调试指令发送给所述客户端中的虚拟机。
[0031]
可选地,所述通过所述客户端中的调试器接收所述调试指令,包括:
[0032]
根据接收的远程调试的开启操作,开启所述客户端的远程调试功能;
[0033]
在所述客户端开启远程调试功能、且所述调试器和所述虚拟机握手成功时,通过所述客户端中的调试器接收所述调试指令。
[0034]
可选地,所述向所述调试设备发送所述调试信息,包括:
[0035]
通过所述虚拟机将所述调试信息发送给所述调试器,所述调试器用于根据预设交互协议对所述调试信息进行解包,并将解包后的调试信息发送给所述调试设备。
[0036]
第二方面,本申请另一实施例提供了一种远程调试方法,应用于调试设备,所述方法包括:
[0037]
在所述目标应用程序的源代码中设置针对所述目标应用程序的用户问题对应的至少一个断点;
[0038]
根据所述至少一个断点的标识获取调试指令,并向客户端发送针对所述调试指令;
[0039]
接收所述客户端发送的所述至少一个断点中的任一断点的调试信息;
[0040]
根据所述调试信息对所述目标应用程序进行调试,以对所述用户问题进行定位。
[0041]
可选地,所述在所述目标应用程序的源代码中设置针对所述目标应用程序的用户
问题对应的至少一个断点,包括:
[0042]
获取所述用户问题在源代码中对应的类签名,向所述客户端发送类引用标识获取指令,所述类引用标识获取指令中包括所述类签名;
[0043]
接收所述客户端发送的类引用标识,并向所述客户端发送方法标识获取指令,所述方法标识获取指令中包括所述类引用标识;
[0044]
接收所述客户端发送的所述类引用标识对应的至少一个方法标识,从所述至少一个方法标识中确定目标方法标识;
[0045]
向所述客户端发送断点标识获取指令,所述断点标识获取指令中包括所述类引用标识、所述目标方法标识以及所述目标方法标识对应的预设代码行的标识;
[0046]
根据接收的至少一个断点的标识,在所述源代码中设置所述用户问题对应的至少一个断点。
[0047]
第三方面,本申请另一实施例提供了一种远程调试装置,所述装置包括:
[0048]
接收模块,用于接收调试设备发送的调试指令,所述调试指令为针对目标应用程序的用户问题的调试指令,所述调试指令中包括至少一个断点的标识;
[0049]
处理模块,用于根据所述调试指令,在所述目标应用程序的源代码中设置所述用户问题对应的至少一个断点;
[0050]
获取模块,用于在所述目标应用程序运行到所述至少一个断点中的任一断点时,获取所述断点的调试信息;
[0051]
发送模块,用于向所述调试设备发送所述调试信息,所述调试设备用于根据所述调试信息对所述目标应用程序进行调试。
[0052]
可选地,获取模块,具体用于:
[0053]
若所述目标应用程序运行到所述断点,获取所述断点对应的执行信息,所述执行信息用于指示所述断点在所述源代码中的位置;
[0054]
根据所述执行信息获取所述断点的调用栈;
[0055]
获取所述调用栈中栈顶变量的参数值,所述栈顶变量为所述调用栈中栈顶的变量;
[0056]
将所述栈顶变量的参数值确定为所述调试信息。
[0057]
可选地,获取模块,具体用于:
[0058]
若所述栈顶变量的数据类型为第一数据类型,采用参数获取指令,获取所述栈顶变量的参数值。
[0059]
可选地,获取模块,具体用于:
[0060]
若所述栈顶变量的数据类型为第二数据类型,采用引用信息获取指令,获取所述栈顶变量的引用信息;
[0061]
根据所述引用信息获取所述栈顶变量对应的字段;
[0062]
采用字段参数获取指令,获取所述字段的参数值;
[0063]
将所述字段的参数值确定为所述栈顶变量的参数值。
[0064]
可选地,获取模块,还用于:
[0065]
根据接收的调试设备发送的类引用标识获取指令,获取指令获取类引用标识,并向所述调试设备发送所述类引用标识,其中,所述类引用标识获取指令中包括所述用户问
题在源代码中对应的类签名;
[0066]
根据接收的调试设备发送的方法标识获取指令,获取所述类引用标识对应的至少一个方法标识,并向所述调试设备发送所述至少一个方法标识,其中,所述方法标识获取指令中包括所述类引用标识;
[0067]
根据接收的调试设备发送的断点标识获取指令,获取至少一个断点的标识,并向所述调试设备发送所述至少一个断点的标识,其中,所述断点标识获取指令中包括所述类引用标识、所述至少一个方法标识中的目标方法标识以及所述目标方法标识对应的预设代码行的标识。
[0068]
可选地,所述执行信息包括以下信息中的至少一个:
[0069]
所述断点对应的事件类型、所述断点在所述至少一个断点中的标识号、所述断点所在的线程号、所述断点在对应调用栈中的位置信息。
[0070]
可选地,接收模块,具体用于:
[0071]
通过所述客户端中的调试器接收所述调试指令,所述调试器用于根据预设交互协议对所述调试指令进行组包,将组包后的调试指令发送给所述客户端中的虚拟机。
[0072]
可选地,接收模块,具体用于:
[0073]
根据接收的远程调试的开启操作,开启所述客户端的远程调试功能;
[0074]
在所述客户端开启远程调试功能、且所述调试器和所述虚拟机握手成功时,通过所述客户端中的调试器接收所述调试指令。
[0075]
可选地,发送模块,具体用于:
[0076]
通过所述虚拟机将所述调试信息发送给所述调试器,所述调试器用于根据预设交互协议对所述调试信息进行解包,并将解包后的调试信息发送给所述调试设备。
[0077]
第四方面,本申请另一实施例提供了一种远程调试装置,所述装置包括:
[0078]
处理模块,用于在所述目标应用程序的源代码中设置针对所述目标应用程序的用户问题对应的至少一个断点;
[0079]
发送模块,用于根据所述至少一个断点的标识获取调试指令,并向客户端发送针对所述调试指令;
[0080]
接收模块,用于接收所述客户端发送的所述至少一个断点中的任一断点的调试信息;
[0081]
所述处理模块,还用于根据所述调试信息对所述目标应用程序进行调试,以对所述用户问题进行定位。
[0082]
可选地,处理模块,具体用于:
[0083]
获取所述用户问题在源代码中对应的类签名,向所述客户端发送类引用标识获取指令,所述类引用标识获取指令中包括所述类签名;
[0084]
接收所述客户端发送的类引用标识,并向所述客户端发送方法标识获取指令,所述方法标识获取指令中包括所述类引用标识;
[0085]
接收所述客户端发送的所述类引用标识对应的至少一个方法标识,从所述至少一个方法标识中确定目标方法标识;
[0086]
向所述客户端发送断点标识获取指令,所述断点标识获取指令中包括所述类引用标识、所述目标方法标识以及所述目标方法标识对应的预设代码行的标识;
[0087]
根据接收的至少一个断点的标识,在所述源代码中设置所述用户问题对应的至少一个断点。
[0088]
第五方面,本申请另一实施例提供了一种客户端设备,包括:处理器、存储器和收发器;所述收发器用于接收和发送数据;所述存储器中存储有所述处理器的可执行指令;其中,所述处理器配置为经由执行所述可执行指令来实现第一方面任一项所述的方法。
[0089]
第六方面,本申请另一实施例提供了一种调试设备,包括:处理器、存储器和收发器;所述收发器用于接收和发送数据;所述存储器中存储有所述处理器的可执行指令;其中,所述处理器配置为经由执行所述可执行指令来实现第二方面任一项所述的方法。
[0090]
第七方面,本申请另一实施例提供了一种计算机可读存储介质,所述计算机可读存储介质中存储有计算机指令,当所述计算机指令被执行时,实现第一方面和第二方面任一项所述的方法。
[0091]
本申请提供的远程调试方法、装置、设备及存储介质,该方法包括:调试设备在目标应用程序的源代码中设置针对目标应用程序的用户问题对应的至少一个断点,调试设备根据至少一个断点的标识获取调试指令,并向客户端发送针对调试指令,若目标应用程序运行到至少一个断点中的任一断点,客户端获取断点的调试信息,向调试设备发送调试信息,调试设备根据调试信息对目标应用程序进行调试,以对用户问题进行定位。在本申请中,根据用户问题设置对应的断点,根据该断点处的调试信息对目标应用程序进行调试,从而可以从源代码角度定位出用户问题的确切源头和具体原因。
附图说明
[0092]
为了更清楚地说明本申请实施例的技术方案,下面将对实施例中所需要使用的附图作简单地介绍,应当理解,以下附图仅示出了本申请的某些实施例,因此不应被看作是对范围的限定,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他相关的附图。
[0093]
图1示出了本申请实施例提供的jpda调试的架构示意图;
[0094]
图2示出了本申请实施例提供的远程调试的系统架构图;
[0095]
图3示出了本申请实施例提供的远程调试方法的流程示意图一;
[0096]
图4示出了本申请实施例提供的目标应用程序运行到断点的场景示意图;
[0097]
图5示出了本申请实施例提供的远程调试方法的流程示意图二;
[0098]
图6示出了本申请实施例提供的远程调试方法的流程示意图三;
[0099]
图7示出了本申请实施例提供的远程调试方法的流程示意图四;
[0100]
图8示出了本申请实施例提供的目标应用程序的设置界面示意图;
[0101]
图9示出了本申请实施例提供的远程调试装置的结构示意图一;
[0102]
图10示出了本申请实施例提供的远程调试装置的结构示意图二;
[0103]
图11示出了本申请实施例提供的客户端设备的结构示意图;
[0104]
图12示出了本申请实施例提供的调试设备的结构示意图。
具体实施方式
[0105]
为使本申请实施例的目的、技术方案和优点更加清楚,下面将结合本申请实施例
中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,应当理解,本申请中附图仅起到说明和描述的目的,并不用于限定本申请的保护范围。另外,应当理解,示意性的附图并未按实物比例绘制。本申请中使用的流程图示出了根据本申请的一些实施例实现的操作。应该理解,流程图的操作可以不按顺序实现,没有逻辑的上下文关系的步骤可以反转顺序或者同时实施。此外,本领域技术人员在本申请内容的指引下,可以向流程图添加一个或多个其他操作,也可以从流程图中移除一个或多个操作。
[0106]
另外,所描述的实施例仅仅是本申请一部分实施例,而不是全部的实施例。通常在此处附图中描述和示出的本申请实施例的组件可以以各种不同的配置来布置和设计。因此,以下对在附图中提供的本申请的实施例的详细描述并非旨在限制要求保护的本申请的范围,而是仅仅表示本申请的选定实施例。基于本申请的实施例,本领域技术人员在没有做出创造性劳动的前提下所获得的所有其他实施例,都属于本申请保护的范围。
[0107]
需要说明的是,本申请实施例中将会用到术语“包括”,用于指出其后所声明的特征的存在,但并不排除增加其它的特征。
[0108]
现有技术中,对于用户在使用软件应用的过程中存在的问题,有一些问题往往无法复现、难以排查,即使使用和用户设备相同的机型,也难以模拟用户使用时的具体场景,导致用户问题无法解决。基于此,目前提供了几种问题排查方法,一种是apm sdk方法,通过监控线上崩溃、卡顿、超时等问题来达到追查问题、改善性能的目的;另一种是上报埋点日志的方法;还有一种是联系用户复现出现问题的具体场景。
[0109]
然而,上述方案都是捕捉程序运行的异常状态进行上报,对于定位崩溃、卡顿等异常问题有效,但存在以下缺陷:
[0110]
(1)无法定位非性能问题,例如页面白屏、加载失败、显示的头像、昵称、等级等信息不正确等用户反馈的问题。
[0111]
(2)无法准确定位到引发卡顿的具体原因。
[0112]
(3)本地复现的问题与用户使用场景有关,无法追溯。
[0113]
基于此,本申请通过在目标应用程序的源代码中设置断点,当目标应用程序运行到断点时,获取调试信息,然后根据调试信息对目标应用程序进行调试,从而能够从源代码角度定位用户问题的确切源头和具体原因。
[0114]
首先对本申请涉及的专业术语进行说明。
[0115]
jpda:全称java platform debugger architecture,中文名称为java平台调试体系。
[0116]
apm:全称application performance management,中文名称为应用性能监控。
[0117]
jvmti:全称java virtual machine tool interface,中文名称为java虚拟机工具接口。
[0118]
jdwp:全称java debug wire protocol,中文名称为java调试协议,通过jpda提供的api,开发人员可以方便灵活的搭建java调试应用程序。
[0119]
jdi:全称java debug interface,中文名称为java调试接口。
[0120]
组包:将调试指令转换为jdwp协议规定的数据包。
[0121]
解包:将虚拟机返回的调试信息解析为jdwp协议规定的数据包。
[0122]
图1示出了本申请实施例提供的jpda调试的架构示意图,如图1所示,包括:客户端
和调试平台。
[0123]
调试平台为调试者、客户端为被调试者,被调试者提供jvmti接口,调试者提供jdi接口,被调试者和调试者之间通过jdwp协议传输命令,所有命令被封装成jdwp数据包。
[0124]
jdwp支持adb和套接字socket两种通信方式,adb依赖于数据线与局域网,在本实施例中,为了实现对调试者进行远程调试,调试者和被调试者之间的通信方式设为socket。
[0125]
其中,jpda运行在客户端上,客户端设备可以为安卓设备。
[0126]
基于图1提供的jpda平台,图2示出了本申请实施例提供的远程调试的系统架构图,如图2所示,包括:调试平台、客户端,其中,调试平台包括服务器和调试设备,客户端包括调试器和虚拟机。
[0127]
其中,调试设备和服务器之间的通信方式为远程socket,服务器和调试器之间的通信方式为远程socket,调试器和虚拟机之间的通信方式为本地socket。
[0128]
需要说明的是,调试器运行在客户端中的应用层,虚拟机运行在客户端中的系统层。
[0129]
在一种实际应用中,当用户在使用目标应用程序的过程中向调试设备反馈问题时,例如,游戏等级显示错误,调试设备在目标应用程序的源代码中设置用户问题对应的断点,并根据断点的标识获取调试指令,也即,jdwp指令,并将调试指令发送给服务器,服务器将调试指令推送到调试器,调试器对接收的调试指令进行组包操作,并将组包后的调试指令发送给虚拟机,虚拟机对接收的组包后的调试指令进行解包操作,获取调试指令中的断点的标识,若目标应用程序运行到该断点,获取该断点的调试信息,然后向调试器返回调试信息,调试器接收调试信息并对该调试信息进行解包操作,将解包后的调试信息发送给服务器,服务器将解包后的调试信息转发给调试设备,调试设备可以根据解包后的调试信息对目标应用程序进行调试,从而从源代码角度定位出用户问题的确切源头和具体原因。
[0130]
下面结合上述远程调试的系统架构,对本申请实施例提供的远程调试方法进行详细说明。
[0131]
图3示出了本申请实施例提供的远程调试方法的流程示意图一,如图3所示,该方法包括:
[0132]
s101、调试设备在目标应用程序的源代码中设置针对目标应用程序的用户问题对应的至少一个断点。
[0133]
其中,调试设备为开发人员进行调试所采用的设备,客户端为运行在客户端设备上的目标应用程序的客户端。目标应用程序可以为安装在客户端设备上的任一应用程序,例如,游戏类应用、视频类应用以及阅读类应用,本实施例对此不做限制。
[0134]
在实际应用中,若目标应用程序为游戏应用,用户在玩游戏的过程中,可能会发现一些用户问题,例如,头像显示异常、昵称错误、等级错误等,用户可以向调试设备反馈该用户问题,调试设备根据接收的针对目标应用程序的用户问题,可以在目标应用程序的源代码中设置针对目标应用程序的用户问题对应的至少一个断点,其中,断点指的是在目标应用程序的源代码中设置断点,当源代码运行到断点处时便停止运行。
[0135]
示例性地,用户问题和断点之间具有对应关系,例如,当用户问题为昵称错误时,对应的至少一个断点可以设置于源代码的第1行、第7行;当用户问题为头像显示异常时,对应的至少一个断点可以设置于源代码的第8行、第9行、第10行。
[0136]
s102、调试设备根据至少一个断点的标识获取调试指令,并向客户端发送调试指令。
[0137]
调试设备根据至少一个断点的标识获取调试指令,并向客户端发送调试指令,调试指令中包括至少一个断点的标识,调试指令为针对目标应用程序的用户问题的调试指令,相应的,客户端接收调试设备发送的调试指令。
[0138]
s103、若目标应用程序运行到至少一个断点中的任一断点,客户端获取断点的调试信息。
[0139]
s104、客户端向调试设备发送调试信息。
[0140]
s105、调试设备根据调试信息对目标应用程序进行调试,以对用户问题进行定位。
[0141]
其中,调试信息可以为断点所在代码行的变量的参数值。若目标应用程序运行到至少一个断点中的任一断点,客户端获取该断点的调试信息,并将调试信息发送给调试设备,调试设备用于根据调试信息对目标应用程序进行调试,相应的,调试设备在目标应用程序运行到至少一个断点中的任一断点时,接收客户端发送的至少一个断点中的任一断点的调试信息,并根据调试信息对目标应用程序进行调试,以对用户问题进行定位。
[0142]
图4示出了本申请实施例提供的目标应用程序运行到断点的场景示意图,如图4所示,若用户问题为用户拥有的游戏角色中的一个角色的昵称错误,例如显示为“我的角色名我的角色名我的角
…”
,则当用户切换到该游戏角色时,说明目标应用程序运行到断点处。
[0143]
示例性地,调试设备本地存储有目标应用程序的初始代码,调试设备通过对比初始代码和调试信息,可以确定出各断点所在代码行的变量的参数值是否相同,若相同,则表明该用户问题的源头在于断点所在的代码行,若不同,则表明该用户问题的源头不在于该断点所在的代码行,从而可以实现对用户问题的定位。其中,目标应用程序的初始代码可以为目标应用程序实际上的源代码。
[0144]
需要说明的是,客户端与调试设备之间传输的数据可以通过服务器进行中转转发。
[0145]
本实施例提供的远程调试的方法,包括:调试设备在目标应用程序的源代码中设置针对目标应用程序的用户问题对应的至少一个断点,调试设备根据至少一个断点的标识获取调试指令,并向客户端发送针对调试指令,若目标应用程序运行到至少一个断点中的任一断点,客户端获取断点的调试信息,向调试设备发送调试信息,调试设备根据调试信息对目标应用程序进行调试,以对用户问题进行定位。在本实施例中,根据用户问题设置对应的断点,根据该断点处的调试信息对目标应用程序进行调试,从而可以从源代码角度定位出用户问题的确切源头和具体原因,并且在目标应用程序上取得了真实有效的应用效果,为解决无法复现、难以排查的线上问题提供了良好的解决方案。
[0146]
可选地,调试指令包括类引用标识获取指令、方法标识获取指令以及断点设置指令。下面结合图5实施例对设置断点的方式进行具体说明。图5示出了本申请实施例提供的远程调试方法的流程示意图二,如图5所示,在目标应用程序的源代码中设置针对目标应用程序的用户问题对应的至少一个断点,包括:
[0147]
s201、调试设备获取用户问题在源代码中对应的类签名,向客户端发送类引用标识获取指令。
[0148]
s202、客户端根据接收的调试设备发送的类引用标识获取指令,获取指令获取类
引用标识,并向调试设备发送类引用标识。
[0149]
其中,类签名为用户问题在源代码中的类的名称,调试设备根据针对目标应用程序的用户问题,可以确定该用户问题在源代码中对应的类签名,并向客户端发送类引用标识获取指令,客户端根据接收的调试设备发送的类引用标识获取指令,获取指令获取类引用标识,并向调试设备发送类引用标识,其中,类引用标识获取指令中包括类签名,类引用标识可以为该类签名在目标应用程序的源代码中的标识,例如可以为1号类引用标识、2号类引用标识,具体可以根据实际情况确定,在此不再赘述。
[0150]
s203、调试设备接收客户端发送的类引用标识,并向客户端发送方法标识获取指令。
[0151]
s204、客户端根据接收的调试设备发送的方法标识获取指令,获取类引用标识对应的至少一个方法标识,并向调试设备发送至少一个方法标识。
[0152]
调试设备接收客户端发送的类引用标识,并向客户端发送方法标识获取指令,其中,方法标识获取指令中包括类引用标识,类引用标识可以根据步骤s201-s201的方法得到。
[0153]
相应的,客户端根据接收到的方法标识获取指令,获取类引用标识对应的至少一个方法标识,并向调试设备发送至少一个方法标识,其中,方法标识获取指令中包括类引用标识。
[0154]
s205、调试设备接收客户端发送的类引用标识对应的至少一个方法标识,从至少一个方法标识中确定目标方法标识。
[0155]
调试设备在接收客户端发送的类引用标识对应的至少一个方法标识时,可以从至少一个方法标识中确定目标方法标识,其中,目标方法标识可以是调试设备从至少一个方法标识中随机确定的一个方法标识,或者从至少一个方法标识中依次选择的一个方法标识,又或者是开发人员根据经验从至少一个方法标识中确定的一个方法标识。
[0156]
需要说明的是,目标方法标识可以是预估的导致出现用户问题的方法的标识。
[0157]
s206、调试设备向客户端发送断点标识获取指令。
[0158]
s207、客户端根据接收的调试设备发送的断点标识获取指令,获取至少一个断点的标识,并向调试设备发送至少一个断点的标识。
[0159]
断点标识获取指令中包括类引用标识、目标方法标识以及目标方法标识对应的预设代码行的标识。
[0160]
目标方法标识对应的预设代码行可以是根据经验确定的导致出现用户问题的代码行,例如可以为目标方法中的第1行代码、第8行代码、第10行代码等,本实施例对此不做限制。
[0161]
调试设备向客户端发送断点标识获取指令,客户端接收调试设备发送的断点标识获取指令,根据该断点标识获取指令获取至少一个断点的标识,并向调试设备发送至少一个断点的标识。
[0162]
s208、调试设备根据接收的至少一个断点的标识,在源代码中设置用户问题对应的至少一个断点。
[0163]
调试设备根据接收到的至少一个断点的标识,在目标应用程序的源代码中按照类引用标识、目标方法标识、目标方法标识对应的预设代码行的标识,找到预设代码行,然后
在源代码中的预设代码行设置用户问题对应的至少一个断点。
[0164]
作为一种示例,类引用标识获取指令为“virtualmachine:classesbysignature”、方法标识获取指令为“referencetype:methodswithgeneric”、断点设置指令为“eventrequest:set”,调试设备向客户端发送“virtualmachine:classesbysignature”,客户端返回类引用标识,调试设备向客户端发送“referencetype:methodswithgeneric”,客户端返回方法标识,调试设备向客户端发送“eventrequest:set”,客户端设置断点,并返回事件请求标识,也就是断点设置成功的响应消息。
[0165]
由此可知,调试指令的调用顺序是串行的,即解析上一个指令的回复作为下一个指令的参数。
[0166]
本实施例提供的远程调试方法,包括:调试设备获取用户问题在源代码中对应的类签名,向客户端发送类引用标识获取指令,客户端根据接收的调试设备发送的类引用标识获取指令,获取指令获取类引用标识,并向调试设备发送类引用标识,调试设备接收客户端发送的类引用标识,并向客户端发送方法标识获取指令,客户端根据接收的调试设备发送的方法标识获取指令,获取类引用标识对应的至少一个方法标识,并向调试设备发送至少一个方法标识,调试设备接收客户端发送的类引用标识对应的至少一个方法标识,从至少一个方法标识中确定目标方法标识,调试设备向客户端发送断点标识获取指令,客户端根据接收的调试设备发送的断点标识获取指令,获取至少一个断点的标识,并向调试设备发送至少一个断点的标识,调试设备根据接收的至少一个断点的标识,在源代码中设置用户问题对应的至少一个断点。在本实施例中,通过调用调试指令,确定在源代码的预设代码行设置断点,提高了用户问题的定位效率。
[0167]
可选地,下面结合图6对获取断点的调试信息进行具体说明。图6示出了本申请实施例提供的远程调试方法的流程示意图三,如图6所示,若目标应用程序运行到至少一个断点中的任一断点,获取断点的调试信息,包括:
[0168]
s301、若目标应用程序运行到断点,调试设备获取断点对应的执行信息。
[0169]
s302、调试设备根据执行信息获取断点的调用栈。
[0170]
其中,执行信息用于指示断点在源代码中的位置。调用栈为内存中保存断点的数据和地址的堆栈,堆栈用于缓存数据和地址。
[0171]
若目标应用程序运行到断点,客户端获取该断点对应的执行信息,然后根据执行信息确定该断点的调用栈,其中,执行信息与调用栈可以具有对应关系,在得到执行信息时,可以在该对应关系中匹配,以得到该执行信息对应的调用栈。
[0172]
可选地,执行信息包括以下信息中的至少一个:
[0173]
断点对应的事件类型、断点在至少一个断点中的标识号、断点所在的线程号、断点在对应调用栈中的位置信息。
[0174]
其中,断点对应的事件类型可以为断点事件。
[0175]
客户端在目标应用程序的源代码中设置用户问题对应的至少一个断点,每个断点标记有标识号,该断点在至少一个断点中的标记号例如可以为1号断点、2号断点、3号断点等。
[0176]
客户端还可以获取断点所在的线程号,以及断点在对应调用栈中的位置信息,例如,在对应调用栈中的第一个地址、第二个地址等。
[0177]
需要说明的是,目标应用程序每运行到一个断点,该断点对应的执行信息还可以缓存在消息队列中,其中,该消息队列可以运行在一个独立的线程,也就是说,分为两个独立线程,一个线程用于缓存消息队列,另一个线程用于运行目标应用程序,若第一断点的执行信息缓存在消息队列中,另一个线程还可以正常运行目标应用程序,其中,缓存在消息队列中的执行信息可以是边缓存边消费的过程。
[0178]
s303、调试设备获取断点的调用栈中栈顶变量的参数值。
[0179]
s304、调试设备将栈顶变量的参数值确定为调试信息。
[0180]
其中,栈顶为断点所在的代码行,栈顶变量为调用栈中栈顶的变量栈顶变量例如可以为头像、昵称、等级等。
[0181]
具体地,调试设备确定断点的调用栈,获取调用栈中栈顶变量的参数值,将该栈顶变量的参数值确定为调试信息,这样,调试设备可以通过对比目标应用程序的初始代码和该栈顶变量的参数值,在该栈顶变量的参数值与初始代码中的值相同时,则表明该用户问题的源头在于该断点所在的代码行,若不同,则表明该用户问题的源头不在于该断点所在的代码行,从而可以实现对用户问题的定位。
[0182]
可选地,获取调用栈中栈顶变量的参数值,包括:
[0183]
若栈顶变量的数据类型为第一数据类型,采用参数获取指令,获取栈顶变量的参数值。
[0184]
其中,第一数据类型可以为基本数据类型,例如int、long,若栈顶变量的数据类型为第一数据类型,则可以采用参数获取指令,直接获取栈顶变量的参数值。
[0185]
示例性地,该参数获取指令可以为“stackframe:getvalues”。
[0186]
可选地,获取调用栈中栈顶变量的参数值,包括:
[0187]
若栈顶变量的数据类型为第二数据类型,采用引用信息获取指令,获取栈顶变量的引用信息;
[0188]
根据引用信息获取栈顶变量对应的字段;
[0189]
采用字段参数获取指令,获取字段的参数值;
[0190]
将字段的参数值确定为栈顶变量的参数值。
[0191]
其中,第二数据类型可以为非基本数据类型,例如string,若栈顶变量为非基本数据类型,则可以采用引用信息获取指令,获取栈顶变量的引用信息,引用信息用于指示栈顶变量引用的参数信息,然后根据引用信息获取栈顶变量对应的字段,接着采用字段参数获取指令获取字段的参数值,将字段的参数值确定为栈顶变量的参数值。
[0192]
需要说明的是,在java中,数据类型分为基本数据类型和非基本数据类型,非基本数据类型即对象,对象拥有字段,对象的调用都是通过引用对象的地址。因此,这里的引用信息指引用对象的地址。
[0193]
本实施例提供的远程调试方法,包括:若目标应用程序运行到断点,获取断点对应的执行信息,根据执行信息获取断点的调用栈,获取断点的调用栈中栈顶变量的参数值,将栈顶变量的参数值确定为调试信息。从而能够准确确定出断点的调试信息,有助于提高定位问题的准确度。
[0194]
可选地,参考图2,客户端中包括调试器和虚拟机,调试器运行在应用层,虚拟机运行在系统层。客户端接收调试设备发送的调试指令,包括:通过客户端中的调试器接收调试
指令,调试器用于根据预设交互协议对调试指令进行组包,将组包后的调试指令发送给客户端中的虚拟机。
[0195]
相应的,客户端向调试设备发送调试信息,包括:客户端通过虚拟机获取调试信息,并将调试信息发送给调试器,调试器用于对调试信息进行解包,并将解包后的调试信息发送给调试设备。
[0196]
下面结合图7对本实施例提供的一种远程调试方法进行说明,图7示出了本申请实施例提供的远程调试方法的流程示意图四,如图7所示,该方法包括:
[0197]
s401、通过客户端中的调试器接收调试指令。
[0198]
调试设备根据接收的针对目标应用程序的用户问题,在目标应用程序的源代码中设置至少一个断点,并根据至少一个断点的标识获取调试指令,向客户端发送调试指令,也就是说,客户端通过调试器接收调试指令,调试器用于根据预设交互协议对调试指令进行组包,将组包后的调试指令发送给客户端中的虚拟机。
[0199]
其中,预设交互协议可以为图2所示的jdwp协议,通过客户端中的调试器接收调试设备发送的调试指令,调试器按照jdwp协议对调试指令进行组包,并将组包后的调试指令发送给虚拟机。
[0200]
示例性地,组包和解包是采用c++实现的,在调试器接收调试指令时,可以按照jdwp协议,采用jni函数调用组包,将调试指令转换为字节(英文名称:byte)流命令,即组包后的调试指令,然后将组包后的调试指令发送给虚拟机。
[0201]
可选地,通过客户端中的调试器接收调试指令,包括:
[0202]
根据接收的远程调试的开启操作,开启客户端的远程调试功能;
[0203]
在客户端开启远程调试功能且调试器和虚拟机握手成功时,通过客户端中的调试器接收调试指令。
[0204]
其中,以图8为例,图8示出了本申请实施例提供的目标应用程序的设置界面示意图,如图8所示,目标应用程序的调试界面中设有允许远程调试的控件,当接收用户针对该控件的触控操作时,也就是接收远程调试的开启操作,开启客户端的远程调试功能。
[0205]
需要说明的是,通常目标应用程序的调试界面需要按照开发人员的指导方可进入,一般情况下,用户不会进入该调试界面。
[0206]
握手成功指的是调试器和虚拟机校验成功,也就是说,表示调试器和虚拟机建立了通信链路,可以进行数据传递。关于握手的相关描述参见现有技术中,在此不再赘述。
[0207]
具体地,只有当客户端的远程调试功能开启,并且客户端中的虚拟机和调试器握手成功,才可通过客户端中的调试器接收调试指令。
[0208]
s402、若目标应用程序运行到至少一个断点中的任一断点,通过虚拟机获取断点的调试信息。
[0209]
具体地,通过客户端中的虚拟机根据组包后的调试指令,在源代码中设置用户问题对应的至少一个断点,并在目标应用程序运行到至少一个断点中的任一断点时,通过虚拟机获取断点的调试信息。
[0210]
s403、通过虚拟机将调试信息发送给调试器,调试器用于对调试信息进行解包,并将解包后的调试信息发送给调试设备。
[0211]
s404、调试设备根据解包后的调试信息对目标应用程序进行调试,以对用户问题
进行定位。
[0212]
若目标应用程序运行到至少一个断定中的任一断点,则通过客户端中的虚拟机获取断点的调试信息,并通过虚拟机将调试信息发送给客户端中的调试器,调试器用于对调试信息进行解包,并将解包后的调试信息发送给调试设备。
[0213]
调试器接收虚拟机发送的调试信息,可以采用jni函数调用解包,将虚拟机发送的调试信息,也即byte流信息,转换为java实体类,即解包后的调试信息,并将解包后的调试信息发送给调试设备,调试设备根据解包后的调试信息对目标应用程序进行调试,以对用户问题进行定位。
[0214]
需要说明的是,调试器和调试设备之间传输的数据可以通过服务器进行中转转发。
[0215]
作为一种示例,调试器用于按照预设交互协议对调试指令进行组包,并将组包后的调试指令发送给虚拟机,虚拟机获取断点的调试信息,并将调试信息发送给调试器,调试器对调试信息进行解包,得到解包后的调试信息。
[0216]
其中,调试指令用于请求客户端在目标应用程序的源代码中设置用户问题对应的至少一个断点。
[0217]
本实施例提供的远程调试方法,包括:通过客户端中的调试器接收调试指令,若目标应用程序运行到至少一个断点中的任一断点,通过虚拟机获取断点的调试信息,通过虚拟机将调试信息发送给调试器,调试器用于对调试信息进行解包,并将解包后的调试信息发送给调试设备,调试设备根据解包后的调试信息对目标应用程序进行调试,以对用户问题进行定位。通过虚拟机和调试器之间的交互,在源代码中设置用户问题对应的断点,根据该断点处的调试信息对目标应用程序进行调试,从而可以从源代码角度定位出用户问题的确切源头和具体原因。
[0218]
下面结合对将虚拟机和调试器之间的通信方式设置为socket的过程进行说明。虚拟机和调试器之间的通信方式设置过程具体包括如下几个步骤:
[0219]
针对安卓5.0系统:
[0220]
第一步、调试器使用dlopen方法加载动态链接库源码(即libart.so),返回其在内存中的句柄。
[0221]
具体地,虚拟机实现jvm ti接口的相关代码在安卓5.0以上默认编译成libart.so,采用dlopen方法加载动态链接库,返回其在内存中的句柄。
[0222]
第二步、调试器采用dlsym方法获取libart.so中startjdwp函数符号化的地址。
[0223]
其中,dlsym用于获取某个方法(符号化后的函数名)的地址。符号化是编译器在将源代码编译成目标文件时会对变量名或函数名进行的名字修饰。其中,可以通过nm命令查找startjdwp、stopjdwp等函数的符号化函数名称。
[0224]
第三步、在libart.so中,根据实际需求,配置startjdwp函数符号化的地址对应的配置参数,以将虚拟机和调试器之间的通信方式设置为socket。
[0225]
针对安卓7.0以上系统:
[0226]
由于从安卓7.0开始,系统会阻止直接使用动态链接库libart.so,强制使用上述dlopen和dlsym方法会崩溃(英文名称:crash)。
[0227]
基于此,将上述第一步和第二步替换为如下步骤:
[0228]
第一步、打开系统文件“/proc/self/maps”,找到libart.so在内存中映射的地址,返回其内存句柄。
[0229]
第二步、通过第一步中返回的句柄,以startjdwp函数符号化的函数名为查找字符串,找到libart.so中startjdwp函数符号化的地址。
[0230]
在本实施例中,采用该虚拟机调试配置的方法,能够无需重新编译,调试发布出去的apk,能够突破数据线和局域网屏障,实时远程调试安装在任何客户端设备上的应用程序。
[0231]
下面结合一具体实施例对本技术方案进行详细说明,本实施例提供的远程调试方法的实现过程包括以下几个步骤:
[0232]
第一步、开启客户端的远程调试功能。
[0233]
第二步、设置通信方式。
[0234]
将服务器和调试器、调试设备之间的通信方式设置为socket,将调试器和虚拟机之间的通信方式设置为socket。
[0235]
第三步、调试设备在显示界面找到已连接的远程客户端,通过服务器向调试器发送调试指令,调试器向虚拟机发送调试指令。
[0236]
其中,调试指令包括类引用标识获取指令、方法标识获取指令以及断点设置指令。
[0237]
具体地,调试器在接收类引用标识获取指令时,获取类引用标识,类引用标识获取指令中包括用户问题在源代码中对应的类签名;在接收方法标识获取指令时,获取类引用标识对应的至少一个方法标识,方法标识获取指令中包括类引用标识,并将类引用标识和至少一个方法标识发送给调试设备,调试设备从至少一个方法标识中获取目标方法标识。
[0238]
然后,调试器在接收调试设备发送的断点设置指令时,将断点设置指令进行组包,并将组包后的断点设置指令发送给虚拟机,由虚拟机根据组包后的断点设置指令,在源代码中设置用户问题对应的至少一个断点,其中,断点设置指令中包括类引用标识、至少一个方法标识中的目标方法标识以及目标方法标识对应的预设代码行的标识。
[0239]
第三步、虚拟机获取断点的调试信息,调试器对该调试信息进行解包。
[0240]
第四步、调试器通过服务器将解包后的调试信息发送给调试设备。
[0241]
虚拟机获取断点的调试信息,并将该调试信息发送给调试器,由调试器将该调试信息进行解包,得到解包后的调试信息,调试器将解包后的调试信息通过服务器发送给调试设备,调试设备根据解包后的调试信息对目标应用程序进行调试。
[0242]
需要说明的是,虚拟机是google为了能将java开发的程序适配到不同硬件设备上运行,在linux内核之上构建的android虚拟机,内置于android系统。调试器是使用了本调试方案的应用程序,本调试方案封装为一个sdk可以提供给任何应用程序使用。调试器一方面与远程服务器通信,一方面与android系统的虚拟机通信。
[0243]
图9示出了本申请实施例提供的远程调试装置的结构示意图一,如图9所示,该远程调试装置20集成在客户端设备中,远程调试装置20包括:
[0244]
接收模块21,用于接收调试设备发送的调试指令,所述调试指令为针对目标应用程序的用户问题的调试指令,所述调试指令中包括至少一个断点的标识;
[0245]
处理模块22,用于根据所述调试指令,在所述目标应用程序的源代码中设置所述用户问题对应的至少一个断点;
[0246]
获取模块23,用于在所述目标应用程序运行到所述至少一个断点中的任一断点时,获取所述断点的调试信息;
[0247]
发送模块24,用于向所述调试设备发送所述调试信息,所述调试设备用于根据所述调试信息对所述目标应用程序进行调试。
[0248]
可选地,获取模块23,具体用于:
[0249]
若所述目标应用程序运行到所述断点,获取所述断点对应的执行信息,所述执行信息用于指示所述断点在所述源代码中的位置;
[0250]
根据所述执行信息获取所述断点的调用栈;
[0251]
获取所述调用栈中栈顶变量的参数值,所述栈顶变量为所述调用栈中栈顶的变量;
[0252]
将所述栈顶变量的参数值确定为所述调试信息。
[0253]
可选地,获取模块23,具体用于:
[0254]
若所述栈顶变量的数据类型为第一数据类型,采用参数获取指令,获取所述栈顶变量的参数值。
[0255]
可选地,获取模块23,具体用于:
[0256]
若所述栈顶变量的数据类型为第二数据类型,采用引用信息获取指令,获取所述栈顶变量的引用信息;
[0257]
根据所述引用信息获取所述栈顶变量对应的字段;
[0258]
采用字段参数获取指令,获取所述字段的参数值;
[0259]
将所述字段的参数值确定为所述栈顶变量的参数值。
[0260]
可选地,获取模块23,还用于:
[0261]
根据接收的调试设备发送的类引用标识获取指令,获取指令获取类引用标识,并向所述调试设备发送所述类引用标识,其中,所述类引用标识获取指令中包括所述用户问题在源代码中对应的类签名;
[0262]
根据接收的调试设备发送的方法标识获取指令,获取所述类引用标识对应的至少一个方法标识,并向所述调试设备发送所述至少一个方法标识,其中,所述方法标识获取指令中包括所述类引用标识;
[0263]
根据接收的调试设备发送的断点标识获取指令,获取至少一个断点的标识,并向所述调试设备发送所述至少一个断点的标识,其中,所述断点标识获取指令中包括所述类引用标识、所述至少一个方法标识中的目标方法标识以及所述目标方法标识对应的预设代码行的标识。
[0264]
可选地,所述执行信息包括以下信息中的至少一个:
[0265]
所述断点对应的事件类型、所述断点在所述至少一个断点中的标识号、所述断点所在的线程号、所述断点在对应调用栈中的位置信息。
[0266]
可选地,接收模块21,具体用于:
[0267]
通过所述客户端中的调试器接收所述调试指令,所述调试器用于根据预设交互协议对所述调试指令进行组包,将组包后的调试指令发送给所述客户端中的虚拟机。
[0268]
可选地,接收模块21,具体用于:
[0269]
根据接收的远程调试的开启操作,开启所述客户端的远程调试功能;
[0270]
在所述客户端开启远程调试功能、且所述调试器和所述虚拟机握手成功时,通过所述客户端中的调试器接收所述调试指令。
[0271]
可选地,发送模块24,具体用于:
[0272]
通过所述虚拟机将所述调试信息发送给所述调试器,所述调试器用于根据预设交互协议对所述调试信息进行解包,并将解包后的调试信息发送给所述调试设备。
[0273]
关于装置中的各模块的处理流程、以及各模块之间的交互流程的描述可以参照上述客户端所执行的方法中的相关说明,这里不再详述。
[0274]
图10示出了本申请实施例提供的远程调试装置的结构示意图二,如图10所示,该远程调试装置30集成在调试设备中,远程调试装置30包括:
[0275]
处理模块31,用于在所述目标应用程序的源代码中设置针对所述目标应用程序的用户问题对应的至少一个断点;
[0276]
发送模块32,用于根据所述至少一个断点的标识获取调试指令,并向客户端发送针对所述调试指令;
[0277]
接收模块33,用于接收所述客户端发送的所述至少一个断点中的任一断点的调试信息;
[0278]
所述处理模块34,还用于根据所述调试信息对所述目标应用程序进行调试,以对所述用户问题进行定位。
[0279]
可选地,处理模块34,具体用于:
[0280]
获取所述用户问题在源代码中对应的类签名,向所述客户端发送类引用标识获取指令,所述类引用标识获取指令中包括所述类签名;
[0281]
接收所述客户端发送的类引用标识,并向所述客户端发送方法标识获取指令,所述方法标识获取指令中包括所述类引用标识;
[0282]
接收所述客户端发送的所述类引用标识对应的至少一个方法标识,从所述至少一个方法标识中确定目标方法标识;
[0283]
向所述客户端发送断点标识获取指令,所述断点标识获取指令中包括所述类引用标识、所述目标方法标识以及所述目标方法标识对应的预设代码行的标识;
[0284]
根据接收的至少一个断点的标识,在所述源代码中设置所述用户问题对应的至少一个断点。
[0285]
关于装置中的各模块的处理流程、以及各模块之间的交互流程的描述可以参照上述调试设备所执行的方法中的相关说明,这里不再详述。
[0286]
图11示出了本申请实施例提供的客户端设备的结构示意图,如图11所示,该客户端设备40包括:
[0287]
处理器41、存储器42和收发器43;所述收发器43用于接收和发送数据;所述存储器42中存储有所述处理器的可执行指令;其中,所述处理器41配置为经由执行所述可执行指令来实现上述客户端所执行的方法。
[0288]
图12示出了本申请实施例提供的调试设备的结构示意图,如图12所示,该调试设备50包括:
[0289]
处理器51、存储器52和收发器53;所述收发器53用于接收和发送数据;所述存储器52中存储有所述处理器51的可执行指令;其中,所述处理器51配置为经由执行所述可执行
指令来实现上述调试设备所执行的方法。
[0290]
本申请实施例还提供了一种计算机可读存储介质,该计算机可读存储介质上存储有计算机程序,该计算机程序被运行时执行上述方法实施例。
[0291]
所属领域的技术人员可以清楚地了解到,为描述的方便和简洁,上述描述的系统和装置的具体工作过程,可以参考方法实施例中的对应过程,本申请中不再赘述。在本申请所提供的几个实施例中,应该理解到,所揭露的系统、装置和方法,可以通过其它的方式实现。以上所描述的装置实施例仅仅是示意性的,例如,所述模块的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,又例如,多个模块或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信方式可以是通过一些通信接口,装置或模块的间接耦合或通信方式,可以是电性,机械或其它的形式。
[0292]
另外,在本申请各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中。所述功能如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本发明各个实施例所述方法的全部或部分步骤。而前述的存储介质包括:u盘、移动硬盘、只读存储器(rom,read-only memory)、随机存取存储器(ram,random access memory)、磁碟或者光盘等各种可以存储程序代码的介质。
[0293]
以上仅为本申请的具体实施方式,但本申请的保护范围并不局限于此,任何熟悉本技术领域的技术人员在本申请揭露的技术范围内,可轻易想到变化或替换,都应涵盖在本申请的保护范围之内。
当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1