专利名称:基于嵌入式实时Java虚拟机的预先类加载方法及装置的制作方法
技术领域:
本发明涉及类加载技术,尤其涉及基于嵌入式实时Java虚拟机的预先类加载方法及装置。
背景技术:
Java平台到现在为止已经拥有广大的开发者的基础,其应用领域从最初的服务器和桌面领域扩展到了实时和嵌入式领域。然而与传统计算环境不同的是,嵌入式实时计算是一种计算资源受限的计算,同时又要求虚拟机运行有较高的确定性。目前类加载有预先加载与依需求加载两种机制。Java运行环境为了优化系统,提高程序的执行速度,在JRE(Java Runtime Enviroment, Java运行环境)运行的开始会将Java运行所需要的基本类采用预先加载的方法全部加载到内存当中,因为这些基本类是在Java程序运行的过程当中经常要使用的,主要包括JRE的rt. jar文件里面所有的.clas文件。当Java虚拟机开始运行以后,它会找到安装在机器上的JRE环境,然后把控制权交给JRE,JRE的类加载器会将lib目录下的rt. jar基础类别文件库加载进内存,这些文件是Java程序执行所必须的,包括java. lang. Object和java. lang. ClassLoader等。系统在开始就将这些文件加载,能够避免在以后使用过程中的多次I/O操作,从而提高程序执行效率。相对于预先加载,在程序中还需要使用一些自定义的类,当使用这些自定义类的时候就要使用依需求加载方法,即在Java程序需要用到的时候再加载,以减少内存的消耗。对于实时嵌入式计算环境,若能够进行类加载,也可大幅提高程序的运行效率。但现有的类加载方法,一方面,由于对于除基本类以外的其他类需在程序执行过程中进行加载,导致了加载时间的不确定性,不能够满足实时的要求;另一方面,类加载器和核心库类的资源极为庞大,嵌入式系统的资源有限,不能够承载现有的类加载器和核心库类。因此,现有技术中,不能将类加载方法应用于实时嵌入式计算环境。
发明内容
针对上述缺陷,本发明提供一种基于嵌入式实时Java虚拟机的预先类加载方法,包括修改类加载器的java类文件,设置用于根据类的列表进行类加载的加载方法;修改虚拟机内核的jni类,设置用于调用所述加载方法以预先加载应用程序所需的全部类的预先类加载方法;获取包含应用程序所需的全部类的类列表;根据所述预先类加载方法,依照所述类列表预先加载所述应用程序所需的全部类。根据本发明的另一方面,还提供一种基于嵌入式实时Java虚拟机的预先类加载装置,包括第一设置模块,用于在类加载器的java类文件中设置用于根据类的列表进行类加载的加载方法;第二设置模块,用于在虚拟机内核的jni类中设置用于调用所述加载方法以预先加载应用程序所需的全部类的预先类加载方法;获取模块,用于获取包含应用程序所需的全部类的类列表;预加载模块,用于根据所述预先类加载方法,依照所述类列表预先加载所述应用程序所需的全部类。根据本发明的基于嵌入式实时Java虚拟机的预先类加载方法及装置,由于预先获取了应用程序所需的全部类,并通过设置预先类加载方法,实现了在嵌入式实时Java虚拟机中,预先加载所需的全部类,从而避免了在程序执行过程中按需加载类的时间抖动所带来不确定性;而且,由于该预先加载的内容仅为应用程序所需的全部类,不包括类加载器和核心类库中的应用程序不需要的大量类资源,因此能够适应嵌入式系统的有限资源;从而,实现了在嵌入式实时Java虚拟机中的预先类加载。
图1为本发明基于嵌入式实时Java虚拟机的预先类加载方法。图2为本发明基于嵌入式实时Java虚拟机的预先类加载装置的结构示意图。
具体实施例方式为使本发明的目的、技术方案和优点更加清楚,下面将结合附图,对本发明的技术方案进行清楚、完整地描述。图1为本发明基于嵌入式实时Java虚拟机的预先类加载方法。如图1所示,该预先类加载方法包括以下步骤步骤S100,修改类加载器的java类文件,设置用于根据类的列表进行类加载的加
载方法。步骤S200,修改虚拟机内核的jni类,设置用于调用加载方法以预先加载应用程序所需的全部类的预先类加载方法;步骤S300,获取包含应用程序所需的全部类的类列表;步骤S400,根据预先类加载方法,依照类列表预先加载所述应用程序所需的全部类。具体地,该基于嵌入式实时Java虚拟机的预先类加载方法包括两个部分一部分获取应用程序所需的所有类的依赖类闭包;另一部分是对Harmony虚拟机内核层有关类加载部分的修改。下面结合步骤S300对第一部分进行说明。在步骤S300中,需获取应用程序依赖的所有类的集合(依赖类闭包),以使JVMCJava虚拟机)启动后,只需一次性地将该依赖类闭包中的内容全部加载进来,从而在之后的运行程序过程中不需要再对所需的类进行加载。这个依赖类闭包,可通过实现小工具MyDependencyFinder来获得。实现小工具MyDependencyFinder例如采用如下方式实现第一步,分析应用程序的jar包,获取其中的第一个类文件及其依赖的类的集合,这些类文件及其依赖的类的集合构成了一个HashMap (基于哈希表的Map接口的实现)。第二步,对HashMap进行处理。该HashMap的初始内容为一些类以及这些类依赖的其他类的集合。在此集合中查找未曾在HashMap的键值中出现的类,并将其加入到HashMap的键值中,于是将导致HashMap的键值增多。若检测到HashMap的键值增多,则对新增加的键值所代表的类再查找一次依赖,循环以上过程,直到HashMap的键值不再增多,则说明没有新的依赖关系生成,循环结束。得到了在应用程序的jar包中的依赖类闭包。第三步,在系统类集合的jar包中对上述得到的HashMap按照第二步的方式进行依赖查找,以得到在系统类集合的jar包中的依赖类闭包。以上的过程使HashMap逐渐增大,直到其不再增大时,则获得了所有依赖类关系,构造出了包括所有需要加载的类的依赖类闭包(即包含应用程序所需的全部类的类列表)。下面结合步骤S100、步骤S200及步骤S400对第二部分进行说明。当JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构,从上到下分别是引导类加载器Bootstrap ClassLoader,其负责加载Java的核心类;扩展类加载器Extension ClassLoader,其负责加载 JRE 的扩展目录(JAVA_H0ME/jre/lib/ext 或者由Java. ext. dirs系统属性指定的)中JAR的类包;系统类加载器System ClassLoader,其负责在JVM被启动时,加载来自在java命令中的-classpath或者java. class, path系统属性或者CLASSPATH*系统属性所指定的JAR类包和类路径。Java虚拟机的加载采类用的是全盘负责委托机制。所谓全盘负责,即是当一个类加载器加载一个类的时候,这个类所依赖的和引用的所有类也由这个类加载器负责载入,除非明显指示使用另外一个类加载器载入。委托机制则是先让父类加载器(parent)寻找,只有在parent找不到的时候才从自己的类路径中去寻找。此外类加载还采用了缓存(cache)机制,也就是如果cache中保存了这个类就直接返回它,如果没有才从文件中读取和转换成类,并将其存入cache。利用MyD印endencyFinder获得的依赖类闭包中的类,一部分是应用程序的类,另一部分是系统类。对于应用程序的类,加载到System ClassLoader加载类时使用的类路径(classpath)中。对于系统类可以分两种,一种是核心类,虚拟机启动时由BootstrapClassLoader ^0 ’另一禾中亥jI^g,由 Extension ClassLoader 5 System ClassLoader加载。于是对于应用程序所需的全部的类中的系统类,将采取不同的策略,如果是核心类则直接使用Bootstrap ClassLoader加载,如果是非核心类,则使用System ClassLoader加载。在步骤S100 中,修改 ClassLoader. java,添加 preloadAlIClasses ()方法,该方法用于按照所接收的文件中加载该文件中列出的所有类。在步骤S200中,修改虚拟机内核里的jni类,添加一个预先加载所有类的方法,该方法使用JNI (Java Native Interface, Java本地编程接口)编码风格。该方法用于调用添力口在 java 层的方法 preloadAlIClasses ()。在步骤S400中,在创建虚拟机成功返回之前,通过根据步骤S200中添加的预先加载所有类的方法,调用preloadAllClassesO,根据依赖类闭包加载该依赖类闭包中所有的类,即应用程序所需的全部的类。至此,实现了在嵌入式实时Java虚拟机中对所需全部类的预加载。根据上述实施例的基于嵌入式实时Java虚拟机的预先类加载方法,由于预先获取了应用程序所需的全部类,并通过设置预先类加载方法,实现了在嵌入式实时Java虚拟机中,预先加载所需的全部类,从而避免了在程序执行过程中按需加载类的时间抖动所带来不确定性;而且,由于该预先加载的内容仅为应用程序所需的全部类,不包括类加载器和核心类库中的应用程序不需要的大量类资源,因此能够适应嵌入式系统的有限资源;从而,实现了在嵌入式实时Java虚拟机中的预先类加载。进一步地,在上述实施例的基于嵌入式实时Java虚拟机的预先类加载方法中,获取包含应用程序所需的全部类的类列表的步骤例如包括步骤1 获取初始类和所述初始类的依赖类,将所述初始类及所述依赖类的键值加入到所述类列表中;步骤2 获取与所述加入到所述类列表中的键值对应的依赖类具有依赖关系的类,若判断获知所述类的键值未包括在所述类列表中,则将所述类的键值加入到所述类表中,并重复执行步骤2。 例如,主类A依赖于类B、类C和类D,类A作为初始值加入到HashMap的键集合中,类B、类C、类D是A对应的依赖类。若类B、类C、类D未包含在HashMap的键集合中,则将类B、类C、类D加入键集合。类B、类C、类D又依赖于类E、类F、类G、类H、类I、类J、类K和类B,其中类B已包含在HashMap的键集合中,故仅将类E、类F、类G、类H、类I、类J、类K加入到HashMap的键集合中,并将其作为下一层依赖关系分析时键的扩张。依此方法类推,直到键集合不再增长为止。进一步地,在上述实施例的基于嵌入式实时Java虚拟机的预先类加载方法中,获取初始类和所述初始类的依赖类之前,还包括获取所述应用程序的jar文件中的.class类文件,并获取所述.class类文件的依赖类。进一步地,在上述实施例的基于嵌入式实时Java虚拟机的预先类加载方法中,修改类加载器的java类文件的步骤之前还包括删除类加载器中的扩展类加载器,以使类加载器中的系统类加载器的双亲为引导类加载器。具体;t也,System ClassLoader 的parent 设为null,艮口默认System ClassLoader的parent是Bootstrap ClassLoader0去掉该扩展类加载器能够简化设计。可采用如下方法对上述实施例的基于嵌入式实时Java虚拟机的预先类加载方法的效果进行验证。步骤S10,修改虚拟机内核里的类加载类以实现以下操作在加载类的方法的实现中打印当时加载的类并且在加载前后分别设置时间戳,通过加载前时阄戳与加载后时间戳的时间差获得加载某个类的时间,将类名和对应的加载时间信息输出到临时文件中;步骤S20,修改虚拟机内核里的jni类,以在创建虚拟机成功返回之前,预先加载所有需要的类的过程中根据步骤SlO中的设置添加时间戳(即加载前的时间戳);步骤S30,修改虚拟机内核里的jni类,以在销毁虚拟机一开始再次得到时间戳(即加载后的时间戳)。通过步骤S20中添加的时间戳与步骤S30中添加的时间戳即可获得对应的主函数执行的时间。步骤S40,获取预加载结束后的类,进行去重、去除数组类得到类的集合,根据上述得到的对应各类的加载时间,将加载时间小于9微秒的类过滤掉,留下的就是程序从主函数开始后加载花的时间较长的类,即没有预先加载的类;以此可以获知利用该方法已成功预加载应用程序所需的类;步骤S50,不启用上述实施例的基于嵌入式实时Java虚拟机的预先类加载方法进行预先类加载(在jni. cpp中注释掉I^eloadAllClassesO),运行应用程序;能够看出该运行过程由于加载的时间具有不可预测性,在时间轴上抖动非常强烈。而启用利用本发法的预先类加载,则程序运行中需要再次加载非常短,通常在10微秒以下,在时间轴上很平稳。通过上述验证,可以获知上述实施例的基于嵌入式实时Java虚拟机的预先类加载方法能够成功预先加载应用程序所需的全部类,避免在程序执行过程中按需加载类的时间抖动所带来不确定性。图2为本发明基于嵌入式实时Java虚拟机的预先类加载装置的结构示意图,如图2所示,该基于嵌入式实时Java虚拟机的预先类加载装置,包括第一设置模块10,用于在类加载器的java类文件中设置用于根据类的列表进行类加载的加载方法;第二设置模块20,用于在虚拟机内核的jni类中设置用于调用加载方法以预先加载应用程序所需的全部类的预先类加载方法;获取模块30,用于获取包含应用程序所需的全部类的类列表;预加载模块40,用于根据预先类加载方法,依照类列表预先加载应用程序所需的全部类。进一步地,在上述实施例的基于嵌入式实时Java虚拟机的预先类加载装置中,获取模块包括第一获取单元,用于获取初始类和初始类的依赖类,将初始类及所述依赖类的键值加入到类列表中;第二获取单元,与第一获取单元连接,用于获取与加入类列表中的键值对应的依赖类的具有依赖关系的类;判断单元,与第二获取单元连接,用于若判断获知类的键值未包括在类列表中,则将类的键值加入到所述类表中,并向第二获取单元发送查询指令,以使第二获取单元再次获取与加入类列表中的键值对应的依赖类的具有依赖关系的类。最后应说明的是以上实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本发明各实施例技术方案的精神和范围。
权利要求
1.一种基于嵌入式实时Java虚拟机的预先类加载方法,其特征在于,包括修改类加载器的java类文件,设置用于根据类的列表进行类加载的加载方法;修改虚拟机内核的jni类,设置用于调用所述加载方法以预先加载应用程序所需的全部类的预先类加载方法;获取包含应用程序所需的全部类的类列表;根据所述预先类加载方法,依照所述类列表预先加载所述应用程序所需的全部类。
2.根据权利要求1所述的基于嵌入式实时Java虚拟机的预先类加载方法,其特征在于,所述获取包含应用程序所需的全部类的类列表的步骤包括步骤1 获取初始类和所述初始类的依赖类,将所述初始类及所述依赖类的键值加入到所述类列表中;步骤2:获取与所述加入到所述类列表中的键值对应的依赖类具有依赖关系的类,若判断获知所述类的键值未包括在所述类列表中,则将所述类的键值加入到所述类表中,并重复执行步骤2。
3.根据权利要求2所述的基于嵌入式实时Java虚拟机的预先类加载方法,其特征在于,在所述步骤1之前还包括获取所述应用程序的jar文件中的.class类文件,并获取所述.class类文件的依赖类。
4.根据权利要求1所述的基于嵌入式实时Java虚拟机的预先类加载方法,其特征在于,所述修改类加载器的java类文件的步骤之前还包括删除所述类加载器中的扩展类加载器,以使所述类加载器中的系统类加载器的双亲为引导类加载器。
5.一种基于嵌入式实时Java虚拟机的预先类加载装置,其特征在于,包括第一设置模块,用于在类加载器的java类文件中设置用于根据类的列表进行类加载的加载方法;第二设置模块,用于在虚拟机内核的jni类中设置用于调用所述加载方法以预先加载应用程序所需的全部类的预先类加载方法;获取模块,用于获取包含应用程序所需的全部类的类列表;预加载模块,用于根据所述预先类加载方法,依照所述类列表预先加载所述应用程序所需的全部类。
6.根据权利要求5所述的基于嵌入式实时Java虚拟机的预先类加载装置,其特征在于,所述获取模块包括第一获取单元,用于获取初始类和所述初始类的依赖类,将所述初始类及所述依赖类的键值加入到所述类列表中;第二获取单元,与所述第一获取单元连接,用于获取与加入所述类列表中的键值对应的依赖类的具有依赖关系的类;判断单元,与所述第二获取单元连接,用于若判断获知所述类的键值未包括在所述类列表中,则将所述类的键值加入到所述类表中,并向所述第二获取单元发送查询指令,以使所述第二获取单元再次获取与加入所述类列表中的键值对应的依赖类的具有依赖关系的类。
全文摘要
本发明提供基于嵌入式实时Java虚拟机的预先类加载方法及装置。该方法包括修改类加载器的java类文件,设置用于根据类的列表进行类加载的加载方法;修改虚拟机内核的jni类,设置用于调用所述加载方法以预先加载应用程序所需的全部类的预先类加载方法;获取包含应用程序所需的全部类的类列表;根据所述预先类加载方法,依照所述类列表预先加载所述应用程序所需的全部类。本发明提供的基于嵌入式实时Java虚拟机的预先类加载方法及装置能够避免时间抖动及嵌入式系统资源有限的缺陷,实现了在嵌入式实时Java虚拟机中的预先类加载。
文档编号G06F9/445GK102567033SQ20101058821
公开日2012年7月11日 申请日期2010年12月14日 优先权日2010年12月14日
发明者曹东刚, 梅宏, 荀娜 申请人:北京大学