首页 | 源码下载 | 网站模板 | 网页特效 | 广告代码 | 网页素材 | 字体下载 | 书库 | 站长工具
会员投稿 投稿指南 RSS订阅
当前位置:主页>网络编程>java教程>资讯:使用实时Java降低Java应用程序的易变性(1)

使用实时Java降低Java应用程序的易变性(1)

www.jz123.cn  2010-10-22   来源:   中国建站    责任编辑(袁袁)    我要投递新闻

Java 类加载暂停

  Java 语言规范要求在应用程序首次引用类时对类进行解析、加载、验证和初始化。如果对一个类 C 的首次引用发生在时间关键型操作期间,那么解析、验证、加载和初始化 C 的时间可能导致执行操作的时间比预期更长。由于加载 C 涉及到验证该类(这可能需要加载其他类),所以 Java 应用程序为了能够首次使用特定类而发生的总延迟可能比预期长很多。

  为什么类只能在应用程序执行期间首次被引用?很少执行的路径是加载新类的一个常见原因。例如,清单 1 中的代码包含一个可能很少发生的 if 条件。(为了简单起见,我们尽可能省略了本文中所有清单中的异常和错误处理)。

  清单 1. 用于加载新类的很少执行的条件示例

 
   Iterator cursor = list.iterator();
  while (cursor.hasNext()) {
  MyClass o = cursor.next();
  if (o.getID() == 17) {
  NeverBeforeLoadedClass o2 = new NeverBeforeLoadedClass(o);
  // do something with o2
  }
  else {
  // do something with o
  }
  }

  异常类是只能在应用程序执行期间加载的类的另一个例子,因为异常在理想情况下(但不一定会遇到这种情况)很少发生。由于异常通常难以快速处理,所以加载额外的类的附加开销可能使操作延迟超出重要阈值。一般而言,应该尽可能避免在时间关键型操作期间抛出异常。

  也可以在 Java 类库中使用某些服务(比如反射)时加载新类。反射类的底层实现会动态生成将加载到 JVM 中的新类。在时间敏感型代码中反复使用反射类可能导致持续不断的类加载活动,这会引起延迟。使用 -verbose:class 选项是检测正在被创建的类的最佳方式。或许避免在程序执行期间创建这些类的最佳方式在于,避免在应用程序的时间关键型部分使用反射服务来从字符串映射类、字段或方法。相反,在应用程序执行过程中尽早调用这些服务并存储结果共以后使用,这可以避免在不需要时动态创建大部分这样的类。

  一种在应用程序的时间敏感型部分避免类加载延迟通用技术是,在应用程序启动或初始化期间预先加载类。尽管这个预加载步骤带来一定的启动延迟(改善一个指标通常会对其他指标带来负面影响),但是如果小心使用,这一步可以在以后消除不需要的类加载过程。这种启动流程很容易实现,如清单 2 所示:

  清单 2. 从一组类中以受控方式加载类


   Iterator classIt = listOfClassNamesToLoad.iterator();
  while (classIt.hasNext()) {
  String className = classIt.next();
  try {
  Class clazz = Class.forName(className);
  String n=clazz.getName();
  } catch (Exception e) {
  System.err.println("Could not load class: " + className);
  System.err.println(e);
  }

  注意 clazz.getName() 调用,它强制执行类初始化。构建类列表需要在应用程序运行时从其中收集信息,或者使用一个实用工具来确定应用程序将加载哪些类。例如,可以使用 -verbose:class 选项在程序运行时捕获输出。清单 3 显示了在使用 IBM WebSphere Real Time 产品时,此命令的可能输出:

  清单 3. 使用 -verbose:class 命令运行 java 的部分输出


  ...
  class load: java/util/zip/ZipConstants
  class load: java/util/zip/ZipFile
  class load: java/util/jar/JarFile
  class load: sun/misc/JavaUtilJarAccess
  class load: java/util/jar/JavaUtilJarAccessImpl
  class load: java/util/zip/ZipEntry
  class load: java/util/jar/JarEntry
  class load: java/util/jar/JarFile$JarFileEntry
  class load: java/net/URLConnection
  class load: java/net/JarURLConnection
  class load: sun/net/www/protocol/jar/JarURLConnection
  ...

  通过存储应用程序在执行时将加载的类列表,并使用该列表填充 清单 2 中显示的循环的类名称列表,可以确保在应用程序开始运行之前加载这些类。当然,不同时刻执行应用程序可能加载不同的路径,所以一次执行的列表可能并不完整。出于此原因,如果应用程序正在开发之中,新编写或修改的代码可能依赖于未包含在列表中的新类(或者虽然包含在列表中,但不再需要的类)不幸的是,维护类列表可能是使用此方法预加载类的非常模麻烦的一部分。如果使用此方法,请记住,-verbose:class 输出的类名称与 -verbose:class does not match the format that's needed by Class.forName() 需要的格式并不匹配:详细输出中使用正斜杠将类包分开,而 Class.forName() 期望用句点来分开它们。

  对于存在类加载问题的应用程序,可以借助一些工具来管理预加载,包括 Real Time Class Analysis Tool (RATCAT) 和 IBM Real Time Application Execution Optimizer for Java。这些工具能够在一定程度上自动识别要预加载的正确类列表,以及将类预加载代码合并到应用程序中

上一篇:Java 字符串正则表达式使用 下一篇:使用实时Java降低Java应用程序的易变性(2)

评论总数:0 [ 查看全部 ] 网友评论


关于我们隐私版权广告服务友情链接联系我们网站地图