我想知道,当我在Reddit thread中发现问题时,为什么Math.sin(double)
委托(delegate)给StrictMath.sin(double)
。提到的代码片段如下所示(JDK 7u25):
Math.java:
public static double sin(double a) {
return StrictMath.sin(a); // default impl. delegates to StrictMath
}
StrictMath.java:
public static native double sin(double a);
第二个声明是
native
,对我来说是合理的。 Math
的文档指出:,问题是:实现平台特定于
StrictMath
的本机库不够吗?除了已安装的JRE,JIT还可以了解有关平台的更多信息(请仅关注这种情况)?换句话说,为什么Math.sin()
还不是原生的? 最佳答案
我将尝试在单个帖子中总结整个讨论。
通常,Math
委托(delegate)给StrictMath
。显然,该调用可以是inlined,因此这不是性能问题。StrictMath
是最终类,其原生库支持native
方法。有人可能会认为,本机意味着最优,但这不一定是事实。通过StrictMath
javadoc可以看到以下内容:
我对这个文档的理解是,实现StrictMath
的本机库是根据fdlibm库实现的,fdlibm库是多平台的,已知会产生可预测的结果。由于它是多平台的,因此不能期望它是每个平台上的最佳实现。我相信这是智能JIT可以微调实际性能的地方,例如通过对输入范围的统计分析并相应地调整算法/实现。
深入研究实现,很快发现,备份StrictMath
的本机库实际上是使用 fdlibm:
OpenJDK 7中的StrictMath.c源代码如下所示:
#include "fdlibm.h"
...
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_sin(JNIEnv *env, jclass unused, jdouble d)
{
return (jdouble) jsin((double)d);
}
正弦函数在fdlibm/src/s_sin.c中定义,在某些地方引用直接来自头文件fdlibm.h的
__kernel_sin
函数。当我暂时接受自己的答案时,我很高兴在出现时接受一个更称职的答案。