诊断Java代码: 平台相关性"gotcha问题"[Java编程]
本文“诊断Java代码: 平台相关性"gotcha问题"[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
一次编写,到处运行.这是答应,但 Java 语言有时刻并不能做到.当然,JVM 把跨平台互操作性的程度提到了前所未有的高度,但是,标准和实现级别上的一些小弊端却使得程序无法在多平台上表现出精确的行为.
用 Java 编程的主要长处之一是它给您带来的很大程度的平台无关性.您只要将您的产品编译成字节码,然后分发到任何带有 JVM 的平台就行了,而没必要为每个目标平台构建一个独立的构建版.大概说,至少事情应当是这样的.
但事情并没有那么简单.固然通过对多平台的支持,Java 编程可认为开辟者节俭无数的时间,但是,差别的 JVM 版本之间存在很多兼容性问题.此中一些问题很简单便可以找到和改正,比方:在构造途径名的时刻利用特定于平台的脱离符字符.但别的问题大概就很难大概不大概截查到.
因此,一些难以注释的不正常的程序行为在某个特定的 JVM 中有大概是一个错误,记着这一点是很重要的.
与供应商相关的错误
当然,假如想看看存在于 JVM 中的众多奇妙的与平台相关的错误中的一些,您只需偶而查查 Sun 的 Java Bug Parade(请参阅 参考资料).这里所列的很多错误都是仅仅实用于某一特定平台上的 JVM 的 实现错误.假如刚巧不在该平台上举行开辟,您乃至大概不知道您的程序会在那个平台上受阻.
但是,并非全部的 Java 平台相关性都是 JVM 实现错误的后果.明显的平台相关性是 JVM 标准自身带来的.当 JVM 的细节在标准级别上不受限制时,便大概在 JVM 之间产生与供应商相关的行为.
比方,正如我们回想“ Improve the performance of your Java code”(2001 年 5 月)所看到的,JVM 标准对 尾递归调用(tail-recursive call)的优化不作要求.尾递归调用就是作为办法的最后一个操作呈现的递归的办法调用.更普通地说,任何办法调用,不管是不是递归的,只要呈目前办法的末尾就是 尾调用(tail call).比方,考虑以下简单的代码:
清单 1. 一个尾递归的 factorial
public class Math {
public int factorial(int n) {
return _factorial(n, 1);
}
private int _factorial(int n, int result) {
if (n <= 0) {
return result;
}
else {
return _factorial(n - 1, n * result);
}
}
}
在这个示例中,大众的 factorial办法和私有的 助手办法 _factorial 都包含尾调用; factorial 包含一个对 _factorial 的尾调用, _factorial 包含一个对它自身的尾递归调用.
假如您认为用这种办法编写 factorial分外复杂,那您并非唯一有这种感受的人.为什么不用以下自然得多的情势编写它呢?
清单 2. 一个纯递归的 factorial
public class Math {
int factorial(int n) {
if (n <= 0) {
return 1;
}
else {
return n * factorial(n-1);
}
}
}
答复是尾递归考虑到了很强有力的优化 ― 尾递归让我们用为 被调办法构建的仓库帧来替换为 主调办法构建的仓库帧.这可以极大地减小运行时的仓库深度,从而避免仓库溢出(特别是假如尾调用是递归的话,比方清单 2 中对 _factorial 的尾调用).
有些 JVM 实现这种优化;有些则不然.后果是有些程序在有些平台上会惹起仓库溢出,在别的平台上则不会.如果这种优化可以静态地举行,我们便可以只将字节码编译成尾调用优化过的情势,这样就可以同时享有平台无关性和这种优化.不幸的是,正如我在上面所引用的谈论这个主题的文章中所讲授的那样,这种优化无法静态地举行.
以上是“诊断Java代码: 平台相关性"gotcha问题"[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |