首先,值得注意的是,“慢”指的是需要花费数十纳秒的时间。对于微不足道的本地方法,在2010年,我在Windows桌面上测量到平均40纳秒的调用,在Mac桌面上则为11纳秒。除非您进行了大量调用,否则您不会注意到。
尽管如此,调用本地方法可能比普通的Java方法调用要慢。原因包括:
虚拟机不会内联本地方法。它们也不会即时编译为这台特定的机器-它们已经编译完成。
Java数组可能会被复制以便在本地代码中访问,并稍后将其复制回来。成本可以与数组大小成线性关系。我在Windows桌面上测量JNI 复制一个100,000个数组的平均时间约为75微秒,在Mac上为82微秒。幸运的是,可以通过GetPrimitiveArrayCritical或NewDirectByteBuffer获得直接访问。
如果该方法被传递一个对象,或者需要进行回调,则本地方法可能会自己向JVM发出调用。从本地代码访问Java字段、方法和类型需要类似于反射的东西。签名在字符串中指定,并从JVM中查询。这既慢又容易出错。
Java字符串是对象,具有长度并且编码。访问或创建字符串可能需要O(n)复制。
关于JNI成本的讨论,可能已过时,请参阅Steve Wilson和Jeff Kesselman在2000年出版的《Java(tm) Platform Performance: Strategies and Tactics》一书中第9.2节。此书链接在Philip的评论中提供,位于页面的三分之一处。
IBM developerWorks于2009年发表的论文“使用Java Native Interface的最佳实践”提供了一些有关避免JNI性能陷阱的建议。