CN114896023A - 一种数据处理方法、装置、设备及存储介质 - Google Patents

一种数据处理方法、装置、设备及存储介质 Download PDF

Info

Publication number
CN114896023A
CN114896023A CN202210475876.6A CN202210475876A CN114896023A CN 114896023 A CN114896023 A CN 114896023A CN 202210475876 A CN202210475876 A CN 202210475876A CN 114896023 A CN114896023 A CN 114896023A
Authority
CN
China
Prior art keywords
calling
class
call
relation
scene
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
CN202210475876.6A
Other languages
English (en)
Inventor
郑祎
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
WeBank Co Ltd
Original Assignee
WeBank Co Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by WeBank Co Ltd filed Critical WeBank Co Ltd
Priority to CN202210475876.6A priority Critical patent/CN114896023A/zh
Publication of CN114896023A publication Critical patent/CN114896023A/zh
Pending legal-status Critical Current

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/44Arrangements for executing specific programs
    • G06F9/455Emulation; Interpretation; Software simulation, e.g. virtualisation or emulation of application or operating system execution engines
    • G06F9/45504Abstract machines for programme code execution, e.g. Java virtual machine [JVM], interpreters, emulators
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/44Arrangements for executing specific programs
    • G06F9/448Execution paradigms, e.g. implementations of programming paradigms
    • G06F9/4488Object-oriented
    • G06F9/449Object-oriented method invocation or resolution
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/54Interprogram communication
    • G06F9/547Remote procedure calls [RPC]; Web services

Abstract

本申请公开了一种数据处理方法、装置、设备及存储介质,所述方法应用于Java虚拟机,所述方法包括:针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。对于本申请的方案,增加了第一场景下缺失的调用关系,克服了在第一场景下由于调用关系的缺失而导致的问题,扩大了获取Java程序方法调用关系的应用场景。

Description

一种数据处理方法、装置、设备及存储介质
技术领域
本申请涉及数据处理技术领域,涉及但不限于数据处理方法、装置、设备及存储介质。
背景技术
随着计算机技术的飞速发展,越来越多的技术应用在金融领域,传统金融业正在逐步向金融科技(Fintech)转变,但由于金融行业的安全性和实时性要求,也对技术提出了更高的要求。
相关技术中,在Java程序中方法之间的调用关系时,可以通过Java虚拟机涉及的相关方法调用指令分析得到方法之间的调用关系以及被调用方法的信息,在多数场景下可以获取到Java方法之间的调用关系。但是,对于一些特殊场景(线程调用场景、函数式编程场景等等),无法通过相关方法调用指令获取到调用关系。
这样,在第一场景下由于调用关系的缺失而导致的问题;降低了获取Java程序方法调用关系的应用场景。
发明内容
本申请提供一种数据处理方法及装置、设备、存储介质,增加了第一场景下缺失的调用关系,克服了在第一场景下由于调用关系的缺失而导致的问题,扩大了获取Java程序方法调用关系的应用场景。
本申请的技术方案是这样实现的:
本申请提供了一种数据处理方法,所述方法应用于Java虚拟机(Java VirtualMachine,JVM),所述方法包括:
针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;
增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;
输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。
本申请提供了一种数据处理装置,所述装置部署于JVM所属的电子设备,所述装置包括:
获得单元,用于针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;
增加单元,用于增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;
输出单元,用于输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。
本申请还提供了一种电子设备,包括:存储器和处理器,所述存储器存储有可在处理器上运行的计算机程序,所述处理器执行所述程序时实现上述数据处理方法。
本申请还提供了一种存储介质,其上存储有计算机程序,该计算机程序被处理器执行时实现上述数据处理方法。
本申请所提供的数据处理方法、装置、设备及存储介质,应用于JVM,包括:针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。对于本申请的方案,增加了第一场景下缺失的第一方法调用第二方法的第一调用关系,克服了在第一场景下由于调用关系的缺失而导致的问题,扩大了获取Java程序的方法调用关系的应用场景。
附图说明
图1为本申请实施例提供的数据处理系统的一种可选的结构示意图;
图2为本申请实施例提供的数据处理方法的一种可选的流程示意图
图3为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图4为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图5为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图6为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图7为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图8为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图9为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图10为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图11为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图12为本申请实施例提供的数据处理方法的一种可选的流程示意图;
图13为本申请实施例提供的数据处理装置的一种可选的结构示意图;
图14为本申请实施例提供的电子设备的一种可选的结构示意图。
具体实施方式
为使本申请实施例的目的、技术方案和优点更加清楚,下面将结合本申请实施例中的附图,对申请的具体技术方案做进一步详细描述。以下实施例用于说明本申请,但不用来限制本申请的范围。
在以下的描述中,涉及到“一些实施例”,其描述了所有可能实施例的子集,但是可以理解,“一些实施例”可以是所有可能实施例的相同子集或不同子集,并且可以在不冲突的情况下相互结合。
在以下的描述中,所涉及的术语“第一\第二\第三”仅是为例区别不同的对象,不代表针对对象的特定排序,不具有先后顺序的限定。可以理解地,“第一\第二\第三”在允许的情况下可以互换特定的顺序或先后次序,以使这里描述的本申请实施例能够以除了在这里图示或描述的以外的顺序实施。
除非另有定义,本文所使用的所有的技术和科学术语与属于本申请的技术领域的技术人员通常理解的含义相同。本文中所使用的术语只是为了描述本申请实施例的目的,不是旨在限制本申请。
本申请实施例可提供数据处理方法及装置、设备和存储介质。实际应用中,数据处理方法可由数据处理装置实现,数据处理装置中的各功能实体可以由电子设备的硬件资源,如处理器等计算资源、通信资源(如用于支持实现光缆、蜂窝等各种方式通信)协同实现。
本申请实施例提供的数据处理方法应用于数据处理系统,数据处理系统包括电子设备(为了便于区分,也可以称为第一电子设备)。
电子设备用于执行:针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。
可选的,数据处理系统还可以包括第二电子设备。第二电子设备用于得到第一Java程序文件,并将第一Java程序文件发送至第一电子设备。
需要说明的是,第一电子设备和第二电子设备可以集成于同一个电子设备上,也可以分别独立部署于不同的电子设备上。
作为一示例,数据处理系统的结构可如图1所示,包括:第一电子设备10和第二电子设备20。其中,第一电子设备10与第二电子设备20之间可以数据传输。
这里,第一电子设备10用于执行:针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。
其中,第一电子设备10可以为运行了Java虚拟机的电子设备(例如服务器等)。
第二电子设备20,用于得到第一Java程序文件,并将第一Java程序文件发送至第一电子设备10。
其中,第二电子设备20可以包括移动终端设备(例如手机、平板电脑等),或者非移动终端设备(例如台式电脑、服务器等)。
下面,结合图1所示的数据处理系统的示意图,对本申请实施例提供的数据处理方法及装置、设备和存储介质的各实施例进行说明。
第一方面,本申请实施例提供一种数据处理方法,该方法应用于数据处理装置;其中,该数据处理装置可以部署于图1中的第一电子设备10。下面,对本申请实施例提供的数据处理过程进行说明。
图2示意了一种可选的一种数据处理方法的流程示意图,参考图2所示的内容,该数据处理方法可以包括但不限于图2所示的S201至S203。
S201、第一电子设备针对第一场景,获得第一Java程序文件中的第一方法。
第一场景包括:线程调用场景或者函数式编程场景。
其中,函数式编程场景可以包括但不限于匿名函数(Lambda)表达式子调用场景或者流(stream)子调用场景。
第一Java程序文件,指采用Java语言编辑的程序文件。本申请实施例对第一Java程序文件的具体格式不作限定可以根据实际需求进行配置。
例如,第一Java程序文件可以包括但不限于:Java归档文件(Java Archive,Jar)包;或者,网络应用程序(Web Application Archive,War)包。
方法,也可以称为函数,可以包括但不限于一项或者多项:方法名、参数信息以及方法类名等等。
第一方法,指第一Java程序文件中的缺少调用关系的调用方法。其中,针对不同的场景,第一方法的类型可能不同。例如,针对线程调用场景,第一方法可以包括构造函数或者开始(start)函数。
S201的实施可以包括:第一电子设备先获得第一Java程序文件,遍历第一Java程序文件中的每个类(class)文件,针对每个class文件,读取class文件中的每个类,针对每个类,读取类中的每个方法,然后根据每个方法中的信息确定第一场景具体的类型,针对第一场景缺少的类型确定缺失的调用关系,基于缺失的调用关系得到第一方法。
S202、第一电子设备增加所述第一方法调用第二方法的第一调用关系。
第一方法与第二方法不同。
调用关系用于表征方法之间的调用过程之间的关系。本申请实施例对调用关系的表达方式不作限定可以根据实际需求进行配置。
示例性的,调用关系可以表现为:
TestRunnable:f2()RunnableImpl1:<init>();
RunnableImpl1:<init>()RunnableImpl1:run()。
其中,空格前面的方法为调用方法,空格后面的方法为被调用方法。
TestRunnable:f2()、RunnableImpl1:<init>()表示:方法TestRunnable:f2()调用RunnableImpl1:<init>;
RunnableImpl1:<init>()RunnableImpl1:run()表示:方法RunnableImpl1:<init>()调用RunnableImpl1:run()。
TestRunnable、RunnableImpl1、RunnableImpl1表示类名;f2、<init>、run表示方法名;()中为方法参数。其中,方法f2、<init>、run没有参数;包含参数的方法可以表示为:C:f(java.lang.String)。其中,java.lang.String为方法C中的参数。
可以看出:调用方法及被调用方法均由完整类名、方法名、方法参数组成。
可以理解的,调用方法及被调用方法还可以包括其他信息,此处不再一一列举。
可以理解的,调用关系还可以包括表格、固定语句等等其他表达方式。
第一调用关系为针对第一场景第一Java程序文件中缺少的调用关系。其中,针对不同的第一场景,第一Java程序文件中缺少的调用关系不同。
S202可以实施为:第一电子设备基于调用关系的格式,增加第一方法调用第二方法的第一调用关系。
S203、第一电子设备输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。
第一电子设备输出第一调用关系用于在需要时可以查找到第一调用关系,本申请实施例对输出的形式不作限定,可以根据实际需求进行配置。例如,输出可以为记录;或者输出还可以为记录并显示。
示例性的,S203可以实施为:第一电子设备在记录调用关系的文件中记录第一调用关系,这样,在需要该调用关系时,可以在记录调用关系的文件中查找到第一调用关系,以基于第一关系实现第一方法对第二方法的调用。
本申请实施例提供的数据处理方案应用于JVM,包括:针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。对于本申请的方案,增加了第一场景下缺失的第一方法调用第二方法的第一调用关系,克服了在第一场景下由于调用关系的缺失而导致的问题,扩大了获取Java程序方法调用关系的应用场景。
参考图3所示的内容,本申请实施例提供的数据处理方法在执行S202之前,还可以包括但不限于下述S204和S205。
S204、第一电子设备获得所述第一方法对应的类的第一取值。
第一取值用于表征是否已增加第一调用关系。
本申请实施例对于第一取值不作具体限定,可以根据实际需求进行配置。
在一种可能的实施方式中,第一取值可以包括:假(FALSE)或者真(TRUE)。在该可能的实施方式中,若第一取值为FALSE,表示未增加第一调用关系;若第一取值为TRUE,表示已增加第一调用关系。
可以理解的,第一取值还可以包括:0或者1。在该可能的实施方式中,若第一取值为0,表示未增加第一调用关系;若第一取值为1,表示已增加第一调用关系。
本申请实施例对获取第一方法对应的类的过程不作限定。示例性的,第一设备获取第一方法对应的类文件的接口列表,在该接口列表中获取具体的类,并获取该类的第一取值。
S205、第一电子设备确定所述第一取值表征未增加所述第一调用关系。
S205可以实施为:第一电子设备获取到第一取值后,基于第一取值表征的含义确定未增加第一调用关系。
例如:若当前类对应的接口列表中包含可运行(Runnable)接口实现类,在Runnable接口实现类映射表(Map)中,以当前类的名称为作为键(key),查找到其对应的值(value)为FALSE,则表示在Runnable接口实现类中未增加第一调用关系。
若当前类对应的接口列表中包含可调用(Callable)接口实现类,在Callable接口实现类Map中,以当前类的名称为作为key,查找到其对应的value为FALSE,则表示在Callable接口实现类中未增加第一调用关系。
若当前类对应的父类为线程(Thread)类,则在Thread子类Map中,以当前类的名称为作为key,查找到其对应的value为FALSE,则表示在Thread子类中未增加第一调用关系。
需要说明的是,若第一电子设备确定第一取值表征已增加所述第一调用关系,则不用执行S202,直接继续进行下一步的操作。
下面,对S202第一设备增加所述第一方法调用第二方法的第一调用关系的过程进行说明。具体可以包括但不限于下述方式A或方式B。
方式A、针对线程调用场景;
方式B、针对函数式编程场景。
其中,在方式A中,具体还可以包括但不限于下述方式A1或方式A2。
方式A1、针对第一方法为构造函数的情况;
方式A2、针对第一方法为开始(start)函数的情况。
下面,对方式A1的实现过程进行说明。
在所述第一方法为构造函数的情况下,增加所述第一调用关系为所述构造函数调用所述第二方法的第一子调用关系。
具体的,在所述第一方法对应的类包括Runnable接口实现类的情况下,所述第二方法包括运行(run)方法;对应的,所述第一子调用关系用于表征所述构造函数调用所述run方法。
在所述第一方法对应的类包括Callable接口实现类的情况下,所述第二方法包括调用(call)方法;对应的,所述第一子调用关系用于表征所述构造函数调用所述call方法。
例如,在Runnable接口的实现类中,自定义代码需要在run()方法中实现。Runnable接口实现类有多种不同的使用方式,可用于创建Thread、异步执行方式(FutureTask)、周期性线程池执行程序(ScheduledThreadPoolExecutor)类对象,作为线程池执行程序(ThreadPoolExecutor.execute)方法的参数等。在不同的使用场景中Runnable接口实现类的run()方法会在不同的时间点,不同的方法中被执行。为了简化处理过程,且保证不同场景下Runnable接口实现类的run()方法都能够被补充,在处理到方法调用指令中调用Runnable接口实现类的构造函数(<init>())方法时,会增加一条对应的Runnable接口实现类的<init>()方法调用run()方法的调用关系。
下面,对方式A2的实现过程进行说明。
在所述第一方法为开始start函数,且所述start函数的参数为空的情况下,增加所述第一调用关系为所述start函数调用运行(run)方法的第二子调用关系。
例如,在Thread类的子类中,在线程中执行的自定义代码需要在run()方法中实现。在启动线程时,需要调用Thread子类的start()方法,之后Java虚拟机会调用run()方法。以上调用关系不包含在Java虚拟机的方法调用指令中,为了补充以上调用关系,在处理到调用Thread子类的start()方法时,会增加一条对应的Thread子类的start()方法调用run()方法的调用关系。
参考图4所示的内容,本申请实施例提供的数据处理方法在执行S202之前,还可以进行预处理,通过预处理建立各类对应的与线程调用及父类相关的信息。具体可以包括但不限于下述S206至S209。
S206、第一设备增加Runnable接口实现类记录、Callable接口实现类记录以及Thread子类记录。
S206可以实施为:第一设备在内存中增加Runnable接口实现类记录、Callable接口实现类记录以及Thread子类记录。
可以理解的,Runnable接口实现类记录、Callable接口实现类记录以及Thread子类记录也可以在其他文件中。
本申请实施例对Runnable接口实现类记录、Callable接口实现类记录以及Thread子类记录的具体格式不作限定,可以根据实际需求进行配置。
示例性的,Runnable接口实现类记录可以为Runnable接口实现类Map;Callable接口实现类记录以为Callable接口实现类Map;Thread子类记录可以为Thread子类Map。
S207、若所述第一方法对应的类包括接口实现Runnable类,第一设备在所述Runnable接口实现类记录中,记录所述第一方法对应的类的第一取值为第一数值。
第一数值用于表征在Runnable接口实现类记录中未增加第一调用关系。
本申请实施例对第一数值不作具体限定,可以根据实际需求进行配置。例如,第一数值可以为FALSE或者0。
S208、若所述第一方法对应的类包括Callable接口实现类,第一设备在所述Callable接口实现类记录中,记录所述第一方法对应的类的第一取值为第二数值。
第二数值用于表征在Runnable接口实现类记录中未增加第一调用关系。
其中,第二数值可以与第一数值相同,也可以与第一数值不同。
S209、若所述第一方法对应的类包括线程Thread子类,第一设备在所述Thread子类记录中,记录所述第一方法对应的类的第一取值为第三数值。
第三数值用于表征在Thread子类记录中未增加第一调用关系。
其中,第三数值可以与第一数值相同,也可以与第一数值不同;
第三数值可以与第二数值相同,也可以与第二数值不同。
下面,对方式B、针对函数式编程场景,第一设备增加第一方法调用第二方法的第一调用关系的过程进行说明。参考图5所示的内容,具体可以包括但不限于下述S2021和S2022。
其中,函数式编程场景可以包括但不限于匿名函数(Lambda)表达式子场景,或者Stream(流)调用子场景。其中,Lambda表达式子场景的处理方式与Stream流调用子场景的处理方式类似,下面以Lambda表达式子场景的处理过程为例进行说明。
在调用Lambda表达式时,被调用的Lambda表达式方法信息不在Java虚拟机方法调用指令中,而是保存在当前类的引导方法中,本申请的实施例会模拟Java虚拟机执行Lambda表达式方法时的执行过程,从引导方法中获取被调用的Lambda表达式具体方法信息。
S2021、若调用所述第二方法的指令为动态调用invokedynamic指令,第一设备从引导方法中获取所述第二方法的方法信息。
S2021可以实施为:若调用所述第二方法的指令为动态调用(invokedynamic)指令,说明当前指令调用的是动态方法,可能调用了Lambda表达式,第一设备从引导方法中获取第二方法的方法信息。
本申请实施例对方法信息的具体内容不作限定,可以根据实际需求进行配置。例如,方法信息可以包括:参数、类名、方法名。
可以理解的,方法信息在Java的class文件的常量池中还可以包括:方法句柄、方法描述等等。
S2022、第一设备基于所述第二方法的方法信息,增加所述第一调用关系。
S2022可以实施为:第一设备基于第二方法的方法信息,增加第一调用关系。
示例性的,第二方法的方法信息可以包括:a.b.F:f1()。其中,a.b.F为类名,f1为方法名,()为参数,这里的参数为空。增加的第一调用关系可以为:a.b.D:d1(int)a.b.F:f1()。
下面,对S2021第一设备从引导方法中获取所述第二方法的方法信息的过程进行说明。参考图6所示的内容,具体可以包括但不限于S601至S605。
S601、第一设备从当前类的常量池中,基于常量动态调用信息CONSTANT_InvokeDynamic_info对象获取引导方法。
示例性的,第一设备从当前类的常量池中,根据当前被调用指令在当前类的常量池中的索引值,获取对应的类型为常量动态调用信息(CONSTANT_InvokeDynamic_info)的常量对象,通过该对象可以获取到invokedynamic指令使用的引导方法、动态调用名称、参数及返回类型等信息。
具体的,CONSTANT_InvokeDynamic_info的引导方法索引(bootstrap_method_attr_index)属性值代表被调用的引导方法在当前类的引导方法数组中的下标。通过遍历当前类的属性的方式,找到类型为引导方法(BootstrapMethods)的属性,即当前类的引导方法信息,获得对应的引导方法数组;以上述CONSTANT_InvokeDynamic_info对象中的bootstrap_method_attr_index属性值作为下标,从引导方法数组中获取对应的引导方法对象。
S602、第一设备基于引导参数bootstrap_arguments数组,从所述引导方法中获取所述第二方法的参数。
引导方法中保存了引导参数(bootstrap_arguments)数组,该数组保存的值是当前引导方法使用的参数在当前类的常量池中的索引。
第一设备遍历引导方法的bootstrap_arguments数组,从当前类的常量池中获取对应的参数常量对象,作为第一方法的参数。
S603、第一设备基于类索引class_index属性值,从所述引导方法中获取所述第二方法对应的类名。
常量字段信息(CONSTANT_Fieldref_info)、常量方法信息(CONSTANT_Methodref_info)或常量接口方法信息CONSTANT_InterfaceMethodref_info类型具有类似的结构,都有类索引(class_index)及名称及描述索引(name_and_type_index),分别为类(或接口)在类的常量池的索引,方法(或变量)的名称及描述符在类的常量池的索引。
第一设备根据以上CONSTANT_Fieldref_info、CONSTANT_Methodref_info或CONSTANT_InterfaceMethodref_info类型的常量中的class_index索引值,从当前类的常量池中获取类名对应的字符串。
可选的,该类名字符串的格式是“a/b/c”的形式,需要转换为“a.b.c”的形式,将转换后的字符串作为第二方法对应的类名。
S604、第一设备基于名称索引name_index属性值,从所述引导方法中获取所述第二方法对应的方法名称。
第一设备根据CONSTANT_NameAndType_info类型常量中的name_index索引,从当前类的常量池的引导方法中获取方法名称字符串。
S605、第一设备基于所述参数、所述类名以及所述方法名称确定所述第二方法的方法信息。
第一设备基于方法信息的存储格式将该参数、类名以及方法名称整理为第一方法的方法信息。
下面以Java虚拟机指令为例,通过一个实施例对本申请实施例提供的数据处理方法进行说明。
下面,对该实施例涉及的部分技术术语进行解释。
Java虚拟机(Java Virtual Machine,JVM):是一个抽象的计算机。Java虚拟机像真正的计算机一样,有一个指令集在运行时操纵各种内存区域。
Java虚拟机指令:对于计算机处理器而言,指令是一段包含了需要由处理器执行的步骤的代码。计算机必须在接受到指令后才能知道需要进行什么操作。Java虚拟机是一种抽象的计算机,像真正的计算机一样,也具有指令集。
Java开发工具包(Java Development Kit,JDK):用于使用Java编程语言构建应用程序等的开发环境。
Java归档文件(Java Archive,Jar)包:指将Java工程的.java文件编译为.class文件后,将.class文件及其他配置文件压缩为后缀为.jar的压缩包。Jar包可在其他Java工程中直接使用相关代码的功能。
网络应用程序(Web Application Archive,War)包:与jar包的格式类似,但war包通常用于网络(Web)项目,通常还包含Web项目中使用的静态资源文件,可用于在Java容器中进行部署并提供Web服务功能。
类(class)文件:由Java虚拟机执行的编译代码使用独立于硬件和操作系统的二进制格式表示,通常(但不一定)存储在文件中,称为class文件格式。其中,class文件中包含Java虚拟机指令(或字节码)和符号表,以及其他辅助信息。
在Java虚拟机指令中,用于方法调用的指令可以包括以下五个指令。
虚拟调用(invokevirtual)指令:用于调用对象的实例方法,在对象的(虚拟)类型上进行调度。这是Java语言中的常规方法分派方式。
接口调用(invokeinterface)指令:用于调用接口方法,搜索特定运行时对象实现的方法以找到合适的方法。
特殊调用(invokespecial)指令:用于调用需要特殊处理的实例方法。例如特殊处理的实例方法可以包括:实例初始化方法、私有方法、父类方法等。
静态调用(invokestatic)指令:调用命名类中的类(静态)方法。
动态调用(invokedynamic)指令:调用动态方法。
以上方法调用指令中包含了被调用方法类名、方法名、参数信息等在常量池中的索引,通过方法调用指令,可以获取到被调用方法的详细信息。
参考图7所示的内容,gousiosg/java-callgraph项目使用字节码工程库(ByteCode Engineering Library,BCEL)解析Java class文件字节码并获取Java方法调用关系可以包括但不限于下述步骤A1至步骤A4。
步骤A1、使用Java语言的软件开发工具包(Java Development Kit,JDK)提供的方法打开Java归档文件(Java Archive,JAR)包/网络应用程序(Web Application Archive,War)包,并遍历其中的每个文件。
步骤A2、对于class文件,使用BCEL提供的方法对当前class文件对应的类进行解析。
步骤A3、遍历当前处理的类中定义的方法的每一条指令,若当前指令属于方法调用指令,则通过方法调用指令获取对应的被调用方法信息。
步骤A4、将以上不同方法之间的调用关系记录到文件。
gousiosg/java-callgraph项目在获取Java方法调用关系时,通过分析Java虚拟机方法调用指令获取被调用方法的信息,在多数场景下能够获取到Java方法调用关系,但存在一些场景无法获取到调用关系,包括:线程调用、函数式编程等场景。
下面,对于线程调用场景进行说明。
Runnable实现类线程调用过程可以包括:假如f1方法中使用内部匿名类形式的Runnable接口实现类在线程中执行操作,在线程中执行了f2方法。
具体程序可以包括:
Figure BDA0003625530860000111
Figure BDA0003625530860000121
通过Thread子类创建线程时,调用的是Thread子类的start()方法,实际的操作在run()方法中实现。即创建线程时调用的方法,与线程实际执行的方法不同。
在gousiosg/java-callgraph项目生成的方法调用关系中,f1调用f2的调用关系会缺失,即f1通过f2间接调用的方法调用关系也会缺失。
对于使用命名类形式的Runnable接口实现类线程调用,Callable实现类线程调用,线程(Thread)类的子类线程调用,与Runnable接口实现类线程调用情况类似,此处不再一一赘述。
下面,对函数式编程场景进行说明。
匿名函数(Lambda)表达式(含线程调用等)的调用过程可以包括:假如f1方法中使用Lambda表达式的形式在线程中执行操作,在线程中执行了f2方法。
具体程序可以包括:
Figure BDA0003625530860000122
使用BCEL的应用程序接口(Application Programming Interface,API)获取Lambda表达式被调用的方法信息时,获取到的不是实际被执行的方法信息。
在gousiosg/java-callgraph项目生成的方法调用关系中,f1调用f2的调用关系会缺失,即f1通过f2间接调用的其他方法的调用关系也会缺失。对于其他使用Lambda表达式的情况,存在相同的问题,原方法调用Lambda表达式中执行的方法的调用关系会缺失,即原方法通过Lambda表达式中执行的方法间接调用的其他方法的调用关系也会缺失。
流(Stream)调用方法调用关系缺失的情况为:在使用Stream时,通过xxx::func方式调用方法,gousiosg/java-callgraph项目生成的方法调用关系中会缺失,与Lambda表达式的情况类似。
例如,具体的程序可以包括:
list.stream().map(this::map2).filter(this::filter2).collect(Collectors.toList());
list.stream().map(TestDto1::getStr).collect(Collectors.toList());
//stream方法,返回当前list集合的流;
//map方法,返回一个流,其中包含执行指定的方法后存在的结果;
//filter方法,返回一个流,其中包含在执行指定的过滤条件后还存在的结果;
//collect方法,对结果进行收集,通过指定类型的集合返回。
在gousiosg/java-callgraph项目生成的方法调用关系中,当前方法调用当前类的map2()、filter2(),及TestDto1类的getStr()方法的调用关系会缺失。
具体分析,调用关系缺失的原因包括:gousiosg/java-callgraph项目仅根据方法调用指令获取方法间的调用关系,在部分场景下无法获取到,因为这些场景下,方法间的调用关系不只是与方法调用指令有关,还受到其他因素影响。
例如,对于线程调用场景,方法间的调用关系存在一些隐含的特殊调用关系;对于函数式编程场景,被调用的方法信息不仅保存在方法调用指令中,还保存在引导方法(Bootstrap method)中。
对于gousiosg/java-callgraph项目无法完整获取线程调用、函数式编程等场景的调用关系的问题,本申请的该实施例能够补充缺失的调用关系。
为了解决线程调用、函数式编程等场景的调用关系无法完整获取的问题,本申请的该实施例在获取方法调用关系时,不只是通过Java虚拟机方法调用指令进行获取,还结合了对应场景的代码在实际运行时的执行步骤,获取方法调用指令之外的调用关系。
相关技术在获取Java方法调用关系时,仅根据class文件字节码中的invokevirtual、invokeinterface、invokespecial、invokestatic、invokedynamic等指令获取方法调用关系,无法获取到上述需要进行特殊处理的方法调用关系。
对于线程调用场景,相关技术无法获取对应的方法调用关系,主要原因是创建线程时调用的方法,与线程实际执行的方法不同。
例如,通过Thread子类创建线程时,调用的是Thread子类的start()方法,实际的操作在run()方法中实现。
对于函数式编程,相关技术无法获取对应的方法调用关系,主要原因是,class文件Lambda表达式及Stream调用相关的字节码,使用BCEL的应用程序接口(ApplicationProgramming Interface,API)获取被调用的方法信息时,获取到的不是实际被执行的方法信息。
例如,使用了Stream的代码“list.stream().map(TestClass::func).collect(Collectors.toList()))”,在获取“.map(TestClass::func)”对应的被调用方法时,获取到的是“java.util.function.Function:apply()”方法,而不是“TestClass:func()”方法。
下面,对相关技术中的调用过程进行说明,具体可以包括但不限于下述步骤B1至步骤B5。
步骤B1、获取程序执行参数中指定的需要处理的jar包,支持指定多个jar包一次处理。
步骤B2、遍历所有的jar包,在处理每个jar包时,遍历其中的class文件,并对class文件进行处理。
步骤B3、在处理class文件时,遍历当前类中的方法,并对每个方法进行处理。
具体的,在处理class文件时,处理当前类中的Lambda方法,通过正则表达式匹配的方式将方法名中的空值(null)修改为对应方法名。
步骤B4、在处理类中的方法时,根据对应方法名获取当前方法对其他方法的调用关系。
步骤B5、将获取到的全部方法调用关系输出到结果文件中。
简单来说,如图8所示,相关技术的调用过程可以包括:开始;S801、遍历指定的jar文件;S802、处理jar包中的class文件;S803、处理当前类中的Lambda方法,将方法名中的null修改为对应方法名;S804、处理class文件中的方法;S805、获取方法间调用关系;S806、将方法间调用关系写入结果文件;结束。
相关技术存在一些场景下的调用关系会缺失,为了解决这些调用关系缺失的问题,本申请的该实施例对执行步骤进行修改,本申请的该实施例的完整执行步骤可以包括下述步骤C1至步骤C7。
步骤C1、获取程序执行参数中指定的需要处理的jar包,支持指定多个jar包一次处理。
其中,与相关技术相比,步骤C1为保持不变的步骤;即步骤C1与相关技术中的步骤B1保持一致。
步骤C2、遍历所有的jar包,对jar包中的class文件进行预处理,用于获得线程调用等场景缺失的方法调用关系所需信息。
其中,与相关技术相比,步骤C2为新增的步骤。
步骤C3、遍历所有的jar包,在处理每个jar包时,遍历其中的class文件,并对class文件进行后续的处理。
其中,与相关技术相比,步骤C3为保持不变的步骤;即步骤C3与相关技术中的步骤B2保持一致。
步骤C4、在处理class文件时,遍历当前类中的方法,并对每个方法进行处理。
其中,与相关技术相比,步骤C4为保持不变的步骤;即步骤C4与相关技术中的步骤B3保持一致。
步骤C5、在处理类中的方法时,获取当前方法对其他方法的调用关系。
其中,与相关技术相比,步骤C5为保持不变的步骤;即步骤C5与相关技术中的步骤B4保持一致。
步骤C6、在处理类中的某个方法时,对函数式编程、线程调用等场景缺失的方法调用关系进行补充。
其中,与相关技术相比,步骤C6为新增的步骤。
步骤C7、将获取到的全部方法调用关系输出到结果文件中。
其中,与相关技术相比,步骤C7为保持不变的步骤;即步骤C7与相关技术中的步骤B5保持一致。
简单来说,如图9所示,本申请该实施例的调用过程可以包括:开始;S901、遍历指定的jar文件;S902、对class文件预处理以获取后续所需信息;S903、处理jar包中的class文件;S904、处理class文件中的方法;S905、补充函数式编程、线程调用等关系;S906、获取方法间调用关系;S907、将方法间调用关系写入结果文件;结束。
本申请的该实施例为了实现以上对步骤的修改,新增了以下程序变量:
记录Runnable接口实现类Map;
记录Callable接口实现类Map;
记录Thread子类Map。
下面,对步骤C1获取程序执行参数中指定的需要处理的jar包,支持指定多个jar包一次处理的实现过程进行说明。
获取程序执行参数中指定的需要处理的jar包,支持指定多个jar包一次处理,对于每个jar包依次执行后续的处理。
下面,对步骤C2遍历所有的jar包,对jar包中的class文件进行预处理,用于获得线程调用等场景缺失的方法调用关系所需信息的实现过程进行说明。
遍历所有的jar包,对jar包中的class文件进行以下预处理,用于获得线程调用、实现与继承等场景缺失的方法调用关系所需信息。
对当前jar包中的class文件进行遍历,并对每个class文件进行以下预处理:
判断当前class文件对应的是一个类还是一个接口;
若当前class文件对应一个类,则获取当前类实现的接口列表。
若当前类对应的接口列表中包含Runnable,则记录到Runnable接口实现类Map中,key为当前类的名称,value为FALSE,代表当前类还未被处理;
若当前类对应的接口列表中包含Callable,则记录到Callable接口实现类Map中,key为当前类的名称,value为FALSE,代表当前类还未被处理;
继续判断当前处理class文件对应的父类:
若当前class文件对应的父类为Thread类,则记录到Thread子类Map中,key为当前class文件类名,value为FALSE,代表当前类还未被处理。
简单来说,如图10所示,本申请该实施例步骤C2的实现过程可以包括:开始;S1001、判断当前class文件是否是一个类,若是执行S1002,继续执行S1005;S1002、记录实现类对应的接口信息及实现的方法;S1003、记录Runnable接口实现类;S1004、记录Callable接口实现类;S1005、获取当前class文件的父类类名;S1006、记录Thread子类;结束。
下面,对步骤C3遍历所有的jar包,在处理每个jar包时,遍历其中的class文件,并对class文件进行后续的处理的过程进行说明。
遍历所有的jar包,在处理每个jar包时,遍历其中的class文件,并对class文件进行后续的处理。
下面,对步骤C6在处理类中的某个方法时,对函数式编程、线程调用等场景缺失的方法调用关系进行补充的过程进行说明。
在处理类中的某个方法时,对函数式编程、线程调用等场景缺失的方法调用关系进行补充。
下面,对处理线程调用方法的过程进行说明。
在Thread类的子类中,在线程中执行的自定义代码需要在run方法中实现。在启动线程时,需要调用Thread子类的start方法,之后Java虚拟机会调用run方法。以上调用关系不包含在Java虚拟机的方法调用指令中,为了补充以上调用关系,本申请的该实施例在处理到调用Thread子类的start方法的指令时,会增加一条对应的Thread子类的start方法调用run方法的调用关系。
在Runnable接口的实现类中,自定义代码需要在run方法中实现。Runnable接口实现类有多种不同的使用方式,可用于创建Thread、FutureTask、ScheduledThreadPoolExecutor类对象,作为ThreadPoolExecutor.execute方法的参数等。在不同的使用场景中Runnable接口实现类的run方法会在不同的时间点,不同的方法中被执行。为了简化处理过程,且保证不同场景下Runnable接口实现类的run方法都能够被补充,本申请的该实施例在处理到调用Runnable接口实现类的构造函数<init>方法时,会增加一条对应的Runnable接口实现类的<init>方法调用run方法的调用关系。
例如,RunnableImpl1类为Runnable接口的实现类,在run()方法中调用了System.out.println()方法。
Figure BDA0003625530860000161
Figure BDA0003625530860000171
TestRunnable类的f2()方法中,创建了RunnableImpl1类的实例,作为Thread类构造函数的参数,并调用创建的Thread类的start()方法。
Figure BDA0003625530860000172
使用现有技术处理以上代码的方法调用关系,获得的结果如下所示:
Figure BDA0003625530860000173
可以看到,TestRunnable:f2()方法调用RunnableImpl1:<init>()的调用关系,与后续RunnableImpl1:run()方法调用java.io.PrintStream:println(java.lang.String)方法的调用关系之间无法关联起来。
本申请的实施例在进行优化后,在处理到TestRunnable:f2()方法调用Runnable接口实现类的RunnableImpl1构造函数<init>()方法的指令时,会增加一条RunnableImpl1类的<init>()方法调用run()方法的调用关系,如下“RunnableImpl1:<init>()RunnableImpl1:run()”
Figure BDA0003625530860000174
增加上述关系后,TestRunnable:f2()方法调用RunnableImpl1:<init>()方法的调用关系,可以关联到RunnableImpl1:<init>()方法调用RunnableImpl1:run()方法的调用关系,再关联到RunnableImpl1:run()方法调用java.io.PrintStream:println(java.lang.String)方法的调用关系,缺失的方法调用关系已经完成补充。
处理线程调用方法可以包括以下两种情况。
第一种情况、若当前被调用方法为构造函数“<init>”,使用当前被调用的类名作为Key,从记录Runnable接口实现类Map(在新增的对class文件预处理步骤中获取)中查找对应的Value。
若以上获取的Value值为假,说明当前被调用的类为Runnable接口实现类,且未被记录过,则记录被调用类的<init>方法调用run方法的调用关系,并在记录Runnable接口实现类Map更新记录,Key为当前被调用的类名,Value为真。
若当前被调用方法为构造函数<init>,使用当前被调用的类名作为Key,从记录Callable接口实现类Map(在新增的对class文件预处理步骤中获取)中查找对应的Value。
若以上获取的Value值为假,说明当前被调用的类为Callable接口实现类,且未被记录过,则记录被调用类的<init>方法调用call方法的调用关系,并在记录Callable接口实现类Map更新记录,Key为当前被调用的类名,Value为真。
第二种情况:若当前被调用方法名为开始(start),参数为空,且从记录Thread子类Map(在新增的对class文件预处理步骤中获取)中使用当前被调用的类名作为Key查询到的Value为假,说明当前被调用的方法为Thread子类的start方法,且未被记录过,则记录被调用类的start方法调用run方法的调用关系,并更新Thread子类Map中的记录,将Key为当前被调用的类名的Value更新为真。
简单来说,如图11所示,本申请该实施例线程调用方法的实现过程可以包括:开始;S1101、判断当前被调用的方法是否为构造函数(构造方法),若是执行S1102,若否执行S1110;S1102、从记录Runnable接口实现类Map中获取Value;S1103、判断获取的Value是否为假,若是执行S1104,若否结束;S1104、记录被调用类的构造方法调用run方法的调用关系;S1105、更新Runnable接口实现类Map中的记录;S1106、从记录Callable接口实现类Map中获取Value;S1107、判断获取的Value是否为假,若是执行S1108,若否结束;S1108、记录被调用类的构造方法调用call方法的调用关系;S1109、更新Callable接口实现类Map中的记录;S1110、判断当前被调用的方法的方法名是否为start,参数是否为空;若是执行S1111,否则结束;S1111、从记录Thread子类Map中获取value;S1112、判断获取的Value是否为假,若是执行S1113,若否结束;S1113、记录被调用类的start方法调用run方法的调用关系;S1114、更新Thread子类Map中的记录;结束。
在调用Lambda表达式时,被调用的Lambda表达式方法信息不在Java虚拟机方法调用指令中,而是保存在当前类的引导方法中。
本申请的该实施例会模拟Java虚拟机执行Lambda表达式方法时的执行过程,从引导方法中获取被调用的Lambda表达式具体方法信息,并添加一条原方法调用Lambda表达式对应方法的调用关系,如下所示:
TestLambda类的test()方法中使用了Lambda表达式,在Lambda表达式中调用了System.getProperty()方法
Figure BDA0003625530860000181
Figure BDA0003625530860000191
使用现有技术处理以上代码的方法调用关系,获得的结果如下所示:
Figure BDA0003625530860000192
可以看到,TestLambda:test()方法调用Lambda表达式的调用关系,与后续Lambda表达式调用java.lang.System:getProperty(java.lang.String)方法的调用关系之间无法关联起来。
本申请的实施例在进行优化后,在处理到TestLambda:test()方法调用Lambda表达式时,会增加一条TestLambda类的test()方法调用lambda$test$0()方法的调用关系,如下“TestLambda:test()test.call_graph.lambda.TestLambda:lambda$test$0(java.lang.String)”
Figure BDA0003625530860000193
增加上述关系后,TestLambda:test()方法调用Lambda表达式的调用关系,可以关联到Lambda表达式调用java.lang.System:getProperty(java.lang.String)方法的调用关系,缺失的方法调用关系已经完成补充。
以下为处理Lambda表达式的具体步骤:
若当前方法调用被调用方法的指令为invokedynamic,说明当前指令调用的是动态方法,可能调用了Lambda表达式,进行以下处理:
从当前类的常量池中,根据当前被调用指令在当前类的常量池中的索引值,获取对应的类型为CONSTANT_InvokeDynamic_info的常量对象,通过该对象可以获取到invokedynamic指令使用的引导方法、动态调用名称、参数及返回类型等信息。CONSTANT_InvokeDynamic_info的bootstrap_method_attr_index属性值代表被调用的引导方法在当前类的引导方法数组中的下标。
遍历当前类的属性,找到类型为BootstrapMethods的属性,即当前类的引导方法信息,获得对应的引导方法数组;以上述CONSTANT_InvokeDynamic_info对象中的bootstrap_method_attr_index属性值作为下标,从引导方法数组中获取对应的引导方法对象。
引导方法中保存了bootstrap_arguments数组,该数组保存的值是当前引导方法使用的参数在当前类的常量池中的索引。遍历引导方法的bootstrap_arguments数组,以每个值作为索引,从当前类的常量池中获取对应的常量对象,若常量类型为CONSTANT_MethodHandle_info,则进行后续处理:
CONSTANT_MethodHandle_info常量对象是一个方法句柄,其中的reference_index属性为当前方法句柄在当前类的常量池中的索引。以CONSTANT_MethodHandle_info对象中的reference_index属性值作为索引,从当前类的常量池中,获取对应的方法句柄常量对象,该常量对象类型可能为CONSTANT_Fieldref_info、CONSTANT_Methodref_info或CONSTANT_InterfaceMethodref_info中的一种。
CONSTANT_Fieldref_info、CONSTANT_Methodref_info或CONSTANT_InterfaceMethodref_info类型具有类似的结构,都有class_index及name_and_type_index,分别为类(或接口)在类的常量池的索引,方法(或变量)的名称及描述符在类的常量池的索引。
根据以上CONSTANT_Fieldref_info、CONSTANT_Methodref_info或CONSTANT_InterfaceMethodref_info类型的常量中的class_index索引值,从当前类的常量池中获取类名对应的字符串,该类名字符串的格式是“a/b/c”的形式,需要转换为“a.b.c”的形式,例如“java/lang/String”转换后为“java.lang.String”;
根据以上CONSTANT_Fieldref_info、CONSTANT_Methodref_info或CONSTANT_InterfaceMethodref_info类型的常量中的name_and_type_index索引,从当前类的常量池中获取对应的类型为CONSTANT_NameAndType_info的常量对象。
CONSTANT_NameAndType_info表示一个字段或一个方法,其中包含了name_index、descriptor_index属性,name_index代表字段或方法名称在当前类的常量池中CONSTANT_Utf8_info类型常量对象的索引、descriptor_index代表字段或方法描述符(包含了方法参数)在当前类的常量池中CONSTANT_Utf8_info类型常量对象的索引。
根据CONSTANT_NameAndType_info类型常量中的name_index索引,从当前类的常量池中获取方法名称字符串;再根据descriptor_index索引,从当前类的常量池中获取方法参数字符串;该方法参数字符串的格式是“La/b/C;”的形式,需要转换为“a.b.C”的形式,例如“Ljava/lang/String;”需要转换为“java.lang.String”。
以上获得的被调用的方法信息,即为被调用的Lambda方法信息,可以记录当前方法调用Lambda方法的调用关系。
简单来说,如图12所示,本申请该实施例Lambda表达式调用方法的实现过程可以包括:开始;S1201、判断当前方法调用被调用方法的指令是否为invokedynamic,若是执行S1202,若否结束;S1202、根据当前指令索引值从当前方法的常量池中获取CONSTANT_InvokeDynamic_info常量;S1203、遍历当前类的属性,获得BootstrapMethod属性的BootstrapMethod数组;S1204、获得CONSTANT_InvokeDynamic_info对象中bootstrap方法在常量中的索引值;S1205、根据以上索引值作为下标从BootstrapMethod数组中获取对应的BootstrapMethod对象;S1206、遍历bootstrapMethod在常量池中的引用索引数组;S1207、从当前的常量池中获取每个引用索引对应的CONSTANT_MethodHandle_info常量对象;S1208、从当前类的常量池中根据以CONSTANT_MethodHandle_info对象中的引用索引作为下标获取对应的常量;S1209、从当前类的常量池中根据以上常量中的类的索引获取类名字符串,并进行转换;S1210、从当前类的常量池中根据以上常量中方法的名称及类型的索引获取CONSTANT_NameAndType_info常量;S1211、从当前类的常量池中根据以上常量方法名称的索引获取方法名称字符串;S1212、从当前类的常量池中根据以上常量描述符的索引获取方法参数字符串,并进行转换;S1213、记录当前方法调用Lambda方法的调用关系;结束。
Stream调用与Lambda表达式的处理方式相同,不再一一赘述。
将获取到的全部方法调用关系输出到结果文件中,包括从Java虚拟机方法调用指令中获取的方法调用关系,以及本申请的该实施例补充的线程调用、函数式编程相关的方法调用关系。
在结果文件中保存了方法调用关系,每行代表一条方法调用关系,格式为“调用方法被调用方法”,调用方法及被调用方法均由完整类名、方法名、方法参数组成,如下所示:
Figure BDA0003625530860000211
为实现上述数据处理方法,本申请实施例的一种数据处理装置,下面结合图13所示的数据处理装置的结构示意图进行说明。
如图13所示,数据处理装置130包括:获得单元1301、增加单元1302、和输出单元1303。其中:
获得单元1301,用于针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;
增加单元1302,用于增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;
输出单元1303,用于输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。
在一些实施例中,数据处理装置130还可以包括确定单元,确定单元还用于:
获得所述第一方法对应的类的第一取值;所述第一取值用于表征是否已增加所述第一调用关系;
确定所述第一取值表征未增加所述第一调用关系。
在一些实施例中,若所述第一场景包括线程调用场景,增加单元1302具体用于:
在所述第一方法为构造函数的情况下,增加所述第一调用关系为所述构造函数调用所述第二方法的第一子调用关系;
在所述第一方法为开始start函数,且所述start函数的参数为空的情况下,增加所述第一调用关系为所述start函数调用运行run方法的第二子调用关系。
在一些实施例中,在所述第一方法对应的类包括Runnable接口实现类的情况下,所述第二方法包括run方法;对应的,所述第一子调用关系用于表征所述构造函数调用所述run方法;
在所述第一方法对应的类包括Callable接口实现类的情况下,所述第二方法包括调用call方法;对应的,所述第一子调用关系用于表征所述构造函数调用所述call方法。
在一些实施例中,数据处理装置130还可以包括预处理单元,在所述增加所述第一方法调用第二方法的第一调用关系之前,预处理单元用于:
增加Runnable接口实现类记录、Callable接口实现类记录以及线程Thread子类记录;
若所述第一方法对应的类包括Runnable接口实现类,在所述Runnable接口实现类记录中,记录所述第一方法对应的类的第一取值为第一数值;所述第一数值用于表征在所述Runnable接口实现类记录中未增加所述第一调用关系;
若所述第一方法对应的类包括Callable接口实现类,在所述Callable接口实现类记录中,记录所述第一方法对应的类的第一取值为第二数值;所述第二数值用于表征在所述Callable接口实现类记录中未增加所述第一调用关系;
若所述第一方法对应的类包括线程Thread子类,在所述Thread子类记录中,记录所述第一方法对应的类的第一取值为第三数值;所述第三数值用于表征在所述Thread子类记录中未增加所述第一调用关系。
在一些实施例中,若所述第一场景包括函数式编程场景,增加单元1302具体用于:
若调用所述第二方法的指令为动态调用invokedynamic指令,从引导方法中获取所述第二方法的方法信息;
基于所述第二方法的方法信息,增加所述第一调用关系。
在一些实施例中,若所述函数式编程场景包括匿名函数Lambda表达式子场景,所述第二方法为Lambda表达式,增加单元1302还用于:
从当前类的常量池中,基于常量动态调用信息
CONSTANT_InvokeDynamic_info对象获取引导方法;
基于引导参数bootstrap_arguments数组,从所述引导方法中获取所述第二方法的参数;
基于类索引class_index属性值,从所述引导方法中获取所述第二方法对应的类名;
基于名称索引name_index属性值,从所述引导方法中获取所述第二方法对应的方法名称;
基于所述参数、所述类名以及所述方法名称确定所述第二方法的方法信息。
需要说明的是,本申请实施例提供的数据处理装置包括所包括的各单元,可以通过电子设备中的处理器来实现;当然也可通过具体的逻辑电路实现;在实施的过程中,处理器可以为中央处理器(CPU,Central Processing Unit)、微处理器(MPU,Micro ProcessorUnit)、数字信号处理器(DSP,Digital Signal Processor)或现场可编程门阵列(FPGA,Field-Programmable Gate Array)等。
以上装置实施例的描述,与上述方法实施例的描述是类似的,具有同方法实施例相似的有益效果。对于本申请装置实施例中未披露的技术细节,请参照本申请方法实施例的描述而理解。
需要说明的是,本申请实施例中,如果以软件功能模块的形式实现上述的数据处理方法,并作为独立的产品销售或使用时,也可以存储在一个计算机可读取存储介质中。基于这样的理解,本申请实施例的技术方案本质上或者说对相关技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机、服务器、或者网络设备等)执行本申请各个实施例所述方法的全部或部分。而前述的存储介质包括:U盘、移动硬盘、只读存储器(Read OnlyMemory,ROM)、磁碟或者光盘等各种可以存储程序代码的介质。这样,本申请实施例不限制于任何特定的硬件和软件结合。
为实现上述数据处理方法,本申请实施例提供一种电子设备,包括存储器和处理器,所述存储器存储有可在处理器上运行的计算机程序,所述处理器执行所述程序时实现上述实施例中提供的数据处理方法中的步骤。
下面结合图14所示的电子设备140,对电子设备的结构图进行说明。
在一示例中,电子设备140可以为上述电子设备。如图14所示,所述电子设备140包括:一个处理器1401、至少一个通信总线1402、用户接口1403、至少一个外部通信接口1404和存储器1405。其中,通信总线1402配置为实现这些组件之间的连接通信。其中,用户接口1403可以包括显示屏,外部通信接口1404可以包括标准的有线接口和无线接口。
存储器1405配置为存储由处理器1401可执行的指令和应用,还可以缓存待处理器1401以及电子设备中各模块待处理或已经处理的数据(例如,图像数据、音频数据、语音通信数据和视频通信数据),可以通过闪存(FLASH)或随机访问存储器(Random AccessMemory,RAM)实现。
第四方面,本申请实施例提供一种存储介质,也就是计算机可读存储介质,其上存储有计算机程序,该计算机程序被处理器执行时实现上述实施例中提供的数据处理方法中的步骤。
这里需要指出的是:以上存储介质和设备实施例的描述,与上述方法实施例的描述是类似的,具有同方法实施例相似的有益效果。对于本申请存储介质和设备实施例中未披露的技术细节,请参照本申请方法实施例的描述而理解。
应理解,说明书通篇中提到的“一个实施例”或“一实施例”意味着与实施例有关的特定特征、结构或特性包括在本申请的至少一个实施例中。因此,在整个说明书各处出现的“在一个实施例中”或“在一些实施例中”未必一定指相同的实施例。此外,这些特定的特征、结构或特性可以任意适合的方式结合在一个或多个实施例中。应理解,在本申请的各种实施例中,上述各过程的序号的大小并不意味着执行顺序的先后,各过程的执行顺序应以其功能和内在逻辑确定,而不应对本申请实施例的实施过程构成任何限定。上述本申请实施例序号仅仅为了描述,不代表实施例的优劣。
需要说明的是,在本文中,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、物品或者装置不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、物品或者装置所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括该要素的过程、方法、物品或者装置中还存在另外的相同要素。
在本申请所提供的几个实施例中,应该理解到,所揭露的设备和方法,可以通过其它的方式实现。以上所描述的设备实施例仅仅是示意性的,例如,所述单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,如:多个单元或组件可以结合,或可以集成到另一个系统,或一些特征可以忽略,或不执行。另外,所显示或讨论的各组成部分相互之间的耦合、或直接耦合、或通信连接可以是通过一些接口,设备或单元的间接耦合或通信连接,可以是电性的、机械的或其它形式的。
上述作为分离部件说明的单元可以是、或也可以不是物理上分开的,作为单元显示的部件可以是、或也可以不是物理单元;既可以位于一个地方,也可以分布到多个网络单元上;可以根据实际的需要选择其中的部分或全部单元来实现本实施例方案的目的。
另外,在本申请各实施例中的各功能单元可以全部集成在一个处理单元中,也可以是各单元分别单独作为一个单元,也可以两个或两个以上单元集成在一个单元中;上述集成的单元既可以采用硬件的形式实现,也可以采用硬件加软件功能单元的形式实现。
本领域普通技术人员可以理解:实现上述方法实施例的全部或部分步骤可以通过程序指令相关的硬件来完成,前述的程序可以存储于计算机可读取存储介质中,该程序在执行时,执行包括上述方法实施例的步骤;而前述的存储介质包括:移动存储设备、只读存储器(Read Only Memory,ROM)、磁碟或者光盘等各种可以存储程序代码的介质。
或者,本申请上述集成的单元如果以软件功能模块的形式实现并作为独立的产品销售或使用时,也可以存储在一个计算机可读取存储介质中。基于这样的理解,本申请实施例的技术方案本质上或者说对相关技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机、服务器、或者网络设备等)执行本申请各个实施例所述方法的全部或部分。而前述的存储介质包括:移动存储设备、ROM、磁碟或者光盘等各种可以存储程序代码的介质。
以上所述,仅为本申请的实施方式,但本申请的保护范围并不局限于此,任何熟悉本技术领域的技术人员在本申请揭露的技术范围内,可轻易想到变化或替换,都应涵盖在本申请的保护范围之内。因此,本申请的保护范围应以所述权利要求的保护范围为准。

Claims (10)

1.一种数据处理方法,其特征在于,所述方法应用于Java虚拟机JVM,所述方法包括:
针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;
增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;
输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。
2.根据权利要求1所述的方法,其特征在于,在所述增加所述第一方法调用第二方法的第一调用关系之前,所述方法还包括:
获得所述第一方法对应的类的第一取值;所述第一取值用于表征是否已增加所述第一调用关系;
确定所述第一取值表征未增加所述第一调用关系。
3.根据权利要求1所述的方法,其特征在于,若所述第一场景包括线程调用场景,所述增加所述第一方法调用第二方法的第一调用关系,包括:
在所述第一方法为构造函数的情况下,增加所述第一调用关系为所述构造函数调用所述第二方法的第一子调用关系;
在所述第一方法为开始start函数,且所述start函数的参数为空的情况下,增加所述第一调用关系为所述start函数调用运行run方法的第二子调用关系。
4.根据权利要求3所述的方法,其特征在于,
在所述第一方法对应的类包括可运行Runnable接口实现类的情况下,所述第二方法包括run方法;对应的,所述第一子调用关系用于表征所述构造函数调用所述run方法;
在所述第一方法对应的类包括可调用Callable接口实现类的情况下,所述第二方法包括调用call方法;对应的,所述第一子调用关系用于表征所述构造函数调用所述call方法。
5.根据权利要求1所述的方法,其特征在于,在所述增加所述第一方法调用第二方法的第一调用关系之前,所述方法还包括:
增加Runnable接口实现类记录、Callable接口实现类记录以及线程Thread子类记录;
若所述第一方法对应的类包括Runnable接口实现类,在所述Runnable接口实现类记录中,记录所述第一方法对应的类的第一取值为第一数值;所述第一数值用于表征在所述Runnable接口实现类记录中未增加所述第一调用关系;
若所述第一方法对应的类包括Callable接口实现类,在所述Callable接口实现类记录中,记录所述第一方法对应的类的第一取值为第二数值;所述第二数值用于表征在所述Callable接口实现类记录中未增加所述第一调用关系;
若所述第一方法对应的类包括线程Thread子类,在所述Thread子类记录中,记录所述第一方法对应的类的第一取值为第三数值;所述第三数值用于表征在所述Thread子类记录中未增加所述第一调用关系。
6.根据权利要求1所述的方法,其特征在于,若所述第一场景包括函数式编程场景,所述增加所述第一方法调用第二方法的第一调用关系,包括:
若调用所述第二方法的指令为动态调用invokedynamic指令,从引导方法中获取所述第二方法的方法信息;
基于所述第二方法的方法信息,增加所述第一调用关系。
7.根据权利要求6所述的方法,其特征在于,若所述函数式编程场景包括匿名函数Lambda表达式子场景,所述第二方法为Lambda表达式,所述从引导方法中获取所述第二方法的方法信息,包括:
从当前类的常量池中,基于常量动态调用信息CONSTANT_InvokeDynamic_info对象获取引导方法;
基于引导参数bootstrap_arguments数组,从所述引导方法中获取所述第二方法的参数;
基于类索引class_index属性值,从所述引导方法中获取所述第二方法对应的类名;
基于名称索引name_index属性值,从所述引导方法中获取所述第二方法对应的方法名称;
基于所述参数、所述类名以及所述方法名称确定所述第二方法的方法信息。
8.一种数据处理装置,其特征在于,所述装置部署于Java虚拟机JVM所属的电子设备,所述装置包括:
获得单元,用于针对第一场景,获得第一Java程序文件中的第一方法;所述第一场景包括:线程调用场景或者函数式编程场景;
增加单元,用于增加所述第一方法调用第二方法的第一调用关系;所述第一方法与所述第二方法不同;所述第一调用关系为针对所述第一场景所述第一Java程序文件中缺少的调用关系;
输出单元,用于输出所述第一调用关系,以使根据所述第一调用关系实现所述第一方法对所述第二方法的调用。
9.一种电子设备,包括存储器和处理器,所述存储器存储有可在处理器上运行的计算机程序,所述处理器执行所述程序时实现权利要求1至7任一项所述的数据处理方法。
10.一种存储介质,其上存储有计算机程序,其特征在于,该计算机程序被处理器执行时,实现权利要求1至7任一项所述的数据处理方法。
CN202210475876.6A 2022-04-29 2022-04-29 一种数据处理方法、装置、设备及存储介质 Pending CN114896023A (zh)

Priority Applications (1)

Application Number Priority Date Filing Date Title
CN202210475876.6A CN114896023A (zh) 2022-04-29 2022-04-29 一种数据处理方法、装置、设备及存储介质

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN202210475876.6A CN114896023A (zh) 2022-04-29 2022-04-29 一种数据处理方法、装置、设备及存储介质

Publications (1)

Publication Number Publication Date
CN114896023A true CN114896023A (zh) 2022-08-12

Family

ID=82719556

Family Applications (1)

Application Number Title Priority Date Filing Date
CN202210475876.6A Pending CN114896023A (zh) 2022-04-29 2022-04-29 一种数据处理方法、装置、设备及存储介质

Country Status (1)

Country Link
CN (1) CN114896023A (zh)

Similar Documents

Publication Publication Date Title
US11036614B1 (en) Data control-oriented smart contract static analysis method and system
JP3178151B2 (ja) オブジェクト指向言語のメッセージコンパイル装置
JP4130713B2 (ja) プログラム変換装置
US6980979B2 (en) Method and apparatus for customizing Java API implementations
JP4165683B2 (ja) 複合データ構造の永続的表現の生成
JP4376181B2 (ja) プログラム実行処理端末装置
US20080229279A1 (en) Method for automatic generation of schema mapping application code
US6633892B1 (en) Archiving tool
US7076765B1 (en) System for hiding runtime environment dependent part
WO2022033229A1 (zh) 一种软件代码编译方法及系统
WO2024045382A1 (zh) 区块链中实现反射机制
US6151605A (en) Generic configuration file processing library and executable
US6996813B1 (en) Frameworks for loading and execution of object-based programs
CN111324395B (zh) 调用方法、装置和计算机可读存储介质
KR20120037152A (ko) 사용자 목적 기반 시맨틱 웹 서비스 검색을 통한 서비스 플로우 생성을 위한 방법 및 장치
US7770160B2 (en) System and method for declaring a resource within a markup document
CN114896023A (zh) 一种数据处理方法、装置、设备及存储介质
CN107239484A (zh) 数据库操作方法、装置和计算机设备
JP5399601B2 (ja) 実装コード開発システム、及び実装コード開発プログラム
JP2000122876A (ja) 情報処理装置
JPH07182179A (ja) オブジェクト指向データベース管理装置
Chang et al. Research friendly MPEG-7 software testbed
CN114020278A (zh) 数据处理方法、装置、设备及存储介质
US6978456B1 (en) Methods and apparatus for numeric constant value inlining in virtual machines
CN117971350A (zh) 小程序运行方法、装置和计算机可读存储介质

Legal Events

Date Code Title Description
PB01 Publication
PB01 Publication
SE01 Entry into force of request for substantive examination
SE01 Entry into force of request for substantive examination