发明内容
本公开实施例至少提供一种异常处理方法及装置。
第一方面,本公开实施例提供了一种异常处理方法,包括:
捕获异常对象;
在检测到所述异常对象的类型为内存溢出异常对象时,将所述异常对象传输至本地native层;
在所述本地native层,获取所述异常对象所对应的调用信息,并将所述调用信息写入日志文件,其中,所述调用信息用于表示抛出所述异常对象的方法与其它方法之间的调用关系;
将生成的所述日志文件传输至服务器。
一种可能的实施方式中,所述捕获异常对象包括:
通过预先注册的异常捕获函数捕获异常对象;
所述将生成的所述日志文件传输至服务器,包括:
在应用程序重新启动之后,将生成的所述日志文件传输至所述应用程序对应的服务器。
一种可能的实施方式中,所述方法还包括:
在检测到所述异常对象的类型不是内存溢出异常对象时,在java层获取所述异常对象对应的调用信息;
将获取的所述调用信息写入日志文件中,并在应用程序再次被启动后,将生成的日志文件传输至所述服务器。
一种可能的实施方式中,所述获取所述异常对象所对应的调用信息,并将所述调用信息写入日志文件,包括:
通过解析所述异常对象中所封装的异常信息,获取所述异常对象对应的native层指针地址;所述native层指针地址为所述异常对象对应的调用信息的存储地址;
基于所述native层指针地址,获取所述调用信息;
将获取的所述调用信息写入日志文件。
一种可能的实施方式中,所述将获取的所述调用信息写入日志文件,包括:
在所述native层构建字符串对象;
将所述调用信息写入构建的所述字符串对象中;
将携带所述调用信息的所述字符串对象写入所述日志文件。
一种可能的实施方式中,所述调用信息包括:
所述异常对象对应的调试信息和调用栈信息;其中,所述调试信息为抛出所述异常对象的方法在构建所述异常对象时,生成的用于指示进行调试的字符串信息;
所述调用栈信息包括:直接或间接调用抛出所述异常对象的方法的其他方法的操作信息、和抛出所述异常对象的方法的操作信息;
所述操作信息包括类名、方法名、类所在的文件名、和方法在文件中的代码中的至少一种。
一种可能的实施方式中,所述将携带所述调用信息的所述字符串对象写入所述日志文件,包括:
将所述字符串对象进行压缩处理之后,写入所述日志文件。
第二方面,本公开实施例还提供一种异常处理装置,包括:
捕获模块,用于捕获异常对象;
传输模块,用于在检测到所述异常对象的类型为内存溢出异常对象时,将所述异常对象传输至本地native层;
写入模块,用于在所述本地native层,获取所述异常对象所对应的调用信息,并将所述调用信息写入日志文件,其中,所述调用信息用于表示抛出所述异常对象的方法与其它方法之间的调用关系;
发送模块,用于将生成的所述日志文件传输至服务器。
一种可能的实施方式中,所述捕获模块,在捕获异常对象时,用于:
通过预先注册的异常捕获函数捕获异常对象;
所述发送模块,在将生成的所述日志文件传输至服务器时,用于:
在应用程序重新启动之后,将生成的所述日志文件传输至所述应用程序对应的服务器。
一种可能的实施方式中,所述传输模块,还用于:
在检测到所述异常对象的类型不是内存溢出异常对象时,在java层获取所述异常对象对应的调用信息;
将获取的所述调用信息写入日志文件中,并在应用程序再次被启动后,将生成的日志文件传输至所述服务器。
一种可能的实施方式中,所述写入模块,在获取所述异常对象所对应的调用信息,并将所述调用信息写入日志文件时,用于:
通过解析所述异常对象中所封装的异常信息,获取所述异常对象对应的native层指针地址;所述native层指针地址为所述异常对象对应的调用信息的存储地址;
基于所述native层指针地址,获取所述调用信息;
将获取的所述调用信息写入日志文件。
一种可能的实施方式中,所述写入模块,在将获取的所述调用信息写入日志文件时,用于:
在所述native层构建字符串对象;
将所述调用信息写入构建的所述字符串对象中;
将携带所述调用信息的所述字符串对象写入所述日志文件。
一种可能的实施方式中,所述调用信息包括:
所述异常对象对应的调试信息和调用栈信息;其中,所述调试信息为抛出所述异常对象的方法在构建所述异常对象时,生成的用于指示进行调试的字符串信息;
所述调用栈信息包括:直接或间接调用抛出所述异常对象的方法的其他方法的操作信息、和抛出所述异常对象的方法的操作信息;
所述操作信息包括类名、方法名、类所在的文件名、和方法在文件中的代码中的至少一种。
一种可能的实施方式中,所述写入模块,在将携带所述调用信息的所述字符串对象写入所述日志文件时,用于:
将所述字符串对象进行压缩处理之后,写入所述日志文件。
第三方面,本公开实施例还提供一种计算机设备,包括:处理器、存储器和总线,所述存储器存储有所述处理器可执行的机器可读指令,当计算机设备运行时,所述处理器与所述存储器之间通过总线通信,所述机器可读指令被所述处理器执行时执行上述第一方面,或第一方面中任一种可能的实施方式中的步骤。
第四方面,本公开实施例还提供一种计算机可读存储介质,该计算机可读存储介质上存储有计算机程序,该计算机程序被处理器运行时执行上述第一方面,或第一方面中任一种可能的实施方式中的步骤。
本公开实施例提供的异常处理方法中,在检测到异常对象的类型为内存溢出异常对象时,可以将异常对象传输至native层,然后在native层执行获取异常对象对应的调用信息,且将调用信息写入日志文件的步骤,由此,可以不用占用应用程序java层的内容,从而可以在产生内存溢出异常时,生成并上传日志文件,为后续研发人员调试程序提供了基础,进而提高异常处理效率。
为使本公开的上述目的、特征和优点能更明显易懂,下文特举较佳实施例,并配合所附附图,作详细说明如下。
具体实施方式
为使本公开实施例的目的、技术方案和优点更加清楚,下面将结合本公开实施例中附图,对本公开实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本公开一部分实施例,而不是全部的实施例。通常在此处附图中描述和示出的本公开实施例的组件可以以各种不同的配置来布置和设计。因此,以下对在附图中提供的本公开的实施例的详细描述并非旨在限制要求保护的本公开的范围,而是仅仅表示本公开的选定实施例。基于本公开的实施例,本领域技术人员在没有做出创造性劳动的前提下所获得的所有其他实施例,都属于本公开保护的范围。
java程序在运行时,是运行在虚拟机上,一般设备在出厂时会限制一个应用程序(Application,APP)所能使用的最大内存,而虚拟机是运行在操作系统之上的,操作系统在出厂时也会有最大使用内存,应用程序的内存即为操作系统的内存中的部分内存,一般而言,操作系统的内存要大于APP的使用内存。
示例性的,如图1所示,图1中,最大的圆圈为操作系统的内存,在各个APP运行过程中,会从操作系统的内存中的部分内存分配給各个APP作为APP的内存。
一般的,系统的代码分为业务代码和系统代码,业务代码为运行APP时的代码,系统代码为构建操作系统时的代码。在java运行过程中,有些异常时可预知的,对于这类异常,可以通过业务代码中的捕获函数进行捕获并处理,而有些异常是无法通过业务代码进行捕获的,对于这些异常,最终可能会上报至系统,从而导致应用程序崩溃关闭。
相关技术中,为了方便对这些可以导致应用系统崩溃关闭的异常进行调试,可以在应用程序关闭前,通过异常捕获函数捕获异常信息,然后获取异常信息对应的调用栈信息,并根据调用栈信息生成日志文件,然后在应用程序重新启动之后,将生成的日志文件自动上传至应用程序对应的服务器中,研发人员可以从服务器获取日志文件然后根据日志文件对异常进行调试。
然而在获取异常信息对应的调用栈信息,根据调用栈信息生成日志文件时,由于调用栈中存储有多个方法的操作信息,当操作方法过多时,可能会占用过多的APP的内存,而若本身产生异常信息的原因就是内存溢出异常,这就导致并没有其余内存供获取调用栈信息和生成日志文件使用,从而无法在服务器上传日志文件,研发人员也就无法获知本次异常产生的原因。
基于此,本公开实施例提供的一种异常处理方法,在检测到异常对象的类型为内存溢出异常对象时,可以将异常对象传输至native层,然后在native层执行获取异常对象对应的调用信息,且将调用信息写入日志文件的步骤,调用信息中包括调用栈信息,由此,可以不用占用应用程序java层的内容,从而可以在产生内存溢出异常时,生成并上传日志文件,为后续研发人员调试程序提供了基础,进而提高异常处理效率。
本公开中所述java层即为APP层,在java层执行操作时占用的是为APP分配的内存,native层为操作系统层,在native层执行操作时,占用的是操作系统中除了为APP分配的内存外的其他内存。
针对以上方案所存在的缺陷,均是发明人在经过实践并仔细研究后得出的结果,因此,上述问题的发现过程以及下文中本公开针对上述问题所提出的解决方案,都应该是发明人在本公开过程中对本公开做出的贡献。
应注意到:相似的标号和字母在下面的附图中表示类似项,因此,一旦某一项在一个附图中被定义,则在随后的附图中不需要对其进行进一步定义和解释。
为便于对本实施例进行理解,首先对本公开实施例所公开的一种异常处理方法进行详细介绍,本公开实施例所提供的异常处理方法的执行主体一般为安装有应用程序且具有一定计算能力的终端设备,终端设备可以为用户设备(User Equipment,UE)、移动设备、用户终端、终端、个人数字处理(Personal Digital Assistant,PDA)等。
参见图2所示,为本公开实施例提供的一种异常处理方法的流程图,包括以下几个步骤:
步骤201、捕获异常对象。
步骤202、在检测到所述异常对象的类型为内存溢出异常对象时,将所述异常对象传输至本地native层。
步骤203、在所述本地native层,获取所述异常对象所对应的调用信息,并将所述调用信息写入日志文件,其中,所述调用信息用于表示抛出所述异常对象的方法与其它方法之间的调用关系。
步骤204、将生成的所述日志文件传输至服务器。
以下是针对上述步骤201~步骤204的详细说明。
实际应用中,可以先在main函数之前注册异常捕获函数,即声明异常捕获函数,然后在检测到异常时,通过注册的异常捕获函数去捕获异常对象。这里,由于方法在抛出异常信息时,抛出异常对象的方法已将异常信息封装为异常对象,因此异常捕获函数捕获的为异常对象。
需要说明的是,异常对象分为两类,一类是在执行方法之前已经预知的可能会出现的异常对象,针对这类异常对象可以通过try-catch函数进行异常对象的捕获,在捕获这类异常对象之后,可以直接通过预先设置的代码,对该类异常对象进行处理;另一类是在执行方法之前不可预知的异常对象,针对这类异常对象,由于系统中并未预先设置对该类异常对象的处理方法,系统也就无法正常的执行程序,从而会导致应用程序闪退。这里,通过异常捕获函数所捕获的异常对象均为不可预知的异常对象。
在检测到异常对象的类型为内存溢出异常对象时,可以将异常对象传输至本地native层,具体的,可以调用JNI(Java Native Interface)函数,将异常对象传输至native层,其中,所述内存溢出异常对象即为由于内存溢出所产生的异常对象。
在检测到异常对象的类型不是内存溢出异常对象时,说明此时java层的内存并不存在内存溢出的情况,即java层有多余的内存去执行获取调用信息、生成日志文件的步骤,此时,可以直接在java层获取异常对象对应的调用信息,然后将获取的调用信息写入日志文件中,并在应用程序再次被启动后,将生成的日志文件传输至服务器。
其中,异常对象对应的调用信息包括异常对象对应的调试信息和调用栈信息,其中,所述调试信息为抛出所述异常对象的方法在构建所述异常对象时,生成的用于指示进行调试的字符串信息,后续研发人员可以根据该调试信息对应用程序进行调试。
调用栈信息中包括:直接或间接调用抛出异常对象的方法的其他方法的操作信息、抛出异常对象的方法的操作信息,操作信息包括类名、方法名、类所在的文件名、和方法在文件中的代码中的至少一种。
需要说明的是,上述所述直接或间接调用抛出异常对象的方法的其他方法的操作信息包括,从main函数的函数入口位置,到抛出异常对象的方法的所有方法。
示例性,如图3所示的调用关系,图3中为从main函数开始所有的方法之间的调用关系,箭头指向的表示二者之间有调用关系,例如方法a→方法b,表示方法b调用方法a,若抛出异常对象的方法为方法e,则在异常对象的调用信息的方法中包括方法e(抛出异常对象的方法)、方法d、方法c、方法a,其中,方法d时直接调用方法e的方法,方法c和方法a均为间接调用方法e的方法。
其中,在获取调用信息,将获取的调用信息写入日志文件中时,可以先解析异常对象获取异常对应的java层指针地址,该指针地址指向的是调用信息的存储位置,由于调用信息在存储时是以机器可读语言存储,即0和1,因此可以先将java层指针地址指向的存储位置中所存储的信息转换为字符串信息(例如可以通过Throwable.dump()函数转换为字符串信息),然后将转换出的字符串信息写入到异常对象中,再将异常对象写入到日志文件中。
在另外一种可能的实施方式中,还可以重新在java层构建一个字符串对象,然后将java层指针地址指向的存储位置中所存储的信息转换为字符串信息后,写入新构建的字符串对象中,然后将携带调用信息的字符串对象写入到日志文件中。
在本地native层,获取异常对象对应的调用信息,并将调用信息写入到日志文件中时,由于已经在步骤202中将异常对象由java层传输至native层,因此,在执行步骤203的步骤时,所占用的为native层的内存。
具体的,在获取异常对象对应的调用信息,并将调用信息写入到日志文件中时,可以先解析异常对象中所封装的异常信息,然后获取异常对象对应的native层指针地址,基于native层指针地址,获取调用信息,再将获取的调用信息写入日志文件中,其中,native层指针地址为所述异常对象对应的调用信息的存储地址。
其中,在将获取的调用信息写入日志文件时,可以先在native层构建字符串对象,然后将获取的调用信息写入构建的字符串对象中,再将携带有调用信息的字符串对象写入日志文件中。
具体的,所述将获取的调用信息写入构建的字符串对象,也就是将异常对应的调试信息、抛出异常对象的方法的操作信息、以及直接或间接调用抛出异常对象的方法的其他方法的操作信息写入构建的字符串对象中。
需要说明的是,在步骤202中,在将异常对象从java层传输至native层时,异常对象中封装的调用信息的指针地址也从java层指针地址转换为native层指针地址,java层的指针地址和native层的指针地址执行同一存储地址,均指向异常对象的调用信息的存储地址,但是java层和native层对于指针地址的解析方法不同,因此java层和native层需要不同的指针地址。
其中,携带调用信息的字符串对象写入日志文件中时,由于调用信息包括多个方法的操作信息,当方法数量较多时,操作信息也比较多,因此,在一种可能的实施方式中,还可以在将字符串对象进行压缩处理之后,再写入日志文件中。
其中,在将字符串对象进行压缩处理时,例如可以将字符串对象中多个方法的操作信息拼接成一行。
需要说明的是,在执行完步骤103所述的步骤,生成日志文件之后,应用程序就可以关闭,当应用程序再次被启动后,可以将生成的日志文件传输至服务器,该服务器为应用程序对应的应用服务器,此过程也可以是由native层执行的,且当应用程序再次被启动之后,由于并未执行抛出所述异常对象的方法,因此,此时应用程序可以正常运行,研发人员可以通过获取服务器中的日志文件,来查找造成内存溢出异常的原因。
本公开实施例提供的异常处理方法中,在检测到异常对象的类型为内存溢出异常对象时,可以将异常对象传输至native层,然后在native层执行获取异常对象对应的调用信息,且将调用信息写入日志文件的步骤,由此,可以不用占用应用程序java层的内容,从而可以在产生内存溢出异常时,生成并上传日志文件,为后续研发人员调试程序提供了基础,进而提高异常处理效率。
本领域技术人员可以理解,在具体实施方式的上述方法中,各步骤的撰写顺序并不意味着严格的执行顺序而对实施过程构成任何限定,各步骤的具体执行顺序应当以其功能和可能的内在逻辑确定。
基于同一发明构思,本公开实施例中还提供了与异常处理方法对应的异常处理装置,由于本公开实施例中的装置解决问题的原理与本公开实施例上述异常处理方法相似,因此装置的实施可以参见方法的实施,重复之处不再赘述。
参照图4所示,为本公开实施例提供的一种异常处理装置的架构示意图,所述装置包括:捕获模块401、传输模块402、写入模块403、以及发送模块404;其中,
捕获模块401,用于捕获异常对象;
传输模块402,用于在检测到所述异常对象的类型为内存溢出异常对象时,将所述异常对象传输至本地native层;
写入模块403,用于在所述本地native层,获取所述异常对象所对应的调用信息,并将所述调用信息写入日志文件,其中,所述调用信息用于表示抛出所述异常对象的方法与其它方法之间的调用关系;
发送模块404,用于将生成的所述日志文件传输至服务器。
一种可能的实施方式中,所述捕获模块401,在捕获异常对象时,用于:
通过预先注册的异常捕获函数捕获异常对象;
所述发送模块404,在将生成的所述日志文件传输至服务器时,用于:
在应用程序重新启动之后,将生成的所述日志文件传输至所述应用程序对应的服务器。
一种可能的实施方式中,所述传输模块402,还用于:
在检测到所述异常对象的类型不是内存溢出异常对象时,在java层获取所述异常对象对应的调用信息;
将获取的所述调用信息写入日志文件中,并在应用程序再次被启动后,将生成的日志文件传输至所述服务器。
一种可能的实施方式中,所述写入模块403,在获取所述异常对象所对应的调用信息,并将所述调用信息写入日志文件时,用于:
通过解析所述异常对象中所封装的异常信息,获取所述异常对象对应的native层指针地址;所述native层指针地址为所述异常对象对应的调用信息的存储地址;
基于所述native层指针地址,获取所述调用信息;
将获取的所述调用信息写入日志文件。
一种可能的实施方式中,所述写入模块403,在将获取的所述调用信息写入日志文件时,用于:
在所述native层构建字符串对象;
将所述调用信息写入构建的所述字符串对象中;
将携带所述调用信息的所述字符串对象写入所述日志文件。
一种可能的实施方式中,所述调用信息包括:
所述异常对象对应的调试信息和调用栈信息;其中,所述调试信息为抛出所述异常对象的方法在构建所述异常对象时,生成的用于指示进行调试的字符串信息;
所述调用栈信息包括:直接或间接调用抛出所述异常对象的方法的其他方法的操作信息、和抛出所述异常对象的方法的操作信息;
所述操作信息包括类名、方法名、类所在的文件名、和方法在文件中的代码中的至少一种。
一种可能的实施方式中,所述写入模块403,在将携带所述调用信息的所述字符串对象写入所述日志文件时,用于:
将所述字符串对象进行压缩处理之后,写入所述日志文件。
关于装置中的各模块的处理流程、以及各模块之间的交互流程的描述可以参照上述方法实施例中的相关说明,这里不再详述。
基于同一技术构思,本申请实施例还提供了一种电子设备。参照图5所示,为本申请实施例提供的电子设备的结构示意图,包括处理器501、存储器502、和总线503。其中,存储器502用于存储执行指令,包括内存5021和外部存储器5022;这里的内存5021也称内存储器,用于暂时存放处理器501中的运算数据,以及与硬盘等外部存储器5022交换的数据,处理器501通过内存5021与外部存储器5022进行数据交换,当电子设备500运行时,处理器501与存储器502之间通过总线503通信,使得处理器501在执行以下指令:
捕获异常对象;
在检测到所述异常对象的类型为内存溢出异常对象时,将所述异常对象传输至本地native层;
在所述本地native层,获取所述异常对象所对应的调用信息,并将所述调用信息写入日志文件,其中,所述调用信息用于表示抛出所述异常对象的方法与其它方法之间的调用关系;
将生成的所述日志文件传输至服务器。
一种可能的实施方式中,处理器501执行的指令中,所述捕获异常对象包括:
通过预先注册的异常捕获函数捕获异常对象;
所述将生成的所述日志文件传输至服务器,包括:
在应用程序重新启动之后,将生成的所述日志文件传输至所述应用程序对应的服务器。
一种可能的实施方式中,处理器501执行的指令中,所述方法还包括:
在检测到所述异常对象的类型不是内存溢出异常对象时,在java层获取所述异常对象对应的调用信息;
将获取的所述调用信息写入日志文件中,并在应用程序再次被启动后,将生成的日志文件传输至所述服务器。
一种可能的实施方式中,处理器501执行的指令中,所述获取所述异常对象所对应的调用信息,并将所述调用信息写入日志文件,包括:
通过解析所述异常对象中所封装的异常信息,获取所述异常对象对应的native层指针地址;所述native层指针地址为所述异常对象对应的调用信息的存储地址;
基于所述native层指针地址,获取所述调用信息;
将获取的所述调用信息写入日志文件。
一种可能的实施方式中,处理器501执行的指令中,所述将获取的所述调用信息写入日志文件,包括:
在所述native层构建字符串对象;
将所述调用信息写入构建的所述字符串对象中;
将携带所述调用信息的所述字符串对象写入所述日志文件。
一种可能的实施方式中,处理器501执行的指令中,所述调用信息包括:
所述异常对象对应的调试信息和调用栈信息;其中,所述调试信息为抛出所述异常对象的方法在构建所述异常对象时,生成的用于指示进行调试的字符串信息;
所述调用栈信息包括:直接或间接调用抛出所述异常对象的方法的其他方法的操作信息、和抛出所述异常对象的方法的操作信息;
所述操作信息包括类名、方法名、类所在的文件名、和方法在文件中的代码中的至少一种。
一种可能的实施方式中,处理器501执行的指令中,所述将携带所述调用信息的所述字符串对象写入所述日志文件,包括:
将所述字符串对象进行压缩处理之后,写入所述日志文件。
本公开实施例还提供一种计算机可读存储介质,该计算机可读存储介质上存储有计算机程序,该计算机程序被处理器运行时执行上述方法实施例中所述的异常处理方法的步骤。其中,该存储介质可以是易失性或非易失的计算机可读取存储介质。
本公开实施例所提供的异常处理方法的计算机程序产品,包括存储了程序代码的计算机可读存储介质,所述程序代码包括的指令可用于执行上述方法实施例中所述的异常处理方法的步骤,具体可参见上述方法实施例,在此不再赘述。
本公开实施例还提供一种计算机程序,该计算机程序被处理器执行时实现前述实施例的任意一种方法。该计算机程序产品可以具体通过硬件、软件或其结合的方式实现。在一个可选实施例中,所述计算机程序产品具体体现为计算机存储介质,在另一个可选实施例中,计算机程序产品具体体现为软件产品,例如软件开发包(Software DevelopmentKit,SDK)等等。
所属领域的技术人员可以清楚地了解到,为描述的方便和简洁,上述描述的系统和装置的具体工作过程,可以参考前述方法实施例中的对应过程,在此不再赘述。在本公开所提供的几个实施例中,应该理解到,所揭露的系统、装置和方法,可以通过其它的方式实现。以上所描述的装置实施例仅仅是示意性的,例如,所述单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,又例如,多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信连接可以是通过一些通信接口,装置或单元的间接耦合或通信连接,可以是电性,机械或其它的形式。
所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部单元来实现本实施例方案的目的。
另外,在本公开各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中。
所述功能如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个处理器可执行的非易失的计算机可读取存储介质中。基于这样的理解,本公开的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本公开各个实施例所述方法的全部或部分步骤。而前述的存储介质包括:U盘、移动硬盘、只读存储器(Read-OnlyMemory,ROM)、随机存取存储器(Random Access Memory,RAM)、磁碟或者光盘等各种可以存储程序代码的介质。
最后应说明的是:以上所述实施例,仅为本公开的具体实施方式,用以说明本公开的技术方案,而非对其限制,本公开的保护范围并不局限于此,尽管参照前述实施例对本公开进行了详细的说明,本领域的普通技术人员应当理解:任何熟悉本技术领域的技术人员在本公开揭露的技术范围内,其依然可以对前述实施例所记载的技术方案进行修改或可轻易想到变化,或者对其中部分技术特征进行等同替换;而这些修改、变化或者替换,并不使相应技术方案的本质脱离本公开实施例技术方案的精神和范围,都应涵盖在本公开的保护范围之内。因此,本公开的保护范围应所述以权利要求的保护范围为准。