为什么Math.sin()委托给StrictMath.sin()?

eme*_*esx 23 java jit jvm

我想知道,为什么Math.sin(double)委托给StrictMath.sin(double)我在Reddit线程中发现问题.提到的代码片段看起来像这样(JDK 7u25):

Math.java:

public static double sin(double a) {
    return StrictMath.sin(a); // default impl. delegates to StrictMath
}
Run Code Online (Sandbox Code Playgroud)

StrictMath.java:

public static native double sin(double a);
Run Code Online (Sandbox Code Playgroud)

第二个声明native对我来说是合理的.国家文件Math说:

鼓励代码生成器使用特定于平台的本机库或微处理器指令(如果可用)

问题是:是不是本机库实现了StrictMath足够的平台?JIT比安装的JRE更了解平台(请关注这个案例)?换句话说,为什么不是Math.sin()本地人呢?

eme*_*esx 17

我将尝试在一篇文章中结束整个讨论..

一般来说,Math代表来StrictMath.显然,可以内联调用,因此这不是性能问题.

StrictMath是一个native由本机库支持的方法的最终类.有人可能认为,本土意味着最优,但并非必须如此.通过StrictMathjavadoc查看以下内容:

(...)此程序包中某些数字函数的定义要求它们产生与某些已发布算法相同的结果.这些算法可以从众所周知的网络库netlib获得,作为"Freely Distributable Math Library"包fdlibm.然后,这些以C编程语言编写的算法应理解为遵循Java浮点算法规则的所有浮点运算.

我如何理解这个文档是本机库实现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);
   }
Run Code Online (Sandbox Code Playgroud)

并且正弦函数在fdlibm/src/s_sin.c中定义,在一些地方引用__kernel_sin直接来自头文件fdlibm.h的函数.


虽然我暂时接受了自己的答案,但我很乐意接受一个更有能力的答案.