正在阅读:提高 Java 代码的性能提高 Java 代码的性能

2005-08-15 14:40 出处: 作者:Eric Allen 责任编辑:xietaoming

 
  您的 JIT 会做这种转换吗?

  因此,如清单 3 中的示例所示,我们不能期望静态编译器会在保持语言语义的同时对 Java 代码执行尾递归转换。相反地,我们必须依靠 JIT 进行的动态编译。JIT 会不会做这种转换是取决于 JVM。  

  要判断您的 JIT 会否转换尾递归的一个办法是编译并运行如下小测试类:  

  清单 4. 判断您的 JIT 能否转换尾递归 

public class TailRecursionTest { 

  private static int loop(int i) { 
    return loop(i); 
  } 

  public static void main(String[] args) { 
    loop(0); 
  } 

  我们来考虑一下这个类的 loop 方法。这个方法只是尽可能长时间地对自身作递归调用。因为它永远不会返回,也不会以任何方式影响任何外部变量,因此如清单 5 所示替换其代码正文将保留程序的语义。  

  清单 5. 一个动态转换 

public class TailRecursionTest { 

  private static int loop(int i) { 
    while (true) { 
    } 
  } 

  public static void main(String[] args) { 
    loop(0); 
  } 

  而且,事实上这也就是足够完善的编译器所做的转换。  

  如果您的 JIT 编译器把尾递归调用转换成迭代,这个程序将无限期地运行下去。它所需的内存很小,而且不会随时间增加。  

  另一方面,如果 JIT 不做这种转换,程序将会很快耗尽堆栈空间并报告一个堆栈溢出错误。  

  我在两个 Java SDK 上运行这个程序,结果令人惊讶。在 SUN 公司的 Hotspot JVM(版本 1.3 )上运行时,发现 Hotspot 不执行这种转换。缺省设置下,在我的机器上运行时,不到一秒钟堆栈空间就被耗尽了。  

  另一方面,程序在 IBM 的 JVM(版本 1.3 )上咕噜噜运行时却没有任何问题,这表明 IBM 的 JVM 以这种方式转换代码。  

  总结 

  记住:我们不能寄希望于我们的代码会总是运行在会转换尾递归调用的 JVM 上。因此,为了保证您的程序在所有 JVM 上都有适当的性能,您应始终努力把那些最自然地符合尾递归模式的代码按迭代风格编写。  

  但是请注意:就象我们的示例所演示的那样,以这种方式转换代码时很容易引入错误,不论是由人工还是由软件来完成这种转换。  

  其实从网上发现这样的文章并不难,希望大家在遇到问题时都能学会如何处理

  学习的过程就是学会学习方法的过程,难道不是吗? 

键盘也能翻页,试试“← →”键

关注我们

最新资讯离线随时看 聊天吐槽赢奖品