类加载方法和装置与流程

文档序号:29160402发布日期:2022-03-09 00:01阅读:76来源:国知局
1.本技术涉及计算机
技术领域
:,尤其涉及类加载方法和装置。
背景技术
::2.在java虚拟机(javavirtualmachine,jvm)框架下,java虚拟机将磁盘中描述类数据的字节码.class文件加载到内存,并对这些数据进行校正、转换解析和初始化,最终形成可以被java虚拟机直接使用的java类型,这就是标准jvm的类加载机制。3.从安卓5.0(android5.0)开始谷歌(google)开放了art运行模式。基于art运行模式,系统服务(systemserver)进程和每个应用都运行在独立的art实例上。在系统服务进程或应用运行时,如果需要加载某个类(class)的类信息(classinfo),则首先根据该类的类名查找到类定义(classdefinition),然后动态分配内存,加载类数据,通过动态链接填充类的属性、方法等信息。其中,类数据是用于描述类的信息,如类所包含的方法的数量等。类信息包括:类的属性、方法等。4.上述技术方案,通常先根据待加载类的类名查找待加载类的类定义,再动态加载待加载类的数据和其他信息。这样,会导致类加载所需要的时间较长。技术实现要素:5.本技术实施例提供了类加载方法和装置,有助于更快地进行类加载,从而缩短类加载所需的时长。6.第一方面,本技术实施例提供了一种类加载方法,应用于计算机设备,计算机设备包括目标二进制文件,目标二进制文件包括多个类的类名与该多个类的类信息之间的对应关系,类名与类的类信息一一对应。目标二进制文件例如可以是dex文件、oat文件或共享动态库(sharedobject,so)文件等。该方法包括:首先,确定运行计算机设备中的应用程序时所需的待加载类的类名;该应用程序例如可以是计算机设备中安装的系统服务进程或任意一个应用。待加载类可以是运行该应用程序所需的任意一个方法所属的类。运行一个应用程序时,例如可以是该应用程序的启动阶段的某一时刻,或者是该应用程序的运行阶段的某一时刻。然后,根据该多个类的类名与该多个类的类信息之间的对应关系,在该多个类的类名中查找待加载类的类名,并获取待加载类的类名对应的类信息;其中,该多个类包括第一类,第一类可以是该多个类中的任意一个类。第一类的类信息是指运行第一类所需的类信息,例如,运行第一类所需的类信息可以包括第一类的类名、类定义、类的属性、方法等。后续,可以根据待加载类的类名对应的类信息,运行该应用程序。7.可见,本技术实施例提供的技术方案中加载类的过程实质上是查找类名,从而获取该类名对应的类信息的过程。相比现有技术“先根据类名查找类定义,再动态加载类的数据和其他信息”的技术方案,本技术实施例提供的技术方案中,可以直接根据类名查找到类的类信息,因此,有助于更快地进行类加载,从而缩短类加载所需的时长。8.在一种可能的设计中,目标二进制文件还包括:该多个类的类地址,以及该多个类的类地址与该多个类的类名的哈希值之间的对应关系;一个类的类地址所指示的存储空间用于存储该类的类信息。其中,类地址可以是在静态编译阶段生成的。例如,当目标二进制文件是so文件时,类地址可以是在静态编译阶段中,且由dex文件生成so文件的过程中所生成的。相应的,该方法还包括:根据该多个类的类地址与该多个类的类名的哈希值之间的对应关系,在该多个类的类名的哈希值中查找目标哈希值,并获取目标哈希值对应的类地址;其中,目标哈希值是待加载类的类名的哈希值。基于此,根据该多个类的类名与该多个类的类信息之间的对应关系,在该多个类的类名中查找待加载类的类名,并获取所述待加载类的类名对应的类信息,可以包括:在目标哈希值对应的类地址所指示的存储空间中,查找待加载类的类名,其中,待加载类的类名是待加载类的类信息的一部分;以及目标哈希值对应的类地址所指示的存储空间中的类信息为待加载类的类信息。9.可见,本技术实施例支持通过寻址的方式查找待加载类的类名,这样,有助于快速从多个类的类名中查找到待加载类的类名。10.在一种可能的设计中,一个哈希值对应一个桶(即哈希桶),一个桶包括零个、一个或多个类地址。相应的,根据该多个类的类地址与该多个类的类名的哈希值之间的对应关系,在该多个类的类名的哈希值中查找目标哈希值,并获取目标哈希值对应的类地址,可以包括:根据多个桶与该多个类的类名的哈希值之间的对应关系,在该多个类的类名的哈希值中查找目标哈希值,并获取目标哈希值对应的桶,将目标哈希值对应的桶所包括的类地址作为目标哈希值对应的类地址。可见,本技术实施例支持使用哈希桶的方式,这样有助于减少冲突率。11.具体实现的过程中,在一种实现方式中,在静态编译阶段,确定桶的数量;可选的,在静态编译阶段确定每个桶所包括的类地址(即桶与类地址之间的对应关系)。换言之,本技术实施例支持静态确定桶的数量和每个桶所包括的类地址。在另一种实现方式中,在应用程序开启阶段或运行阶段,确定桶的数量;可选的,在应用程序开启阶段或运行阶段,确定每个桶所包括的类地址。换言之,本技术实施例支持动态确定桶的数量和每个桶所包括的类地址。12.在一种可能的设计中,一个桶具有一个首地址和一个尾地址,该多个桶包括第一桶,第一桶可以是该多个桶中的任意一个桶。第一桶的首地址和尾地址所限定的存储空间用于存储第一桶包括的类地址。相应的,在将目标哈希值对应的桶所包括的类地址作为目标哈希值对应的类地址之前,该方法还可以包括:从该多个桶的首地址和尾地址中,查找目标哈希值对应的桶的首地址和尾地址;从目标哈希值对应的桶的首地址至尾地址所限定的存储空间中,读取目标哈希值对应的桶所包括的类地址。该可能的设计提供了一种确定类地址的实现方式。当然具体实现时不限于此。13.在一种可能的设计中,在确定运行计算机设备中的应用程序时所需的待加载类的类名之前,该方法还包括:将运行该应用程序所需的二进制文件(即二进制文件)从计算机设备的外存中加载到计算机设备的内存中;其中,计算机设备的外存例如可以是硬盘、磁盘等。计算机设备的外存可以用于存储静态编译阶段所生成的二进制文件。该全量二进制文件包括目标二进制文件。例如,当目标二进制文件是so文件时,这里的运行该应用程序所需的二进制文件可以是运行该应用程序所需的so文件。又如,当目标二进制文件是dex文件时,这里的运行该应用程序所需的二进制文件可以是运行该应用程序所需的dex文件。可选的,该过程可以发生在应用程序启动阶段。基于该可能的设计,在类加载时,计算机设备(具体是计算机设备的cpu)可以从内存中的全量二进制文件中,查找待加载类的类信息,这样可以更快地进行类加载,从而缩短类加载所需的时长。14.在一种可能的设计中,该方法还包括:创建该应用程序的至少两个类加载器;建立该至少两个类加载器与该全量二进制文件之间的对应关系;例如,一个类加载器可以与一个或多个二进制文件之间对应,该至少两个类加载器包括第一类加载器,第一类加载器可以是该至少两个类加载器中的任意一个类加载器。第一类加载器用于在与第一类加载器对应的二进制文件中查找待加载类的类信息。可选的,该过程可以发生在应用程序启动阶段或应用程序运行阶段。基于该可能的设计,在类加载时,计算机设备可以基于类加载器,在相应的二进制文件中查找待加载类的类信息。15.在一种可能的设计中,该方法还包括:根据双亲委派机制,在该至少两个类加载器中确定当前执行查找操作的类加载器,以通过所确定的当前执行查找操作的类加载器,在该全量二进制文件中查找所述待加载类的类信息。16.在一种可能的设计中,类加载器与二进制文件存在对应关系,包括:该类加载器与该二进制文件的路径存在对应关系,其中,二进制文件的路径可以认为是二进制文件的标识信息的一种具体实现。相应的,该方法还包括:根据该至少两个类加载器与该全量二进制文件的路径之间的对应关系,在该全量二进制文件的路径中查找目标栈帧所在的二进制文件的路径,并获取目标栈帧所在的二进制文件的路径对应的类加载器,将所确定的类加载器作为双亲委派机制中所采用的初始类加载器;目标栈帧是调用待加载方法的栈帧,待加载方法所属待加载类。可见,本技术实施例支持调用待加载方法的目标栈帧所在的二进制文件的路径对应的类加载器,确定双亲委派机制中所采用的初始类加载器的技术方案。17.在一种可能的设计中,该方法还包括:建立该至少两个类加载器与该全量二进制文件中的类之间的对应关系;其中,第一类加载器与第一类加载器对应的二进制文件所包含的类之间存在对应关系;将当前调用待加载类的类所对应的类加载器,作为双亲委派机制中所采用的初始类加载器。这样,有助于提升类加载性能。18.第二方面,本技术实施例提供了一种类加载装置,该装置包括用于执行第一方面或第一方面任一种可能的设计中的类加载方法的各个模块。该装置例如可以是计算机设备或芯片。19.第三方面,本技术实施例提供了一种类加载装置,该装置包括存储器和处理器,存储器用于用于存储计算机执行指令,该装置运行时,该处理器执行该存储器中的计算机执行指令以利用该装置中的硬件资源执行第一方面或第一方面任一种可能的设计中的方法的操作步骤。该装置例如可以是计算机设备或芯片。20.第四方面,本技术实施例提供了一种计算机可读存储介质,其上储存有计算机程序,当该计算机程序在计算机上运行时,使得计算机执行上述第一方面或第一方面的任一种可能的设计中任一种可能的方法的操作步骤。21.第五方面,本技术实施例提供了一种计算机程序产品,当其在计算机上运行时,使得上述第一方面或第一方面的任一种可能的设计中任一种可能的方法的操作步骤被执行。22.可以理解的是,上述提供的任一种类加载装置或计算机可读存储介质或计算机程序产品等均用于执行上文所提供的对应的方法,因此,其所能达到的有益效果可参考对应的方法中的有益效果,此处不再赘述。附图说明23.图1为可适用于本技术实施例的一种计算机设备的硬件结构示意图;24.图2为可适用于本技术实施例的一种另一种计算机设备的硬件结构示意图;25.图3为本技术实施例提供的一种建立哈希表的方法的示意图;26.图4为本技术实施例提供的一种基于类名生成的哈希表的示意图;27.图5为本技术实施例提供的一种应用程序启动阶段计算机设备所执行的步骤的示意图;28.图6为本技术实施例提供的一种应用程序运行阶段计算机设备所执行的步骤的示意图;29.图7为本技术实施例提供的一种类加载器、so文件和类加载器域之间的对应关系的示意图;30.图8为本技术实施例提供的一种确定双亲委托机制所采用的初始类加载器的对比示意图;31.图9为本技术实施例提供的一种类加载方法的流程示意图;32.图10为本技术实施例提供的一种类加载装置的结构示意图。具体实施方式33.首先,对本技术实施例中所涉及的术语进行简单介绍,以方便读者理解:34.类:是一种抽象的数据类型,它是对所具有相同特征实体的抽象。本技术实施例中所描述类通常是指java类。在一个示例中,可以认为一个类是多个属性和方法的集合。35.类信息:一个类的类信息可以包括该类的类名、类定义、类的属性、方法等。36.类的全量信息:是指执行该类所需的全部信息。例如,类的全量信息包括该类的所有类信息如类名、类定义、类的属性、方法以及属性和方法的对外可见性等。37.作为一个示例,类的全量信息可以包括如表1所示的各种信息:38.表139.40.应当理解的是,表1所示的各种信息仅为类的全量信息的一个示例,实际实现时,一个类的全量信息可以包括比表1所示的信息更多或更少的信息。41.类加载器(classloader),是加载java类到虚拟机中的逻辑单元。42.二进制文件:广义的二进制文件是指文件,由文件在外部设备的存放形式为二进制而得名。狭义的二进制文件是除文本文件以外的文件。dex文件、oat文件或so文件都属于二进制文件。如果不加说明,下文中的二进制文件均是以so文件为例进行说明的。其中,dex文件是android虚拟机下的一种目标文件,包含应用程序的所有操作指令和运行时所需的数据。oat文件是dex文件经过静态(aheadoftime,aot)编译优化后的一种可执行文件。oat文件可以基于aot编译器的静态引导得到。so文件是一种可执行格式(executableandlinkingformat,elf)文件,也称为动态库文件或共享库文件。43.桶(bucket):也称为哈希桶,是哈希表内元素的虚拟子群组,同一个桶内的元素所对应的哈希值相同,不同桶内的元素所对应的哈希值不同。在本技术的一些实施例中,桶内的元素可以是类地址。44.本技术实施例中的术语“至少一个(种)”包括一个(种)或多个(种)。“多个(种)”是指两个(种)或两个(种)以上。例如,a、b和c中的至少一种,包括:单独存在a、单独存在b、同时存在a和b、同时存在a和c、同时存在b和c,以及同时存在a、b和c。在本技术的描述中,除非另有说明,“/”表示或的意思,例如,a/b可以表示a或b;本文中的“和/或”仅仅是一种描述关联对象的关联关系,表示可以存在三种关系,例如,a和/或b,可以表示:单独存在a,同时存在a和b,单独存在b这三种情况。“多个”是指两个或多于两个。另外,为了便于清楚描述本技术实施例的技术方案,在本技术的实施例中,采用了“第一”、“第二”等字样对功能和作用基本相同的相同项或相似项进行区分。本领域技术人员可以理解“第一”、“第二”等字样并不对数量和执行次序进行限定,并且“第一”、“第二”等字样也并不限定一定不同。45.如图1所示,为可适用于本技术实施例的一种计算机设备100的硬件结构示意图。图1所示的计算机设备100包括:至少一个处理器101、通信线路102、存储器103以及至少一个通信接口104。其中:46.处理器101可以是一个通用中央处理器(centralprocessingunit,cpu),微处理器,特定应用集成电路(application-specificintegratedcircuit,asic),或一个或多个用于控制本技术方案程序执行的集成电路。47.通信线路102可以包括一通路,在上述组件之间传送信息。48.通信接口104可以是任何收发器一类的装置,用于与其他设备或通信网络通信,如以太网,无线接入网(radioaccessnetwork,ran),无线局域网(wirelesslocalareanetworks,wlan)等。49.存储器103可以是只读存储器(read-onlymemory,rom)或可存储静态信息和指令的其他类型的静态存储设备,随机存取存储器(randomaccessmemory,ram)或者可存储信息和指令的其他类型的动态存储设备,也可以是电可擦可编程只读存储器(electricallyerasableprogrammableread-onlymemory,eeprom)、只读光盘(compactdiscread-onlymemory,cd-rom)或其他光盘存储、光碟存储(包括压缩光碟、激光碟、光碟、数字通用光碟、蓝光光碟等)、磁盘存储介质或者其他磁存储设备、或者能够用于携带或存储具有指令或数据结构形式的期望的程序代码并能够由计算机存取的任何其他介质,但不限于此。50.存储器103可以是独立存在,通过通信线路102与处理器101相连接。或者,存储器103可以和处理器101集成在一起。本技术实施例提供的存储器103通常可以具有非易失性。其中,存储器103用于存储执行本技术方案的计算机指令,并由处理器101来控制执行。处理器101用于执行存储器103中存储的计算机指令,从而实现本技术实施例提供的方法。51.本技术实施例不限定计算机设备100的类型,例如,计算机设备100可以是包含图1所示的硬件结构的通用的设备,也可以是包含图1所示的硬件结构的专用设备。52.可选的,本技术实施例中的计算机指令也可以称之为应用程序代码,本技术实施例对此不作具体限定。53.在具体实现中,作为一种实施例,计算机设备100可以包括多个处理器。这些处理器中的每一个可以是一个单核(single-cpu)处理器,也可以是一个多核(multi-cpu)处理器。这里的处理器可以指一个或多个设备、电路、和/或用于处理数据(例如计算机程序指令)的处理核。54.在具体实现中,作为一种实施例,计算机设备100还可以包括输出设备105和输入设备106。输出设备105和处理器101通信,可以以多种方式来显示信息。例如,输出设备105可以是液晶显示器(liquidcrystaldisplay,lcd),发光二级管(lightemittingdiode,led)显示设备,阴极射线管(cathoderaytube,crt)显示设备,或投影仪(projector)等。输入设备106和处理器101通信,可以以多种方式接收用户的输入。例如,输入设备106可以是鼠标、键盘、触摸屏设备或传感设备等。55.在具体实现中,作为一种实施例,如图2所示,存储器103可以包括主存储器1031和辅存储器1032。处理器101可以包括主处理器1011和辅处理器1012。其中:56.主存储器1031可以是内存(memory)。57.辅存储器1032可以是外存,也可以称为外存设备,例如可以是硬盘、光驱、软盘、磁盘等。辅存储器1032可以存储静态编译阶段编译得到的二进制文件(如so文件等)等。58.主处理器1011可以是cpu。主处理器1011不能直接访问辅存储器1032(如外存),只能访问主存储器1031(如内存)。59.辅处理器1012可以是直接内存存取(directmemoryaccess,dma)处理器等可以从辅存储器1032(如外存)中读取数据至主存储器1031(如内存)中的处理器。60.以主处理器1011是cpu、辅处理器1012是dma处理器、主存储器1031是内存、且辅存储器1032是外存为例,数据由外存到内存再到cpu的过程可以包括:内存向cpu发出读取外设指令,cpu将系统总线控制权限交给dma处理器;dma处理器将数据从外存读入内存;cpu从dma处理器接管总线控制权;cpu向内存发出读取数据命令;cpu对数据进行运算处理,同时和内存进行必要的数据交换;处理结束后,如果有外存读取操作,cpu可以将结果数据发送到外存。61.在一个示例中,计算机设备100运行应用程序(包括系统服务进程或应用等)的过程可以理解为是cpu调用方法的过程。所调用的方法属于一个类。在一个示例中,调用方法,可以理解为是调用函数。因此,可以由dma处理器先将外存中存储的待加载方法所属的类的类信息加载到内存中,并由cpu读取内存中的数据,以执行该待加载方法。62.以下,结合附图,说明本技术实施例提供的技术方案进行说明。为了清楚说明本技术实施例提供的技术方案,以下通过静态编译阶段、应用程序启动阶段和应用程序运行阶段进行说明。其中,本技术提供的类加载方法可以包含在应用程序运行阶段和/或应用程序启动阶段,因此,下文不再对类加载方法进行单独说明。63.静态编译阶段64.在静态编译阶段,静态编译器工具链编译动态库,即将dex文件编译成so文件。其中,本技术实施例对将dex文件编译成so文件的具体实现方式不进行限定,例如可以参考现有技术。需要说明的是,应用于本技术实施例时,在将dex文件编译成so文件的过程中,静态编译器工具链可以基于该dex文件中的类的类名生成哈希表,该哈希表是so文件的一部分。65.具体的:对于任意一个待编译dex文件来说,静态编译器工具链可以对待编译dex文件中的所有类的类名分别进行哈希运算,得到每个类名的哈希值,并建立哈希表。66.其中,本技术实施例对执行哈希运算时所采用的哈希算法不进行限定,例如可以是bkdr哈希算法等,其中,bkdr哈希算法来自于kernighananddennisritchie合著的c语言编程一书,是2个人名合起来的简写。采用bkdr哈希算法进行哈希运算的一个示例如下:[0067][0068]可选的,如图3所示,建立哈希表的过程可以包括以下步骤:[0069]s101:静态编译器工具链生成待编译dex文件中每个类的类地址。每个类的类地址所指示的存储空间中用于存放该类的类信息。其中,一个dex文件可以包括一个或多个类。[0070]在本技术的一些实施例中,每个类对应一个类地址。类地址可以是虚拟地址(即逻辑地址)或物理地址。本技术实施例对此不进行具体限定。[0071]s102:静态编译器工具链建立待编译dex文件中每个类的类地址与该类的类名的哈希值之间的对应关系。基于此,后续可以通过寻址的方式,查找待加载类的类信息。[0072]可选的,s102可以包括以下步骤s102-1~s102-3:[0073]s102-1:静态编译器工具链通过哈希值将待编译dex文件中所有类的类地址分布到不同的桶中。每个桶包括具有相同哈希值的类地址,不同桶包括具有不同哈希值的类地址。一个类地址具有的哈希值,是指该类地址表示的存储空间中存放的类信息包括的类名的哈希值。[0074]也就是说,静态编译器工具链通过建立类地址与该类地址所属的桶之间的对应关系,和桶与哈希值之间的对应关系,来建立每个类的类地址与该类的类名的哈希值之间的对应关系。[0075]作为一个示例,静态编译器工具链可以采用固定数量的桶,并根据桶所对应的哈希值大小从低到高连续存放所有桶。为了便于描述,下文中均以此为例进行说明。[0076]作为一个示例,对于多个桶来说,静态编译器工具链可以按照桶所对应的哈希值大小从低到高对桶进行编号。为了便于描述,下文中均以此为例进行说明。[0077]s102-2:静态编译器工具链为每个桶分配一个首地址和一个尾地址,其中,每个桶所包括的类地址存放在该桶的首地址和尾地址所限定的存储空间中。[0078]例如,假设对从0开始各桶分别进行连续编号,那么对于桶m(即编号为m的桶)来说:如果m=0,则桶0的首地址是各桶的首地址,桶0的尾地址是基于桶0所包含的类地址的数量确定的;如果m>0,则桶m的首地址是基于桶m-1的尾地址确定的,桶m的尾地址是基于桶m所包含的类地址的数量确定的。0≤m≤m-1,m是桶的数量,m和m均是整数。[0079]为了方便描述,本技术实施例中,是以每个桶中连续存放其所包含的类地址为例进行说明的。也就是说,如果一个桶中包括a个类地址,则该桶的尾地址与首地址之差为a,a是大于或等于0的整数。当然本技术实施例不限于此。[0080]s102-3:静态编译器工具链创建对待编译dex文件进行编译后得到的so文件的第一字段(section)和第二字段。其中,第一字段用于存放该so文件包括的所有桶的首地址。第二字段用于存放该so文件包括的所有桶的尾地址。[0081]作为一个示例,第一字段中所存放的首地址所属的桶的编号由低到高连续排列,第二字段中所存放的尾地址所属的桶的编号由低到高连续排列。[0082]每个so文件本质上都是一个elf文件,包含elf头(header)和多个字段,其中每个so文件中包含一个哈希表,例如,如图4所示的哈希表。[0083]如图4所示,为本技术实施例提供的一种基于类名生成的哈希表的示意图。图4所示的哈希表是一个so文件中的哈希表。其中,①表示so文件的第一字段。②表示so文件的第二字段。③表示桶0,④表示桶1;且桶m对应哈希值m。若桶0包括11个类地址,桶1包括10个类地址,则桶0的首地址“__class_hashtab_bucket_0_start__”可以是地址0,尾地址“__class_hashtab_bucket_0_end__”可以是地址10;相应的,桶1首地址“__class_hashtab_bucket_1_start__”可以是地址11,尾地址“__class_hashtab_bucket_1_end__”可以是地址21。⑤表示桶0中的第一个类地址所指示的存储空间中存储的类的类信息,具体包括:类名(如“__classinfo__ljava_2flang_2fstring_24caseinsensitivecomparator_3b”)和其他信息。结合图4,可以认为:本技术实施例所描述的哈希表包含一个so文件中的每个类和该类的组织关系。[0084]需要说明的是,在一些实施例中,在静态编译阶段,确定桶的数量,如根据so中所包含的类的数量确定桶的数量。在另一些实施例中,在应用程序启动阶段或应用程序运行阶段,确定桶的数量、桶与类地址之间的对应关系等。例如,所包含的类的数量较多的so文件,所对应的桶的数量相对较多。这样,对于所包含的类数量较大的so文件,有助于减少冲突率。其中,同一桶中所包含的类的数量越多,则冲突率越高。[0085]可以理解的是,静态编译阶段所编译获得的so文件通常会存储在计算机设备的外存中。[0086]应用程序启动阶段[0087]作为一个示例,如图5所示,在应用程序启动阶段,计算机设备可以执行如下步骤:[0088]s201:在计算机设备中安装的应用程序启动时,将外存中的运行该应用程序所需的so文件加载到内存中。例如,结合图2,计算机设备中的dma处理器通过一次或多次加载,将外存中存储的运行该应用程序所需的全量so文件(即全部的so文件)加载到内存中。[0089]其中,应用程序可以包括系统服务进程或应用(application,app)等。[0090]s202:计算机设备创建该应用程序的至少一个类加载器,例如通常建立多个类加载器。[0091]作为一个示例,结合图2,s202的执行主体具体可以是计算机设备中的cpu。[0092]其中,针对一个应用程序创建类加载器的具体实现方式可以参考现有技术(如现有基于art运行模式的技术等)。可选的,如果针对该应用程序创建了多个类加载器,则计算机设备还可以创建该多个类加载器之间的父子关系,其具体实现过程可以参考现有技术(如现有基于art运行模式的技术等)。[0093]s203:计算机设备建立该至少一个类加载器与该so文件之间的对应关系。其中,一个类加载器与一个或多个so文件存在对应关系,一个so文件仅与一个类加载器存在对应关系;一个类加载器用于在与自身存在对应关系的so文件中查找待加载类的类信息。[0094]计算机设备建立的该应用程序的至少一个类加载器与运行该应用程序所需的so文件之间的对应关系的具体实现方式,可以参考现有技术(如现有基于art运行模式的技术等)中的建立该应用程序的至少一个类加载器与运行该应用程序所需的全量dex文件之间的对应关系。具体的,如果该至少一个类加载器中的类加载器i与该全量dex文件中的dex文件j之间对应,则类加载器i与so文件j之间对应。其中,so文件j是在静态编译期对dex文件j进行编译得到so文件。1≤i≤i,1≤j≤j,i是计算机设备所创建的该应用程序的类加载器的数量,j是计算机设备运行该应用程序所需的so文件(或dex文件)的数量。i、j、i和j均是整数,i<j。[0095]s204:对于该至少一个类加载器中的任意一个类加载器来说,计算机设备通过系统调用方法打开与该类加载器对应的所有so文件,并获得每个so文件的第一字段(如图4中的__class_hashtab_start__)和第二字段(如图4中的__class_hashtabend_start__),并初始化每个so文件中的所有类的类加载器域。该步骤是为该应用程序运行时执行类加载做准备。[0096]在一个示例中,如图7所示,计算机设备所创建的每个类加载器的序号可以保存在类加载器列表①中,序号从0开始,类加载器之间可能存在父子关系,如图示中④中表示类加载器0的父亲是类加载器1。图7中是以类加载器0对应3个so文件,如图中②表示的so文件1、so文件2和so文件3为例进行说明的。每个so文件可以包含elf头和哈希表,其中,图7中的“.class_hashtab”表示哈希表。[0097]每个类的类信息还可以包括类加载器域,如图7中的③所示。一个类的类加载器域中的信息可以用于表示该类所属的类加载器在类加载器列表①中的序号,如图7中so文件2中的所有类的类加载器域中均被设置成clindex=0(即类加载器的索引或编号为0)。其中,一个类所属的类加载器是该类所属的so文件所对应的类加载器。[0098]上述s201~s204可以认为是执行类加载方法的准备阶段,基于此,后续所执行的类加载方法,具体为在内存中查询类的方法。这样,可以提高查找(或类加载)效率,从而缩短查找(或类加载)时间。需要说明的是,类加载方法可以在应用程序启动阶段和/或运行阶段执行,下文中均是以在应用程序运行阶段为例进行说明的。[0099]应用程序运行阶段[0100]作为一个示例,如图6所示,在应用程序运行阶段,计算机设备可以执行如下步骤:[0101]s301:计算机设备确定当前需要调用的方法(即待加载方法),并将该方法所属的类作为待加载类。[0102]s302:计算机设备根据哈希算法,对待加载类的类名进行哈希运算,得到目标哈希值。[0103]其中,s302中所采用的哈希算法与上述静态编译阶段所采用的哈希算法相同。[0104]s303:计算机设备在该应用程序的至少一个类加载器中确定待加载类的初始类加载器。[0105]在一些实施例中,初始类加载器可以是显式指示的,如由用户指示给计算机设备的。[0106]在另一些实施例中,在没有显式指示初始类加载器的情况下,本技术实施例提供了以下实现方式:[0107]方式1:计算机设备根据该至少一个类加载器与该so文件之间的对应关系,确定待加载方法的调用栈的目标栈帧所在的so文件所对应的类加载器,并将所确定的类加载器作为待加载类的初始类加载器。其目标栈帧是调用(如直接或间接调用)待加载方法的栈帧。[0108]例如,如果运行应用程序的过程中,需要调用方法a;在执行方法a的过程中,需要调用方法b;在调用方法b的过程中,需要调用方法c。那么,“方法a→方法b→方法c”即为一个调用栈,调用栈中的每个方法为该调用栈的一个栈帧。若待加载方法是方法c,那么,目标栈帧可以是直接调用方法c的栈帧即方法b,或者是间接调用方法c的栈帧即方法a。[0109]可以理解的是,在上述s203中已经建立了应用程序的至少一个类加载器与运行该应用程序所需的so文件之间的对应关系。具体实现时,so文件的路径可以作为so文件的标识信息,因此,在一种实现方式中,一个类加载器与一个so文件之间的对应关系,可以包括:该类加载器与该so文件的路径之间的对应关系。基于此,方式1可以描述为:计算机设备根据该至少一个类加载器与该so文件的路径之间的对应关系,确定目标栈帧所在的so文件的路径所对应的类加载器,并将所确定的类加载器作为初始类加载器。[0110]方式2:计算机设备将待加载类的调用者所对应的类加载器,作为待加载类的初始类加载器。待加载类的调用者是指当前调用待加载类的类。[0111]在上述s204中已经初始化了每个so文件中的所有类的类加载器域,也就是说,已经建立了该至少一个类加载器与该so文件中的类之间的对应关系;其中,一个类加载器与该加载器对应的so文件所包含的类之间存在对应关系。方式2提供的技术方案中,可以使用待加载类的调用者对应的类加载器域所指示的类加载器,作为待加载类的初始类加载器。[0112]需要说明的是,基于art运行模式的技术中,通常通过回栈(backstack)获取初始类加载,其中,回栈是获得当前待加载方法的调用栈中的某一栈。然而,回栈存在一定的时间开销,因此,本技术实施例中,直接使用待加载类的调用者所对应的类加载器作为初始类加载器,可以避免应用程序在运行时触发回栈所带来的时间开销。如果回栈触发频率越高,则使用方式2可以节省更多的cpu运行时间。[0113]以class.forname()为例,假设需要在类a中通过class.forname()方法来加载test类(如图8所示的①),且没有指定初始类加载器,则:基于art运行模式的技术中,是在应用程序运行时通过vmstack.getcallingclassloader()来获得初始类加载器(如图8所示的②)。的这个方法是通过回栈来实现的。本技术实施例中,在静态编译阶段就定义了每个类(包括类a)的类加载器域,如图8中所示的③中a.getclassloader(),并且,在执行类加载之前,初始化了每个类的类加载域,因此,可以在没有指定初始类加载器时,直接调用a.getclassloader(),即直接将特定类加载器域的初始值所指示的类加载器作为初始类加载器,该特定类加载器域是待加载类的调用者所对应的类加载器域。这比回栈的性能快很多。也就是说,通过图8中所示的②替换③,从而提升类加载性能。[0114]s304:计算机设备基于待加载类的初始类加载器,并根据双亲委派机制,在该至少一个类加载器中确定当前执行加载操作的类加载器,并在该so文件中查找待加载类的类名对应的待加载类的类信息。[0115]以应用于art运行模式为例,传统技术中的双亲委派机制包括:[0116]1)、当需要记载待加载类时,触发类加载请求。并确定是否加载过待加载类,如果加载过(即内存中存储有待加载类的类信息),则直接返回。[0117]2)、如果没有加载过,则根据如下规则“优先把类加载请求委托给初始类加载器的父类加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,类加载请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回。如果父类加载器无法完成加载任务,子加载器才会尝试自己去执行加载任务”确定当前执行加载操作的类加载器。[0118]基于上述s201可知,在本技术的一些实施例中,在应用程序启动时,会将运行该应用程序所需的so文件均加载到内存中。基于此,上述s304中,根据双亲委派机制,在该至少一个类加载器中确定当前执行加载操作的类加载器,可以包括:当需要记载待加载类时,触发类加载请求,并根据上述2)中的规则,在该至少一个类加载器中确定当前执行加载操作的类加载器。基于此,可以将s304作为变种的(或演进的或新的)双亲委派机制。[0119]s305:计算机设备根据所查找到的待加载类的类信息,运行应用程序。[0120]具体实现时,基于类加载器加载类,本质就是从该类加载器所管理的所有so文件中查找待加载类。其中,对于任意一个so文件来说,计算机设备可以基于该so文件所对应的类加载器,执行以下步骤,如图9所示,以查找待加载类的类信息:[0121]s401:根据多个哈希值与m个桶之间的对应关系,从该多个哈希值中查找目标哈希值,并获取目标哈希值对应的桶。例如,根据多个哈希值与m个桶的编号之间的对应关系,从该多个哈希值中查找目标哈希值,并获取目标哈希值对应的桶的编号。[0122]例如,假设目标哈希值是h,则目标哈希值对应的桶是m个桶中的第h+1个桶。[0123]s402:从m个桶的首地址和尾地址中,查找目标哈希值对应的桶的首地址和尾地址。[0124]基于s401中的示例,从该so文件的第一字段的第一个地址(即桶0的首地址)开始,将目标哈希值h作为偏移量,得到目标哈希值对应的桶的首地址。同理,从该so文件的第二字段的第一个地址(即桶0的尾地址)开始,将目标哈希值h作为偏移量,得到目标哈希值对应的桶的尾地址。[0125]s403:从目标哈希值对应的桶的首地址至尾地址所限定的存储空间中,读取目标哈希值对应的桶所包括的类地址,并将所读取的类地址作为目标哈希值对应的类地址。[0126]基于s402中的示例,假设目标哈希值h对应的桶是桶0,则根据图4中所示的⑨和⑦,即可确定目标哈希值对应的桶所包括的类地址。假设目标哈希值h对应的桶是桶1,则根据图4中所示的⑧和⑥,即可确定目标哈希值对应的桶所包括的类地址。[0127]s404:在目标哈希值对应的类地址所指示的存储空间中,查找待加载类的类名。其中,待加载类的类名是待加载类的类信息中的一部分。[0128]基于s403中的示例,假设目标哈希值h对应的桶是桶0,则根据图4中所示的⑩,可以确定目标哈希值对应的类地址所指示的存储空间。并判断该存储空间中存储的类名与待加载类的类名是否匹配,如果相同则认为匹配(即已查找到);否则,认为不匹配(即没有查找到)。[0129]s405:如果查找到,则将目标哈希值对应的类地址所指示的存储空间中存储的类的类信息,作为待加载类的类信息。[0130]可以理解的是,如果查找不到,说明该so文件中没有存储待加载类的类信息,则在该类加载器所对应的下一个so文件中查找待加载类的类信息。如果遍历完该类加载器对应的所有so文件之后,仍然查找不到待加载类的类信息,则根据双亲委派机制继续由下一个类加载器负责查找,直到查找到待加载类的类信息。如果遍历完该应用程序的所有类加载器之后,仍然查找不到待加载类的类信息,则计算机设备输出异常处理信息。[0131]本技术实施例提供的技术方案,与基于art运行模式的技术的主要区别在于,本技术实施例中在静态执行阶段建立的是类名与类的类信息之间的对应关系,而基于art运行模式的技术中建立的是类名与类定义之间的对应关系。基于此,可知,在进行类加载时,本技术实施例可以直接根据类名查找到该类名对应的类信息,而基于art运行模式的技术根据类名仅能查找到该类名对应的类定义,后续可以基于动态分配内存加载类数据,并通过动态链接填充类的属性、方法等信息,因此,相比基于art运行模式的技术,本技术实施例提供的技术方案能够更快地进行类加载。[0132]另外,在本技术的一些实施例中,在应用程序启动时,将运行该应用程序所需的so文件均加载到内存中,这样,在应用程序运行时,类加载实质上为在内存中进行类查找,这样,可以进一步提高类加载速率。尤其是相对基于art运行模式的技术下首次加载类信息时,本技术试试提供的技术方案,能够使系统和应用运行更快。[0133]另外,本技术实施例提供的技术方案填补了安卓操作系统中运用静态编译技术将dex文件转成so文件后进行类加载的空白,实现了一套兼容安卓操作系统正常运行的类加载机制。[0134]上述主要从方法的角度对本技术实施例提供的方案进行了介绍。为了实现上述功能,其包含了执行各个功能相应的硬件结构和/或软件模块。本领域技术人员应该很容易意识到,结合本文中所公开的实施例描述的各示例的单元及算法步骤,本技术能够以硬件或硬件和计算机软件的结合形式来实现。某个功能究竟以硬件还是计算机软件驱动硬件的方式来执行,取决于技术方案的特定应用和设计约束条件。专业技术人员可以对每个特定的应用来使用不同方法来实现所描述的功能,但是这种实现不应认为超出本技术的范围。[0135]本技术实施例可以根据上述方法示例对类加载装置进行功能模块的划分,例如,可以对应各个功能划分各个功能模块,也可以将两个或两个以上的功能集成在一个处理模块中。上述集成的模块既可以采用硬件的形式实现,也可以采用软件功能模块的形式实现。需要说明的是,本技术实施例中对模块的划分是示意性的,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式。[0136]如图10所示,为本技术实施例提供的一种类加载装置90的结构示意图。该装置90可以用于执行图6、图8或图9所示的方法。示例的,该装置90可以是上文中的计算机设备。[0137]该装置90可以包括目标二进制文件,目标二进制文件包括多个类的类名与所述多个类的类信息之间的对应关系,类名与类的类信息一一对应。该装置90包括:确定单元901、查找单元902和运行单元903。其中,确定单元901,用于确定运行该装置90中的应用程序时所需的待加载类的类名。查找单元902,用于根据该多个类的类名与该多个类的类信息之间的对应关系,在该多个类的类名中查找待加载类的类名,并获取待加载类的类名对应的类信息;该多个类包括第一类,第一类的类信息是指运行第一类所需的类信息。运行单元903,用于根据待加载类的类名对应的类信息,运行该应用程序。例如,结合图6,确定单元901具体可以用于执行s301,查找单元902具体可以用于执行s302~s304,运行单元903可以用于执行s305。[0138]可选的,目标二进制文件还包括:该多个类的类地址,以及该多个类的类地址与该多个类的类名的哈希值之间的对应关系;一个类的类地址所指示的存储空间用于存储一个类的类信息。相应的,查找单元902还用于,根据该多个类的类地址与该多个类的类名的哈希值之间的对应关系,在该多个类的类名的哈希值中查找目标哈希值,并获取目标哈希值对应的类地址;其中,目标哈希值是待加载类的类名的哈希值。在根据该多个类的类名与该多个类的类信息之间的对应关系,在该多个类的类名中查找待加载类的类名,并获取待加载类的类名对应的类信息的方面,查找单元902具体用于:在目标哈希值对应的类地址所指示的存储空间中,查找待加载类的类名,其中,待加载类的类名是待加载类的类信息的一部分;将目标哈希值对应的类地址所指示的存储空间中的类信息,作为待加载类的类信息。例如,结合图9,查找单元902具体可以用于执行s403~s405。[0139]可选的,一个哈希值对应一个桶,一个桶包括零个、一个或多个类地址;在根据该多个类的类地址与该多个类的类名的哈希值之间的对应关系,在该多个类的类名的哈希值中查找目标哈希值,并获取目标哈希值对应的类地址的方面,查找单元902具体用于:根据多个桶与该多个类的类名的哈希值之间的对应关系,在该多个类的类名的哈希值中查找目标哈希值,并获取目标哈希值对应的桶,并将目标哈希值对应的桶所包括的类地址作为目标哈希值对应的类地址。例如,结合图9,查找单元902具体可以用于执行s403。[0140]可选的,一个桶具有一个首地址和一个尾地址,该多个桶包括第一桶,第一桶的首地址和尾地址所限定的存储空间用于存储第一桶包括的类地址。相应的,查找单元902还用于:从该多个桶的首地址和尾地址中,查找目标哈希值对应的桶的首地址和尾地址;从目标哈希值对应的桶的首地址至尾地址所限定的存储空间中,读取目标哈希值对应的桶所包括的类地址。例如,结合图9,查找单元902具体可以用于执行s401~s402。[0141]可选的,该装置90还包括:加载单元904,用于将运行上述应用程序所需的全量二进制文件从该装置90的外存加载到该装置90的内存中;全量二进制文件包括目标二进制文件。[0142]可选的,该装置90还包括:创建单元905,用于创建上述应用程序的至少两个类加载器,并建立该至少两个类加载器与该全量二进制文件之间的对应关系;该至少两个类加载器包括第一类加载器,第一类加载器用于在与第一类加载器对应的二进制文件中查找待加载类的类信息。例如,结合图5,创建单元905可以用于执行s202和s203。[0143]可选的,确定单元901还用于,根据双亲委派机制,在该至少两个类加载器中确定当前执行查找操作的类加载器,以通过所确定的当前执行查找操作的类加载器,在运行上述应用程序所需的全量二进制文件中查找待加载类的类信息。例如,结合图6,确定单元901可以用于执行s303。[0144]可选的,类加载器与二进制文件存在对应关系,包括:类加载器与二进制文件的路径存在对应关系;相应的,查找单元902还用于,根据该至少两个类加载器与该全量二进制文件的路径之间的对应关系,在该全量二进制文件的路径中查找目标栈帧所在的二进制文件的路径,并获取目标栈帧所在的二进制文件的路径对应的类加载器,将所确定的类加载器作为双亲委派机制中所采用的初始类加载器;目标栈帧是调用待加载计算机设备的栈帧,待加载计算机设备所属所述待加载类。例如,结合图6,确定单元901可以用于执行s303。[0145]可选的,创建单元905还用于,建立该至少两个类加载器与该全量二进制文件中的类之间的对应关系;其中,第一类加载器与第一类加载器对应的二进制文件所包含的类之间存在对应关系;确定单元901还用于,将当前调用待加载类的类所对应的类加载器,作为双亲委派机制中所采用的初始类加载器。[0146]可选的,上述二进制文件包括so文件。[0147]上述所描述的任意一种装置90均可以用于执行上述方法实施例中的相应步骤,因此,其相关内容的解释及有益效果均可以参考上述方法实施例中的相应描述,此处不再赘述。[0148]在上述实施例中,可以全部或部分地通过软件、硬件、固件或者其任意组合来实现。当使用软件程序实现时,可以全部或部分地以计算机程序产品的形式来实现。该计算机程序产品包括一个或多个计算机指令。在计算机上加载和执行计算机执行指令时,全部或部分地产生按照本技术实施例的流程或功能。计算机可以是通用计算机、专用计算机、计算机网络、或者其他可编程装置。计算机指令可以存储在计算机可读存储介质中,或者从一个计算机可读存储介质向另一个计算机可读存储介质传输,例如,计算机指令可以从一个网站站点、计算机、服务器或者数据中心通过有线(例如同轴电缆、光纤、数字用户线(digitalsubscriberline,dsl))或无线(例如红外、无线、微波等)方式向另一个网站站点、计算机、服务器或数据中心进行传输。计算机可读存储介质可以是计算机能够存取的任何可用介质或者是包含一个或多个可以用介质集成的服务器、数据中心等数据存储设备。可用介质可以是磁性介质(例如,软盘、硬盘、磁带),光介质(例如,dvd)、或者半导体介质(例如固态硬盘(solidstatedisk,ssd))等。[0149]以上所述,仅为本技术的具体实施方式。熟悉本
技术领域
:的技术人员根据本技术提供的具体实施方式,可想到变化或替换,都应涵盖在本技术的保护范围之内。当前第1页12当前第1页12
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1