{"id":10006277,"date":"2022-08-22T14:03:13","date_gmt":"2022-08-22T06:03:13","guid":{"rendered":"https:\/\/ityet.com\/?p=10006277"},"modified":"2022-08-22T14:03:13","modified_gmt":"2022-08-22T06:03:13","slug":"%e5%af%86%e9%9b%86%e8%ae%a1%e7%ae%97%e5%9c%ba%e6%99%af%e4%b8%8b%e7%9a%84-jni-%e5%ae%9e%e6%88%98","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006277","title":{"rendered":"\u5bc6\u96c6\u8ba1\u7b97\u573a\u666f\u4e0b\u7684 JNI \u5b9e\u6218"},"content":{"rendered":"<blockquote><p>\u4f5c\u8005\uff1avivo \u4e92\u8054\u7f51\u670d\u52a1\u5668\u56e2\u961f- Wei Qianzi\u3001Li Haoxuan<\/p><\/blockquote>\n<p>\u5728 Java \u53d1\u5c55\u5386\u7a0b\u4e2d\uff0cJNI \u4e00\u76f4\u90fd\u662f\u4e00\u4e2a\u4e0d\u53ef\u6216\u7f3a\u7684\u89d2\u8272\uff0c\u4f46\u662f\u5728\u5b9e\u9645\u7684\u9879\u76ee\u5f00\u53d1\u4e2d\uff0cJNI \u8fd9\u9879\u6280\u672f\u5e94\u7528\u7684\u5f88\u5c11\u3002\u5728\u7b14\u8005\u7ecf\u8fc7\u8270\u96be\u7684\u8e29\u5751\u4e4b\u540e\uff0c\u7ec8\u4e8e\u5c06 JNI \u8fd0\u7528\u5230\u4e86\u9879\u76ee\u5b9e\u6218\uff0c\u672c\u6587\u7b14\u8005\u5c06\u7b80\u5355\u4ecb\u7ecd JNI \u6280\u672f\uff0c\u5e76\u4ecb\u7ecd\u7b80\u5355\u7684\u539f\u7406\u548c\u6027\u80fd\u5206\u6790\u3002\u901a\u8fc7\u5206\u4eab\u6211\u4eec\u7684\u5b9e\u8df5\u8fc7\u7a0b\uff0c\u5e26\u5404\u4f4d\u8bfb\u8005\u4f53\u9a8c JNI \u6280\u672f\u7684\u5e94\u7528\u3002<\/p>\n<h2>\u4e00\u3001 \u80cc\u666f<\/h2>\n<p>\u8ba1\u7b97\u5bc6\u96c6\u578b\u573a\u666f\u4e2d\uff0cJava \u8bed\u8a00\u9700\u8981\u82b1\u8d39\u8f83\u591a\u65f6\u95f4\u4f18\u5316 GC \u5e26\u6765\u7684\u989d\u5916\u5f00\u9500\u3002\u5e76\u4e14\u5728\u4e00\u4e9b\u5e95\u5c42\u6307\u4ee4\u4f18\u5316\u65b9\u9762\uff0cC++ \u8fd9\u79cd\u201c\u4eb2\u6838\u6027\u201d\u7684\u8bed\u8a00\u6709\u7740\u8f83\u597d\u7684\u4f18\u52bf\u548c\u5927\u91cf\u7684\u4e1a\u754c\u5b9e\u8df5\u7ecf\u9a8c\u3002\u90a3\u4e48\u4f5c\u4e3a\u4e00\u4e2a\u591a\u5e74\u7684 Java \u7a0b\u5e8f\u5458\uff0c\u80fd\u5426\u5728 Java \u670d\u52a1\u4e0a\u9762\u8fd0\u884c C++ \u4ee3\u7801\u5462\uff1f\u7b54\u6848\u662f\u80af\u5b9a\u7684\u3002<\/p>\n<p>JNI (Java Native Interface) \u6280\u672f\u6b63\u662f\u5e94\u5bf9\u8be5\u573a\u666f\u800c\u63d0\u51fa\u7684\u89e3\u51b3\u65b9\u6848\u3002\u867d\u7136 JNI \u6280\u672f\u8ba9\u6211\u4eec\u80fd\u591f\u8fdb\u884c\u6df1\u5ea6\u7684\u6027\u80fd\u4f18\u5316\uff0c\u5176\u8f83\u4e3a\u7e41\u7410\u7684\u5f00\u53d1\u65b9\u5f0f\u4e5f\u4e0d\u514d\u8ba9\u65b0\u4eba\u611f\u5230\u5934\u75bc\u3002\u672c\u6587\u901a\u8fc7 step by step \u7684\u65b9\u5f0f\u4ecb\u7ecd\u5982\u4f55\u5b8c\u6210 JNI \u7684\u5f00\u53d1\uff0c\u4ee5\u53ca\u6211\u4eec\u4f18\u5316\u7684\u6548\u679c\u548c\u601d\u8003\u3002<\/p>\n<blockquote><p>\u5f00\u59cb\u6b63\u6587\u524d\u6211\u4eec\u53ef\u4ee5\u601d\u8003\u4e09\u4e2a\u95ee\u9898\uff1a<\/p><\/blockquote>\n<ol>\n<li>\u4e3a\u4ec0\u4e48\u9009\u62e9\u4f7f\u7528 JNI \u6280\u672f\uff1f<\/li>\n<li>\u5982\u4f55\u5728 Maven \u9879\u76ee\u4e2d\u5e94\u7528 JNI \u6280\u672f\uff1f<\/li>\n<li>JNI \u771f\u7684\u597d\u7528\u5417\uff1f<\/li>\n<\/ol>\n<h2>\u4e8c\u3001\u5173\u4e8e JNI\uff1a\u4e3a\u4ec0\u4e48\u4f1a\u9009\u62e9\u5b83\uff1f<\/h2>\n<h3>2.1 JNI \u57fa\u672c\u6982\u5ff5<\/h3>\n<p>JNI \u7684\u5168\u79f0\u53eb\u505a Java Native Interface \uff0c\u7ffb\u8bd1\u8fc7\u6765\u5c31\u662f Java \u672c\u5730\u63a5\u53e3\u3002\u7231\u770b JDK \u6e90\u7801\u7684\u5c0f\u4f19\u4f34\u4f1a\u53d1\u73b0\uff0cJDK \u4e2d\u6709\u4e9b\u65b9\u6cd5\u58f0\u660e\u662f\u5e26\u6709 native \u4fee\u9970\u7b26\u7684\uff0c\u5e76\u4e14\u627e\u4e0d\u5230\u5177\u4f53\u5b9e\u73b0\uff0c\u5176\u5b9e\u662f\u5728\u975e Java \u8bed\u8a00\u4e0a\uff0c\u8fd9\u5c31\u662f JNI \u6280\u672f\u7684\u4f53\u73b0\u3002<\/p>\n<p>\u65e9\u5728 JDK1.0 \u7248\u672c\u5c31\u5df2\u7ecf\u6709\u4e86 JNI\uff0c\u5b98\u65b9\u7ed9 JNI \u7684\u5b9a\u4e49\u662f\uff1a<\/p>\n<blockquote><p>Java Native Interface (JNI) is a standard programming interface for writing Java native methods and embedding the Java virtual machine into native applications. The primary goal is binary compatibility of native method libraries across all Java virtual machine implementations on a given platform.<\/p><\/blockquote>\n<p>JNI \u662f\u4e00\u79cd\u6807\u51c6\u7684\u7a0b\u5e8f\u63a5\u53e3\uff0c\u7528\u4e8e\u7f16\u5199 Java \u672c\u5730\u65b9\u6cd5\uff0c\u5e76\u4e14\u5c06 JVM \u5d4c\u5165 Native \u5e94\u7528\u7a0b\u5e8f\u4e2d\u3002\u662f\u4e3a\u4e86\u7ed9\u8de8\u5e73\u53f0\u4e0a\u7684 JVM \u5b9e\u73b0\u672c\u5730\u65b9\u6cd5\u5e93\u8fdb\u884c\u4e8c\u8fdb\u5236\u517c\u5bb9\u3002<\/p>\n<p>JNI \u6700\u521d\u662f\u4e3a\u4e86\u4fdd\u8bc1\u8de8\u5e73\u53f0\u7684\u517c\u5bb9\u6027\uff0c\u800c\u8bbe\u8ba1\u51fa\u6765\u7684\u4e00\u5957\u63a5\u53e3\u534f\u8bae\u3002\u5e76\u4e14\u7531\u4e8e Java \u8bde\u751f\u5f88\u65e9\uff0c\u6240\u4ee5 JNI \u6280\u672f\u7edd\u5927\u90e8\u5206\u60c5\u51b5\u4e0b\u8c03\u7528\u7684\u662f C\/C++ \u548c\u7cfb\u7edf\u7684 lib \u5e93\uff0c\u5bf9\u5176\u4ed6\u8bed\u8a00\u7684\u652f\u6301\u6bd4\u8f83\u5c40\u9650\u3002\u968f\u7740\u65f6\u95f4\u7684\u53d1\u5c55\uff0cJNI \u4e5f\u9010\u6e10\u88ab\u5f00\u53d1\u8005\u6240\u5173\u6ce8\uff0c\u6bd4\u5982 Android \u7684 NDK\uff0cGoogle \u7684 JNA\uff0c\u90fd\u662f\u5bf9 JNI \u7684\u6269\u5c55\uff0c\u8ba9\u8fd9\u9879\u6280\u672f\u80fd\u591f\u66f4\u52a0\u8f7b\u677e\u7684\u88ab\u5f00\u53d1\u8005\u6240\u4f7f\u7528\u3002<\/p>\n<p>\u6211\u4eec\u53ef\u4ee5\u770b\u4e00\u4e0b\u5728 JVM \u4e2d JNI \u76f8\u5173\u7684\u6a21\u5757\uff0c\u5982\u56fe 1\uff1a<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042329698\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u56fe1 &#8211; JVM \u5185\u5b58\u548c\u5f15\u64ce\u6267\u884c\u5173\u7cfb<\/p>\n<p>\u5728 JVM \u7684\u5185\u5b58\u533a\u57df\uff0cNative Interface \u662f\u4e00\u4e2a\u91cd\u8981\u7684\u73af\u8282\uff0c\u8fde\u63a5\u7740\u6267\u884c\u5f15\u64ce\u548c\u8fd0\u884c\u65f6\u6570\u636e\u533a\u3002\u672c\u5730\u63a5\u53e3 (JNI) \u7684\u65b9\u6cd5\u5728\u672c\u5730\u65b9\u6cd5\u6808\u4e2d\u7ba1\u7406 native \u65b9\u6cd5\uff0c\u5728 Execution Engine \u6267\u884c\u65f6\u52a0\u8f7d\u672c\u5730\u65b9\u6cd5\u5e93\u3002<\/p>\n<p>JNI \u5c31\u50cf\u662f\u6253\u7834\u4e86 JVM \u7684\u675f\u7f1a\uff0c\u62e5\u6709\u7740\u548c JVM \u540c\u6837\u7684\u80fd\u529b\uff0c\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u5904\u7406\u5668\u4e2d\u7684\u5bc4\u5b58\u5668\uff0c\u4e0d\u4ec5\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u5904\u7406\u5668\u4e2d\u7684\u5bc4\u5b58\u5668\uff0c\u8fd8\u53ef\u4ee5\u76f4\u63a5\u627e\u64cd\u4f5c\u7cfb\u7edf\u7533\u8bf7\u4efb\u610f\u5927\u5c0f\u7684\u5185\u5b58\uff0c\u751a\u81f3\u80fd\u591f\u8bbf\u95ee\u5230 JVM \u865a\u62df\u673a\u8fd0\u884c\u65f6\u7684\u6570\u636e\uff0c\u6bd4\u5982\u641e\u70b9\u5806\u5185\u5b58\u6ea2\u51fa\u4ec0\u4e48\u7684\uff1a\uff09<\/p>\n<h3>2.2 JNI \u7684\u529f\u80fd<\/h3>\n<p>JNI \u62e5\u6709\u7740\u5f3a\u5927\u7684\u529f\u80fd\uff0c\u90a3\u5b83\u80fd\u505a\u54ea\u4e9b\u4e8b\u5462\uff1f\u5b98\u65b9\u6587\u6863\u7ed9\u51fa\u4e86\u53c2\u8003\u7b54\u6848\u3002<\/p>\n<blockquote>\n<ol>\n<li>\u6807\u51c6 Java \u7c7b\u5e93\u4e0d\u652f\u6301\u5e94\u7528\u7a0b\u5e8f\u6240\u9700\u7684\u5e73\u53f0\u76f8\u5173\u7279\u6027\u3002<\/li>\n<li>\u60a8\u5df2\u7ecf\u6709\u4e00\u4e2a\u7528\u53e6\u4e00\u79cd\u8bed\u8a00\u7f16\u5199\u7684\u5e93\uff0c\u5e76\u5e0c\u671b\u901a\u8fc7 JNI \u4f7f\u5176\u53ef\u4f9b Java \u4ee3\u7801\u8bbf\u95ee\u3002<\/li>\n<li>\u60a8\u60f3\u7528\u8f83\u4f4e\u7ea7\u522b\u7684\u8bed\u8a00\uff08\u4f8b\u5982\u6c47\u7f16\uff09\u5b9e\u73b0\u4e00\u5c0f\u90e8\u5206\u8017\u65f6\u77ed\u7684\u4ee3\u7801\u3002<\/li>\n<\/ol>\n<\/blockquote>\n<p>\u5f53\u7136\u8fd8\u6709\u4e00\u4e9b\u6269\u5145\uff0c\u6bd4\u5982\uff1a<\/p>\n<blockquote>\n<ol>\n<li>\u4e0d\u5e0c\u671b\u6240\u5199\u7684 Java \u4ee3\u7801\u88ab\u53cd\u7f16\u8bd1\uff1b<\/li>\n<li>\u9700\u8981\u4f7f\u7528\u7cfb\u7edf\u6216\u5df2\u6709\u7684 lib \u5e93\uff1b<\/li>\n<li>\u671f\u671b\u4f7f\u7528\u66f4\u5feb\u901f\u7684\u8bed\u8a00\u53bb\u5904\u7406\u5927\u91cf\u7684\u8ba1\u7b97\uff1b<\/li>\n<li>\u5bf9\u56fe\u50cf\u6216\u672c\u5730\u6587\u4ef6\u64cd\u4f5c\u9891\u7e41\uff1b<\/li>\n<li>\u8c03\u7528\u7cfb\u7edf\u9a71\u52a8\u7684\u63a5\u53e3\u3002<\/li>\n<\/ol>\n<\/blockquote>\n<p>\u6216\u8bb8\u8fd8\u6709\u522b\u7684\u573a\u666f\uff0c\u53ef\u4ee5\u4f7f\u7528\u5230 JNI\uff0c\u53ef\u4ee5\u770b\u5230 JNI \u6280\u672f\u6709\u7740\u975e\u5e38\u597d\u7684\u5e94\u7528\u6f5c\u529b\u3002<\/p>\n<h2>\u4e09\u3001JNI \u5b9e\u6218\uff1a\u63a2\u7a76\u8e29\u5751\u7684\u5168\u8fc7\u7a0b<\/h2>\n<p>\u6211\u4eec\u7684\u4e1a\u52a1\u4e2d\u5b58\u5728\u4e00\u4e2a\u8ba1\u7b97\u5bc6\u96c6\u578b\u573a\u666f\uff0c\u9700\u8981\u4ece\u672c\u5730\u52a0\u8f7d\u6570\u636e\u6587\u4ef6\u8fdb\u884c\u6a21\u578b\u63a8\u7406\u3002\u9879\u76ee\u7ec4\u5728 Java \u7248\u672c\u8fdb\u884c\u4e86\u51e0\u8f6e\u4f18\u5316\u540e\u53d1\u73b0\u6ca1\u6709\u4ec0\u4e48\u5927\u7684\u8fdb\u5c55\uff0c\u4e3b\u8981\u8868\u73b0\u4e3a\u63a8\u7406\u8017\u65f6\u8f83\u957f\uff0c\u5e76\u4e14\u52a0\u8f7d\u6a21\u578b\u65f6\u5b58\u5728\u6027\u80fd\u6296\u52a8\u3002\u7ecf\u8fc7\u8c03\u7814\uff0c\u5982\u679c\u60f3\u8fdb\u4e00\u6b65\u63d0\u9ad8\u8ba1\u7b97\u548c\u52a0\u8f7d\u6587\u4ef6\u7684\u901f\u5ea6\uff0c\u53ef\u4ee5\u4f7f\u7528 JNI \u6280\u672f\u53bb\u7f16\u5199\u4e00\u4e2a C++ \u7684 lib \u5e93\uff0c\u7531 Java native \u65b9\u6cd5\u8fdb\u884c\u8c03\u7528\uff0c\u9884\u8ba1\u4f1a\u6709\u4e00\u5b9a\u7684\u63d0\u5347\u3002<\/p>\n<p>\u7136\u800c\u9879\u76ee\u7ec4\u76ee\u524d\u4e5f\u6ca1\u6709 JNI \u7684\u5b9e\u8df5\u7ecf\u9a8c\uff0c\u6700\u7ec8\u6027\u80fd\u662f\u5426\u80fd\u6709\u63d0\u5347\uff0c\u8fd8\u662f\u8981\u6253\u4e2a\u95ee\u53f7\u3002\u672c\u7740\u521d\u751f\u725b\u728a\u4e0d\u6015\u864e\u7684\u7cbe\u795e\uff0c\u6211\u9f13\u8d77\u52c7\u6c14\u4e3b\u52a8\u8ba4\u9886\u4e86\u8fd9\u4e2a\u4f18\u5316\u4efb\u52a1\u3002\u4e0b\u9762\u5c31\u5206\u4eab\u4e00\u4e0b\u6211\u5b9e\u8df5 JNI \u7684\u8fc7\u7a0b\u548c\u9047\u5230\u7684\u95ee\u9898\uff0c\u7ed9\u5927\u5bb6\u629b\u7816\u5f15\u7389\u3002<\/p>\n<h3>3.1 \u573a\u666f\u51c6\u5907<\/h3>\n<p>\u5b9e\u6218\u5c31\u4e0d\u4ece Hello world \u5f00\u59cb\u4e86\uff0c\u6211\u4eec\u76f4\u63a5\u6572\u5b9a\u573a\u666f\uff0c\u601d\u8003\u8be5\u8ba9 C++ \u5b9e\u73b0\u54ea\u90e8\u5206\u903b\u8f91\u3002<\/p>\n<p>\u573a\u666f\u5982\u4e0b\uff1a<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042329699\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u56fe2 \u5b9e\u6218\u573a\u666f<\/p>\n<p>\u5728\u8ba1\u7b97\u670d\u52a1\u4e2d\uff0c\u6211\u4eec\u5c06\u79bb\u7ebf\u8ba1\u7b97\u6570\u636e\u8f6c\u6362\u6210 map \u7ed3\u6784\uff0c\u8f93\u5165\u4e00\u7ec4 key \u5728 map \u4e2d\u67e5\u627e\u5e76\u5bf9 value \u5e94\u7528\u7b97\u6cd5\u516c\u5f0f\u6c42\u503c\u3002\u901a\u8fc7\u5206\u6790 JVM \u5806\u6808\u4fe1\u606f\u548c\u706b\u7130\u56fe (flame graph)\uff0c\u53d1\u73b0\u6027\u80fd\u74f6\u9888\u4e3b\u8981\u5728\u5927\u91cf\u7684\u903b\u8f91\u56de\u5f52\u8fd0\u7b97\u548c GC \u4e0a\u9762\uff0c\u7531\u4e8e\u7f13\u5b58\u4e86\u91cf\u7ea7\u5f88\u5927\u7684 Map \u7ed3\u6784\uff0c\u5bfc\u81f4\u5360\u7528 heap \u5185\u5b58\u5f88\u5927\uff0c\u56e0\u6b64 GC Mark-and-Sweep \u8017\u65f6\u5f88\u957f\uff0c\u6240\u4ee5\u6211\u4eec\u51b3\u5b9a\u5c06\u52a0\u8f7d\u6587\u4ef6\u548c\u903b\u8f91\u56de\u5f52\u8fd0\u7b97\u4e24\u4e2a\u65b9\u6cd5\u6539\u9020\u4e3a native \u65b9\u6cd5\u3002<\/p>\n<p>\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre><code>\/**\n * \u52a0\u8f7d\u6587\u4ef6\n * @param path \u6587\u4ef6\u672c\u5730\u8def\u5f84\n * @return C++ \u521b\u5efa\u7684\u7c7b\u5bf9\u8c61\u7684\u6307\u9488\u5730\u5740\n *\/\npublic static native long loadModel(String path);\n \n\/**\n * \u91ca\u653e C++ \u76f8\u5173\u7c7b\u5bf9\u8c61\n * @param ptr  C++ \u521b\u5efa\u7684\u7c7b\u5bf9\u8c61\u7684\u6307\u9488\u5730\u5740\n *\/\npublic static native void close(long ptr);\n \n\/**\n * \u6267\u884c\u8ba1\u7b97\n * @param ptr C++ \u521b\u5efa\u7684\u7c7b\u5bf9\u8c61\u7684\u6307\u9488\u5730\u5740\n * @param keys \u8f93\u5165\u7684\u5217\u8868\n * @return \u8f93\u51fa\u7684\u8ba1\u7b97\u7ed3\u679c\n *\/\npublic static native float compute(long ptr, long[] keys);<\/code><\/pre>\n<p>\u90a3\u4e48\uff0c\u6211\u4eec\u4e3a\u4ec0\u4e48\u8981\u4f20\u9012\u6307\u9488\u5462\uff0c\u5e76\u4e14\u8bbe\u8ba1\u4e86\u4e00\u4e2a close \u65b9\u6cd5\u5462\uff1f<\/p>\n<blockquote>\n<ol>\n<li>\u4fbf\u4e8e\u517c\u5bb9\u73b0\u6709\u5b9e\u73b0\u7684\u8003\u8651\uff1a\u867d\u7136\u6574\u4e2a\u8ba1\u7b97\u8fc7\u7a0b\u90fd\u5728 C++ \u8fd0\u884c\u65f6\u4e2d\u8fdb\u884c\uff0c\u4f46\u5bf9\u8c61\u7684\u751f\u547d\u5468\u671f\u7ba1\u7406\u662f\u5728 Java \u4e2d\u5b9e\u73b0\u7684\uff0c\u6240\u4ee5\u6211\u4eec\u9009\u62e9\u56de\u4f20\u52a0\u8f7d\u5e76\u521d\u59cb\u5316\u540e\u7684\u6a21\u578b\u5bf9\u8c61\u6307\u9488\uff0c\u4e4b\u540e\u6bcf\u6b21\u6c42\u503c\u65f6\u4ec5\u4f20\u9012\u8be5\u6307\u9488\u5373\u53ef\uff1b<\/li>\n<li>\u5185\u5b58\u6b63\u786e\u91ca\u653e\u7684\u8003\u8651\uff1a\u5229\u7528 Java \u81ea\u8eab\u7684 GC \u548c\u6a21\u578b\u7ba1\u7406\u5668\u4ee3\u7801\u673a\u5236\uff0c\u5728\u6a21\u578b\u5378\u8f7d\u65f6\u663e\u5f0f\u8c03\u7528 close \u65b9\u6cd5\u91ca\u653e C++ \u8fd0\u884c\u65f6\u7ba1\u7406\u7684\u5185\u5b58\uff0c\u9632\u6b62\u51fa\u73b0\u5185\u5b58\u6cc4\u6f0f\u3002<\/li>\n<\/ol>\n<\/blockquote>\n<p>\u5f53\u7136\uff0c\u8fd9\u4e2a\u5efa\u8bae\u53ea\u9002\u7528\u4e8e\u9700\u8981 lib \u6267\u884c\u65f6\u5c06\u90e8\u5206\u6570\u636e\u7f13\u5b58\u5728\u5185\u5b58\u4e2d\u7684\u573a\u666f\uff0c\u53ea\u4f7f\u7528 native \u65b9\u6cd5\u8fdb\u884c\u8ba1\u7b97\uff0c\u65e0\u9700\u8003\u8651\u8fd9\u79cd\u60c5\u51b5\u3002<\/p>\n<h3>3.2 \u73af\u5883\u642d\u5efa<\/h3>\n<p>\u4e0b\u9762\u7b80\u5355\u4ecb\u7ecd\u4e00\u4e0b\u6211\u4eec\u6240\u4f7f\u7528\u7684\u73af\u5883\u548c\u9879\u76ee\u7ed3\u6784\uff0c\u8fd9\u90e8\u5206\u4ecb\u7ecd\u7684\u4e0d\u662f\u5f88\u591a\uff0c\u5982\u679c\u6709\u7591\u95ee\u53ef\u4ee5\u53c2\u8003\u6587\u672b\u7684\u53c2\u8003\u8d44\u6599\u6216\u8005\u5728\u7f51\u4e0a\u8fdb\u884c\u67e5\u9605\u3002<\/p>\n<p>\u6211\u4eec\u4f7f\u7528\u7684\u662f\u7b80\u5355\u7684 maven \u9879\u76ee\uff0c\u4f7f\u7528 Docker \u7684 ubuntu-20.04 \u5bb9\u5668\u8fdb\u884c\u7f16\u8bd1\u548c\u90e8\u7f72\uff0c\u9700\u8981\u5728\u5bb9\u5668\u4e2d\u5b89\u88c5 GCC\uff0cBazel\uff0cMaven\uff0copenJDK-8 \u7b49\u3002\u5982\u679c\u662f\u5728 Windows \u4e0b\u8fdb\u884c\u5f00\u53d1\uff0c\u4e5f\u53ef\u4ee5\u5b89\u88c5\u76f8\u5e94\u7684\u5de5\u5177\u5e76\u7f16\u8bd1\u6210 .dll \u6587\u4ef6\uff0c\u6548\u679c\u662f\u4e00\u6837\u7684\u3002<\/p>\n<p>\u6211\u4eec\u521b\u5efa\u597d maven \u9879\u76ee\u7684\u76ee\u5f55\uff0c\u5982\u4e0b\uff1a<\/p>\n<pre><code>\/src # \u4e3b\u76ee\u5f55\n-\/main\n--\/cpp  # c++ \u4ed3\u5e93\u76ee\u5f55\n---export_jni.h  # java \u5bfc\u51fa\u7684\u6587\u4ef6\n---computer.cc  # \u5177\u4f53\u7684 C++ \u4ee3\u7801\n---\/third_party  # \u4e09\u65b9\u5e93\n---WORKSPACE  # bazel \u6839\u76ee\u5f55\n---BUILD  # bazel \u6784\u5efa\u6587\u4ef6\n--\/java  # java \u4ed3\u5e93\u76ee\u5f55\n---\/com\n----\/vivo\n-----\/demo\n------\/model\n-------ModelComputer.java  # java \u4ee3\u7801\n--\/resources  # \u5b58\u653e lib \u7684\u8d44\u6e90\u76ee\u5f55\n-\/test\n--\/java\n----ModelComputerTest.java  # \u6d4b\u8bd5\u7c7b\npom.xml  # maven pom<\/code><\/pre>\n<h3>3.3 \u5b9e\u6218\u8fc7\u7a0b<\/h3>\n<p>\u90fd\u5df2\u7ecf\u51c6\u5907\u597d\u4e86\uff0c\u90a3\u4e48\u5c31\u76f4\u5165\u6b63\u9898\uff1a<\/p>\n<pre><code>package com.vivo.demo.model;\nimport java.io.*;\n \npublic class ModelComputer implements Closeable {\n    static {\n        \/\/ \u52a0\u8f7d lib \u5e93\n        loadPath(&quot;export_jni_lib&quot;);\n    }\n \n    \/**\n     * C++ \u7c7b\u5bf9\u8c61\u5730\u5740\n     *\/\n    private Long ptr;\n \n    public ModelComputer(String path) {\n        \/\/ \u6784\u9020\u51fd\u6570\uff0c\u8c03\u7528 C++ \u7684\u52a0\u8f7d\n        ptr = loadModel(path);\n    }\n \n    \/**\n     * \u52a0\u8f7d lib \u6587\u4ef6\n     *\n     * @param name lib\u540d\n     *\/\n    public static void loadPath(String name) {\n        String path = System.getProperty(&quot;user.dir&quot;) + &quot;\/\/src\/\/main\/\/resources\/\/&quot;;\n        path += name;\n        String osName = System.getProperty(&quot;os.name&quot;).toLowerCase();\n        if (osName.contains(&quot;linux&quot;)) {\n            path += &quot;.so&quot;;\n        } else if (osName.contains(&quot;windows&quot;)) {\n            path += &quot;.dll&quot;;\n        }\n        \/\/ \u5982\u679c\u5b58\u5728\u672c\u6587\u4ef6\uff0c\u76f4\u63a5\u52a0\u8f7d\uff0c\u5e76\u8fd4\u56de\n        File file = new File(path);\n        if (file.exists() &amp;&amp; file.isFile()) {\n            System.load(path);\n            return;\n        }\n        String fileName = path.substring(path.lastIndexOf('\/') + 1);\n        String prefix = fileName.substring(0, fileName.lastIndexOf(&quot;.&quot;) - 1);\n        String suffix = fileName.substring(fileName.lastIndexOf(&quot;.&quot;));\n \n        \/\/ \u521b\u5efa\u4e34\u65f6\u6587\u4ef6\uff0c\u6ce8\u610f\u5220\u9664\n        try {\n            File tmp = File.createTempFile(prefix, suffix);\n            tmp.deleteOnExit();\n \n            byte[] buff = new byte[1024];\n            int len;\n            \/\/ \u4ecejar\u4e2d\u8bfb\u53d6\u6587\u4ef6\u6d41\n            try (InputStream in = ModelComputer.class.getResourceAsStream(path);\n                    OutputStream out = new FileOutputStream(tmp)) {\n                while ((len = in.read(buff)) != -1) {\n                    out.write(buff, 0, len);\n                }\n            }\n            \/\/ \u52a0\u8f7d\u5e93\u6587\u4ef6\n            System.load(tmp.getAbsolutePath());\n        } catch (Exception e) {\n            throw new RuntimeException();\n        }\n    }\n \n    \/\/ native \u65b9\u6cd5\n    public static native long loadModel(String path);\n    public static native void close(long ptr);\n    public static native float compute(long ptr, long[] keys);\n \n    @Override\n    public void close() {\n        Long tmp = ptr;\n        ptr = null;\n        \/\/ \u5173\u95ed C++ \u5bf9\u8c61\n        close(tmp);\n    }\n \n    \/**\n     * \u8ba1\u7b97\n     * @param keys \u8f93\u5165\u7684\u5217\u8868\n     * @return \u8f93\u51fa\u7684\u7ed3\u679c\n     *\/\n    public float compute(long[] keys) {\n        return compute(ptr, keys);\n    }\n}<\/code><\/pre>\n<ul>\n<li><strong>\u8e29\u57511\uff1a\u542f\u52a8\u65f6\u62a5 java.lang.UnsatisfiedLinkError \u5f02\u5e38<\/strong><\/li>\n<\/ul>\n<p>\u8fd9\u662f\u56e0\u4e3a lib \u6587\u4ef6\u5728\u538b\u7f29\u5305\u4e2d\uff0c\u800c\u52a0\u8f7d lib \u7684\u51fd\u6570\u5bfb\u627e\u7684\u662f\u7cfb\u7edf\u8def\u5f84\u4e0b\u7684\u6587\u4ef6\uff0c\u901a\u8fc7 InputStream \u548c File \u64cd\u4f5c\u4ece\u538b\u7f29\u5305\u4e2d\u8bfb\u53d6\u8be5\u6587\u4ef6\u5230\u4e34\u65f6\u6587\u4ef6\u5939\uff0c\u83b7\u53d6\u5176\u8def\u5f84\uff0c\u518d\u8fdb\u884c\u52a0\u8f7d\u5c31\u53ef\u4ee5\u4e86\u3002\u4e0a\u6587\u4e2d getPath \u65b9\u6cd5\u4f5c\u4e3a\u89e3\u51b3\u529e\u6cd5\u7684\u793a\u4f8b\u53ef\u4ee5\u53c2\u8003\uff1aSystem.load() \u51fd\u6570\u8f93\u5165\u7684\u8def\u5f84\u5fc5\u987b\u662f\u5168\u8def\u5f84\u4e0b\u7684\u6587\u4ef6\u540d\uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528 System.loadLibrary() \u52a0\u8f7d java.library.path \u4e0b\u7684lib\u5e93\uff0c\u4e0d\u9700\u8981 lib \u6587\u4ef6\u7684\u540e\u7f00\u3002<\/p>\n<p>\u4fdd\u5b58\u4e0a\u6587\u7684 Java \u4ee3\u7801\uff0c\u901a\u8fc7 Javah \u6307\u4ee4\u53ef\u4ee5\u751f\u6210\u5bf9\u5e94\u7684 C++ \u5934\u6587\u4ef6\uff0c\u524d\u6587\u76ee\u5f55\u7ed3\u6784\u4e2d\u7684 export_jni.h \u5c31\u662f\u901a\u8fc7\u8be5\u6307\u4ee4\u751f\u6210\u7684\u3002<\/p>\n<pre><code>javah -jni -encoding utf-8 -classpath com.vivo.demo.model.ModelComputer -o ..\/cpp\/extern_jni.h\n# -classpath \u8868\u793a\u6240\u5728\u7684package\n# -d \u8868\u793a\u8f93\u51fa\u7684\u6587\u4ef6\u540d<\/code><\/pre>\n<p>\u6253\u5f00\u53ef\u4ee5\u770b\u5230\u751f\u6210\u51fa\u6765\u7684\u6587\u4ef6\u5982\u4e0b\uff1a<\/p>\n<pre><code>#include &lt;jni.h&gt;  \/\/ \u5f15\u5165\u7684\u5934\u6587\u4ef6\uff0c \u8be5\u5934\u6587\u4ef6\u5728 $JAVA_HOME\/include \u4e0b\uff0c\u968fJava\u7248\u672c\u53d8\u5316\u800c\u6539\u53d8\n#ifndef _Included_com_vivo_demo_model_ModelComputer \/\/ \u5b8f\u5b9a\u4e49 \u683c\u5f0f _Included_\u5305\u540d_\u7c7b\u540d\n#define _Included_com_vivo_demo_model_ModelComputer\n#ifdef __cplusplus\nextern &quot;C&quot; {  \/\/ \u4fdd\u8bc1\u51fd\u6570\u3001\u53d8\u91cf\u3001\u679a\u4e3e\u7b49\u5728\u6240\u6709\u7684\u6e90\u6587\u4ef6\u4e2d\u4fdd\u6301\u4e00\u81f4\uff0c\u8fd9\u91cc\u5e94\u7528\u4e8e\u5bfc\u51fa\u7684\u51fd\u6570\u540d\u79f0\u4e0d\u88ab\u6539\u53d8\n#endif\n\/\/ \u751f\u6210\u7684loadModel\u51fd\u6570\uff0c\u53ef\u4ee5\u770b\u5230JNI\u7684\u4fee\u9970\u548cjlong\u8fd4\u56de\u503c\uff0c\u51fd\u6570\u540d\u79f0\u683c\u5f0f\u4e3a Java_\u5305\u540d_\u7c7b\u540d_\u51fd\u6570\u540d\n\/\/ \u51fd\u6570\u7684\u524d\u4e24\u4e2a\u53c2\u6570\u662f JNIEnv \u8868\u793a\u5f53\u524d\u7ebf\u7a0b\u7684 JVM \u73af\u5883\u53c2\u6570\uff0cjclass \u8868\u793a\u8c03\u7528\u7684 class \u5bf9\u8c61\uff0c\u53ef\u4ee5\u901a\u8fc7\u8fd9\u4e24\u4e2a\u53c2\u6570\u53bb\u64cd\u4f5c Java \u5bf9\u8c61\u3002\nJNIEXPORT jlong JNICALL Java_com_vivo_demo_model_ModelComputer_loadModel\n  (JNIEnv *, jclass, jstring);\n \nJNIEXPORT void JNICALL Java_com_vivo_demo_model_ModelComputer_close\n  (JNIEnv *, jclass, jlong);\n \nJNIEXPORT jfloat JNICALL Java_com_vivo_demo_model_ModelComputer_compute\n  (JNIEnv *, jclass, jlong, jlongArray);\n \n#ifdef __cplusplus\n}\n#endif\n#endif<\/code><\/pre>\n<ul>\n<li><strong>\u8e29\u57512\uff1aJavah \u8fd0\u884c\u5931\u8d25<\/strong><\/li>\n<\/ul>\n<p>\u5982\u679c\u751f\u6210\u5931\u8d25\uff0c\u53ef\u4ee5\u53c2\u8003\u4e0a\u9762 JNI \u683c\u5f0f\u7684 \u201c.h\u201d \u6587\u4ef6\u624b\u5199\u4e00\u4e2a\u51fa\u6765\uff0c\u53ea\u8981\u683c\u5f0f\u65e0\u8bef\uff0c\u6548\u679c\u662f\u4e00\u6837\u7684\u3002\u5176\u4e2d jni.h \u662f JDK \u8def\u5f84\u4e0b\u7684\u4e00\u4e2a\u6587\u4ef6\uff0c\u91cc\u9762\u5b9a\u4e49\u4e86\u4e00\u4e9b JNI \u7684\u7c7b\u578b\uff0c\u8fd4\u56de\u503c\uff0c \u5f02\u5e38\uff0c JavaVM \u7ed3\u6784\u4f53\u4ee5\u53ca\u4e00\u4e9b\u65b9\u6cd5\uff08\u7c7b\u578b\u8f6c\u5316\uff0c\u5b57\u6bb5\u83b7\u53d6\uff0cJVM \u4fe1\u606f\u83b7\u53d6\u7b49\uff09\u3002jni.h \u8fd8\u4f9d\u8d56\u4e86\u4e00\u4e2a jni_md.h \u6587\u4ef6\uff0c\u5176\u4e2d\u5b9a\u4e49\u4e86 jbyte\uff0cjint \u548c jlong\uff0c\u8fd9\u4e09\u4e2a\u7c7b\u578b\u5728\u4e0d\u540c\u7684\u673a\u5668\u4e0b\u7684\u5b9a\u4e49\u662f\u6709\u5dee\u5f02\u7684\u3002<\/p>\n<p>\u6211\u4eec\u53ef\u4ee5\u770b\u4e0b JNI \u5e38\u7528\u6570\u636e\u7c7b\u578b\u4e0e Java \u7684\u5bf9\u5e94\u5173\u7cfb\uff1a<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042329700\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u56fe3 JNI\u5e38\u7528\u6570\u636e\u7c7b\u578b<\/p>\n<p>\u5982\u56fe3\uff0cJNI \u5b9a\u4e49\u4e86\u4e00\u4e9b\u57fa\u672c\u6570\u636e\u7c7b\u578b\u548c\u5f15\u7528\u6570\u636e\u7c7b\u578b\uff0c\u53ef\u4ee5\u5b8c\u6210 Java \u548c C++ \u7684\u6570\u636e\u8f6c\u5316\u3002JNIEnv \u662f\u4e00\u4e2a\u6307\u5411\u672c\u5730\u7ebf\u7a0b\u6570\u636e\u7684\u63a5\u53e3\u6307\u9488\uff0c\u901a\u4fd7\u7684\u6765\u8bb2\uff0c\u6211\u4eec\u901a\u8fc7 JNIEnv \u4e2d\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5b8c\u6210 Java \u548c C++ \u7684\u6570\u636e\u8f6c\u5316\uff0c\u901a\u8fc7\u5b83\uff0c\u53ef\u4ee5\u4f7f C++ \u8bbf\u95ee Java \u7684\u5806\u5185\u5b58\u3002<\/p>\n<p>\u5bf9\u4e8e\u57fa\u672c\u7684\u6570\u636e\u7c7b\u578b\uff0c\u901a\u8fc7\u503c\u4f20\u9012\uff0c\u53ef\u4ee5\u8fdb\u884c\u5f3a\u5236\u8f6c\u5316\uff0c\u53ef\u4ee5\u7406\u89e3\u4e3a\u53ea\u662f\u5b9a\u4e49\u7684\u540d\u79f0\u53d1\u751f\u6539\u53d8\uff0c\u548c java \u57fa\u672c\u6570\u636e\u7c7b\u578b\u5dee\u5f02\u4e0d\u5927\u3002<\/p>\n<p>\u800c\u5f15\u7528\u6570\u636e\u7c7b\u578b\uff0cJNI \u5b9a\u4e49\u4e86 Object \u7c7b\u578b\u7684\u5f15\u7528\uff0c\u90a3\u4e48\u5c31\u610f\u5473\u7740\uff0cjava \u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u4efb\u610f\u5bf9\u8c61\u5230 C++ \u4e2d\u3002\u5bf9\u4e8e\u50cf\u57fa\u7840\u7c7b\u578b\u7684\u6570\u7ec4\u548c string \u7c7b\u578b\uff0c\u5982\u679c\u901a\u8fc7\u5f15\u7528\u4f20\u9012\uff0c\u90a3\u4e48 C++ \u5c31\u8981\u8bbf\u95ee Java \u7684\u5806\u5185\u5b58\uff0c\u901a\u8fc7 JNIEnv \u4e2d\u7684\u65b9\u6cd5\u6765\u8bbf\u95ee Java \u5bf9\u8c61\uff0c\u867d\u7136\u4e0d\u9700\u8981\u6211\u4eec\u5173\u5fc3\u5177\u4f53\u903b\u8f91\uff0c\u4f46\u662f\u5176\u6027\u80fd\u6d88\u8017\u8981\u9ad8\u4e8e C++ \u6307\u9488\u64cd\u4f5c\u5bf9\u8c61\u7684\u3002\u6240\u4ee5 JNI \u5c06\u6570\u7ec4\u548c string \u590d\u5236\u5230\u672c\u5730\u5185\u5b58\uff08\u7f13\u51b2\u533a\uff09\u4e2d\uff0c\u8fd9\u6837\u4e0d\u4f46\u63d0\u9ad8\u4e86\u8bbf\u95ee\u901f\u5ea6\uff0c\u8fd8\u51cf\u8f7b\u4e86 GC \u7684\u538b\u529b\uff0c\u7f3a\u70b9\u5c31\u662f\u9700\u8981\u4f7f\u7528 JNI \u63d0\u4f9b\u7684\u65b9\u6cd5\u8fdb\u884c\u521b\u5efa\u548c\u91ca\u653e\u3002<\/p>\n<pre><code>\/\/ \u53ef\u4ee5\u4f7f\u7528\u4e0b\u5217\u4e09\u7ec4\u51fd\u6570\uff0c\u5176\u4e2d tpye \u4e3a\u57fa\u672c\u6570\u636e\u7c7b\u578b,\u540e\u4e24\u7ec4\u6709 Get \u548c Release \u65b9\u6cd5\uff0cRelease \u65b9\u6cd5\u7684\u4f5c\u7528\u662f\u63d0\u9192 JVM \u91ca\u653e\u5185\u5b58\n\/\/ \u6570\u636e\u91cf\u5c0f\u7684\u65f6\u5019\u4f7f\u7528\u6b64\u65b9\u6cd5\uff0c\u539f\u7406\u662f\u5c06\u6570\u636e\u590d\u5236\u5230C\u7f13\u51b2\u533a\uff0c\u5206\u914d\u5728 C \u5806\u6808\u4e0a\uff0c\u56e0\u6b64\u53ea\u9002\u7528\u4e8e\u5c11\u91cf\u7684\u5143\u7d20\uff0cSet \u64cd\u4f5c\u662f\u5bf9\u7f13\u5b58\u533a\u8fdb\u884c\u4fee\u6539\nGet&lt;type&gt;ArrayRegion\nSet&lt;type&gt;ArrayRegion\n\/\/ \u5c06\u6570\u7ec4\u7684\u5185\u5bb9\u62f7\u8d1d\u5230\u672c\u5730\u5185\u5b58\u4e2d\uff0c\u4f9b C++ \u4f7f\u7528\nGet&lt;type&gt;ArrayElement\nRelease&lt;type&gt;ArrayElement\n\/\/ \u6709\u53ef\u80fd\u76f4\u63a5\u8fd4\u56de JVM \u4e2d\u7684\u6307\u9488\uff0c\u5426\u5219\u7684\u8bdd\u4e5f\u4f1a\u62f7\u8d1d\u4e00\u4e2a\u6570\u7ec4\u51fa\u6765\uff0c\u548c GetArrayElement \u529f\u80fd\u76f8\u540c\nGetPrimitiveArrayCritical\nReleasePrimitiveArrayCritical<\/code><\/pre>\n<p>\u901a\u8fc7\u8fd9\u4e09\u7ec4\u65b9\u6cd5\u7684\u4ecb\u7ecd\uff0c\u4e5f\u5c31\u5927\u81f4\u4e86\u89e3\u4e86 JNI \u7684\u6570\u636e\u7c7b\u578b\u8f6c\u5316\uff0c\u5982\u679c\u6ca1\u6709 C++ \u521b\u5efa\u4fee\u6539 Java Object \u7684\u64cd\u4f5c\u7684\u8bdd\uff0c\u90a3\u7f16\u5199 C++ \u4ee3\u7801\u548c\u6b63\u5e38\u7684 C++ \u5f00\u53d1\u65e0\u5f02\uff0c\u4e0b\u9762\u7ed9\u51fa\u4e86 \u201cexport_jni.h\u201d \u4ee3\u7801\u793a\u4f8b\u3002<\/p>\n<pre><code>#include &quot;jni.h&quot; \/\/ \u8fd9\u91cc\u6539\u4e3a\u76f8\u5bf9\u5f15\u7528\uff0c\u662f\u56e0\u4e3a\u628a jni.h \u548c jni_md.h \u62f7\u8d1d\u5230\u9879\u76ee\u4e2d\uff0c\u65b9\u4fbf\u7f16\u8bd1\n#include &quot;computer.cc&quot;\n#ifndef _Included_com_vivo_demo_model_ModelComputer\n#define _Included_com_vivo_demo_model_ModelComputer\n#ifdef __cplusplus\nextern &quot;C&quot; {\n#endif\n    JNIEXPORT jlong JNICALL Java_com_vivo_demo_model_ModelComputer_loadModel\n    (JNIEnv* env, jclass clazz, jstring path) {\n        vivo::Computer* ptr = new vivo::Computer();\n        const char* cpath = env-&gt;GetStringUTFChars(path, 0); \/\/ \u5c06 String \u8f6c\u4e3a char*\n        ptr-&gt;init_model(cpath);\n        env-&gt;ReleaseStringUTFChars(path, cpath); \/\/ \u91ca\u653eString\n        return (long)ptr;\n    };\n \n    JNIEXPORT void JNICALL Java_com_vivo_demo_model_ModelComputer_close\n    (JNIEnv* env, jclass clazz, jlong ptr) {\n        vivo::Computer* computer = (vivo::Computer*)ptr; \/\/ \u83b7\u53d6\u5230\u5bf9\u8c61\n        delete computer; \/\/ \u5220\u9664\u5bf9\u8c61\n    };\n \n    JNIEXPORT jfloat JNICALL Java_com_vivo_demo_model_ModelComputer_compute\n    (JNIEnv* env, jclass clazz, jlong ptr, jlongArray array) {\n        jlong* idx_ptr = env-&gt;GetLongArrayElements(array, NULL); \/\/ \u5c06 array \u8f6c\u4e3a jlong*\n        vivo::Computer* computer = (vivo::Computer*)ptr; \/\/ \u83b7\u53d6\u5230 C++ \u5bf9\u8c61\n        float result = computer-&gt;compute((long *)idx_ptr); \/\/ \u6267\u884c C++ \u65b9\u6cd5\n        env-&gt;ReleaseLongArrayElements(array, idx_ptr, 0); \/\/ \u91ca\u653e array\n        return result; \/\/ \u8fd4\u56de\u7ed3\u679c\n    };\n \n#ifdef __cplusplus\n}\n#endif\n#endif<\/code><\/pre>\n<p>C++ \u4ee3\u7801\u7f16\u8bd1\u5b8c\u6210\u540e\uff0c\u628a lib \u6587\u4ef6\u653e\u5230 resource \u76ee\u5f55\u6307\u5b9a\u4f4d\u7f6e\uff0c\u5982\u679c\u4e3a\u4e86\u65b9\u4fbf\uff0c\u53ef\u4ee5\u5199\u4e2a shell \u811a\u672c\u4e00\u952e\u6267\u884c\u3002<\/p>\n<ul>\n<li><strong>\u8e29\u57513\uff1a\u670d\u52a1\u5668\u542f\u52a8\u65f6\u62a5java.lang.UnsatisfiedLinkError \u5f02\u5e38<\/strong><\/li>\n<\/ul>\n<blockquote><p>\u53c8\u662f\u8fd9\u4e2a\u5f02\u5e38\uff0c\u524d\u6587\u5df2\u7ecf\u4ecb\u7ecd\u4e86\u4e00\u79cd\u89e3\u51b3\u65b9\u6848\uff0c\u4f46\u5728\u5b9e\u9645\u5e94\u7528\u4e2d\u4ecd\u7136\u9891\u7e41\u51fa\u73b0\uff0c\u6bd4\u5982\uff1a<\/p><\/blockquote>\n<ol>\n<li>\u8fd0\u884c\u73af\u5883\u6709\u95ee\u9898\uff08\u6bd4\u5982\u5728 linux \u4e0b\u7f16\u8bd1\u5728 windows \u4e0a\u8fd0\u884c\uff0c\u8fd9\u662f\u4e0d\u53ef\u4ee5\u7684\uff09\uff1b<\/li>\n<li>JVM \u4f4d\u6570\u548c lib \u7684\u4f4d\u6570\u4e0d\u4e00\u81f4 \uff08\u6bd4\u5982\u4e00\u4e2a\u662f 32 \u4f4d\uff0c\u4e00\u4e2a\u662f 64 \u4f4d\uff09\uff1b<\/li>\n<li>C++ \u51fd\u6570\u540d\u5199\u9519\uff1b<\/li>\n<li>\u751f\u6210\u7684 lib \u6587\u4ef6\u4e2d\u5e76\u6ca1\u6709\u76f8\u5bf9\u5e94\u7684\u65b9\u6cd5\u3002<\/li>\n<\/ol>\n<p>\u5bf9\u4e8e\u8fd9\u4e9b\u95ee\u9898\uff0c\u53ea\u8981\u8ba4\u771f\u5206\u6790\u5f02\u5e38\u65e5\u5fd7\uff0c\u4fbf\u53ef\u4ee5\u9010\u4e00\u89e3\u51b3\uff0c\u4e5f\u6709\u5de5\u5177\u53ef\u4ee5\u534f\u52a9\u6211\u4eec\u89e3\u51b3\u95ee\u9898\u3002<\/p>\n<p><strong>\u4f7f\u7528 dumpbin\/objdump \u5206\u6790 lib\uff0c\u66f4\u5feb\u901f\u5730\u89e3\u51b3 UnsatisfiedLinkError\u3002<\/strong><\/p>\n<p>\u5bf9\u4e8e lib \u5e93\u4e2d\u7684\u51fd\u6570\u68c0\u67e5\uff0c\u4e0d\u540c\u64cd\u4f5c\u7cfb\u7edf\u4e5f\u63d0\u4f9b\u4e86\u4e0d\u540c\u7684\u5de5\u5177\u3002<\/p>\n<p>\u5728 windows \u4e0b\uff0c\u53ef\u4ee5\u4f7f\u7528 dumpbin \u5de5\u5177\u6216\u8005 Dependency Walker \u5de5\u5177\u5206\u6790 lib \u4e2d\u662f\u5426\u5b58\u5728\u6240\u7f16\u5199\u7684 C++ \u65b9\u6cd5\u3002dumpbin \u6307\u4ee4\u5982\u4e0b\uff1a<\/p>\n<pre><code>dumpbin \/EXPORTS xxx.dll<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042329701\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u56fe4 dumpbin \u67e5\u770b dll \u6587\u4ef6<\/p>\n<p>\u800c Dependency Walker \u53ea\u9700\u8981\u6253\u5f00 dll \u6587\u4ef6\u5c31\u53ef\u4ee5\u770b\u5230\u76f8\u5173\u4fe1\u606f\u4e86\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042329702\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u56fe5 Dependency Walker \u67e5\u770b dll \u6587\u4ef6<\/p>\n<p>\u5728 Linux \u4e0b\uff0c\u53ef\u4ee5\u4f7f\u7528 objdump \u5de5\u5177\u5206\u6790 so \u6587\u4ef6\u4e2d\u7684\u4fe1\u606f\u3002<\/p>\n<p>objdump \u6307\u4ee4\u5982\u4e0b\uff1a<\/p>\n<pre><code>objdump -t xxx.so<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042329703\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u56fe6 objdump \u67e5\u770b so \u6587\u4ef6<\/p>\n<h3>3.4 \u6027\u80fd\u5206\u6790<\/h3>\n<p>\u6839\u636e\u4e4b\u524d\u7684\u8c03\u7814\uff0c\u6211\u4eec\u6ce8\u610f\u5230 Java \u5bf9 native \u65b9\u6cd5\u7684\u8c03\u7528\u672c\u8eab\u4e5f\u5b58\u5728\u989d\u5916\u6027\u80fd\u5f00\u9500\uff0c\u9488\u5bf9\u6b64\u6211\u4eec\u7528 JMH \u8fdb\u884c\u4e86\u7b80\u5355\u6d4b\u8bd5\u3002\u56fe 7 \u5c55\u793a\u7684\u662f JNI \u7a7a\u65b9\u6cd5\u8c03\u7528\u548c Java \u7684\u5bf9\u6bd4\uff1a<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042329704\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u56fe7 &#8211; \u7a7a\u51fd\u6570\u8c03\u7528\u5bf9\u6bd4 \uff08\u6570\u636e\u6e90\u81ea\u4e2a\u4eba\u673a\u5668JMH\u6d4b\u8bd5\uff0c\u4ec5\u4f9b\u53c2\u8003\uff09<\/p>\n<p>\u5176\u4e2d JmhTest.code \u4e3a\u8c03\u7528 native \u7a7a\u65b9\u6cd5\uff0c JmhTest.jcode \u4e3a\u8c03\u7528 java \u7a7a\u65b9\u6cd5\uff0c\u4ece\u4e2d\u53ef\u4ee5\u770b\u51fa\uff0c\u76f4\u63a5\u8c03\u7528 java \u7684\u65b9\u6cd5\u8981\u6bd4\u8c03\u7528 native \u65b9\u6cd5\u5feb\u5341\u500d\u8fd8\u8981\u591a\u3002\u6211\u4eec\u5bf9\u5806\u6808\u8c03\u7528\u8fdb\u884c\u4e86\u7b80\u5355\u5206\u6790\uff0c\u53d1\u73b0\u8c03\u7528 native \u7684\u8fc7\u7a0b\u6bd4\u76f4\u63a5\u8c03\u7528 java \u65b9\u6cd5\u8981\u7e41\u7410\u4e00\u4e9b\uff0c\u8fdb\u5165\u4e86 ClassLoad \u7684 findNative \u65b9\u6cd5\u3002<\/p>\n<pre><code>\/\/ Invoked in the VM class linking code.\n\/\/ loader \u4e3a\u7c7b\u52a0\u8f7d\u5668\uff0c name \u4e3aC++\u65b9\u6cd5\u7684 name\uff0ceg: Java_com_vivo_demo_model_ModelComputer_compute\nstatic long findNative(ClassLoader loader, String name) {\n    \/\/ \u9009\u62e9 nativeLibary   \n    Vector&lt;NativeLibrary&gt; libs =\n        loader != null ? loader.nativeLibraries : systemNativeLibraries;\n    synchronized (libs) {\n        int size = libs.size();\n        for (int i = 0; i &lt; size; i++) {\n            NativeLibrary lib = libs.elementAt(i);\n            \/\/ \u627e\u5230 name \u6301\u6709\u7684 handel\n            long entry = lib.find(name); \n            if (entry != 0)\n                \/\/ \u8fd4\u56de handel\n                return entry;\n        }\n    }\n    return 0;\n}<\/code><\/pre>\n<p>\u5806\u6808\u4fe1\u606f\u5982\u4e0b\uff1a<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042329705\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u56fe8 \u8c03\u7528 native \u5806\u6808\u4fe1\u606f<\/p>\n<p>find \u65b9\u6cd5\u662f\u4e00\u4e2a native \u65b9\u6cd5\uff0c\u5806\u6808\u4e0a\u4e5f\u6253\u5370\u4e0d\u51fa\u76f8\u5173\u4fe1\u606f\uff0c\u4f46\u4e0d\u96be\u5f97\u51fa\uff0c\u901a\u8fc7 find \u65b9\u6cd5\u53bb\u8c03\u7528 lib \u5e93\u4e2d\u7684\u65b9\u6cd5\uff0c\u8fd8\u8981\u518d\u7ecf\u8fc7\u81f3\u5c11\u4e00\u8f6e\u7684\u6620\u5c04\u624d\u80fd\u627e\u5230\u5bf9\u5e94\u7684 C++ \u51fd\u6570\u6267\u884c\uff0c\u7136\u540e\u5c06\u7ed3\u679c\u8fd4\u56de\u3002\u77ac\u95f4\u56de\u60f3\u8d77\u56fe\u4e00\uff0c\u8fd9\u79cd\u8c03\u7528\u94fe\u8def\uff0c\u901a\u8fc7 Native Interface \u6765\u4e32\u8d77\u672c\u5730\u65b9\u6cd5\u6808\uff0c\u865a\u62df\u673a\u6808\uff0cnativeLibrary \u548c\u6267\u884c\u5f15\u64ce\u4e4b\u95f4\u7684\u5173\u7cfb\uff0c\u903b\u8f91\u52bf\u5fc5\u4f1a\u590d\u6742\u4e00\u4e9b\uff0c\u76f8\u5bf9\u7684\u8c03\u7528\u8017\u65f6\u4e5f\u4f1a\u589e\u52a0\u3002<\/p>\n<p>\u505a\u4e86\u8fd9\u4e48\u591a\u5de5\u4f5c\uff0c\u5dee\u70b9\u5fd8\u4e86\u6211\u4eec\u7684\u76ee\u6807\uff1a\u63d0\u9ad8\u6211\u4eec\u7684\u8ba1\u7b97\u548c\u52a0\u8f7d\u901f\u5ea6\u3002\u7ecf\u8fc7\u4e0a\u6587\u7684\u4f18\u5316\u540e\uff0c\u6211\u4eec\u5728\u538b\u6d4b\u73af\u5883\u8fdb\u884c\u4e86\u5168\u94fe\u8def\u538b\u6d4b\uff0c\u53d1\u73b0\u5373\u4f7f native \u7684\u8c03\u7528\u5b58\u5728\u989d\u5916\u5f00\u9500\uff0c\u5168\u94fe\u8def\u7684\u6027\u80fd\u4ecd\u7136\u6709\u4e86\u8f83\u4e3a\u660e\u663e\u7684\u63d0\u5347\u3002<\/p>\n<p>\u6211\u4eec\u7684\u670d\u52a1\u5728\u6a21\u578b\u63a8\u7406\u7684\u6838\u5fc3\u8ba1\u7b97\u4e0a\u8017\u65f6\u964d\u4f4e\u4e86 80%\uff0c\u52a0\u8f7d\u548c\u89e3\u6790\u6a21\u578b\u6587\u4ef6\u8017\u65f6\u4e5f\u964d\u4f4e\u4e86 60%\uff08\u5206\u949f\u7ea7\u5230\u79d2\u7ea7\uff09\uff0cGC \u7684\u5e73\u5747\u8017\u65f6\u4e5f\u964d\u4f4e\u4e86 30%\uff0c\u6574\u4f53\u7684\u6536\u76ca\u975e\u5e38\u660e\u663e\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042329706\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u56fe9 young GC \u8017\u65f6\u5bf9\u6bd4<\/p>\n<h2>\u56db\u3001\u601d\u8003\u548c\u603b\u7ed3\uff1aJNI \u5e26\u6765\u7684\u6536\u76ca<\/h2>\n<p>JNI \u5728\u4e00\u4e9b\u7279\u5b9a\u573a\u666f\u4e0b\u7684\u6210\u529f\u5e94\u7528\u6253\u5f00\u4e86\u6211\u4eec\u7684\u4f18\u5316\u601d\u8def\uff0c\u5c24\u5176\u662f\u5728 Java \u4e0a\u8fdb\u884c\u4e86\u8f83\u591a\u4f18\u5316\u5c1d\u8bd5\u540e\u5e76\u6ca1\u6709\u8fdb\u5c55\u65f6\uff0cJNI \u786e\u5b9e\u503c\u5f97\u4e00\u8bd5\u3002<\/p>\n<p>\u53c8\u56de\u5230\u4e86\u6700\u521d\u7684\u95ee\u9898\uff1aJNI \u771f\u7684\u597d\u7528\u5417\uff1f\u6211\u7684\u7b54\u6848\u662f\uff1a\u5b83\u5e76\u4e0d\u662f\u5f88\u597d\u7528\u3002\u5982\u679c\u662f\u4e00\u540d\u5f88\u5c11\u63a5\u89e6 C++ \u7f16\u7a0b\u7684\u5de5\u7a0b\u5e08\uff0c\u90a3\u4e48\u5728\u7b2c\u4e00\u6b65\u7684\u73af\u5883\u642d\u5efa\u548c\u7f16\u8bd1\u4e0a\uff0c\u5c31\u8981\u8017\u8d39\u5927\u91cf\u7684\u65f6\u95f4\uff0c\u518d\u5230\u540e\u7eed\u7684\u4ee3\u7801\u7ef4\u62a4\uff0cC++ \u8c03\u4f18\u7b49\u7b49\uff0c\u662f\u4e00\u4e2a\u975e\u5e38\u5934\u75bc\u7684\u4e8b\u60c5\u3002\u4f46\u6211\u8fd8\u662f\u975e\u5e38\u63a8\u8350\u53bb\u4e86\u89e3\u8fd9\u9879\u6280\u672f\u548c\u8fd9\u9879\u6280\u672f\u7684\u5e94\u7528\uff0c\u53bb\u601d\u8003\u8fd9\u9879\u6280\u672f\u80fd\u591f\u7ed9\u81ea\u5df1\u7684\u670d\u52a1\u5668\u6027\u80fd\u5e26\u6765\u63d0\u5347\u3002<\/p>\n<p>\u6216\u8bb8\u6709\u4e00\u5929\uff0cJNI \u80fd\u4e3a\u4f60\u6240\u7528\uff01<\/p>\n<p>\u53c2\u8003\u8d44\u6599\uff1a<\/p>\n<ol>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=cMJ3rijtDc%2BsrTHo7rRacw%3D%3D.TsU4900W0%2FM%2BCNm7O1o7bH9kz7RYppGX48mduYTwNDXJkosyRiR6sUB4smwmEnfi3vAbQJdpN0nTmJgHIX5RTA%3D%3D\" rel=\"nofollow\">Oracle JNI Guide: Java Native Interface<\/a><\/li>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=yipMiITdbtFVzqs2Pe6hag%3D%3D.rSl2rE%2F1MLgsQGtd0hwarHzrbR94XtzbPpQZKon6KvPhTbllG%2F8AKNv3WgLZb%2BiuAmvYdpEEbJt9RpXs1%2BPPFg%3D%3D\" rel=\"nofollow\">bazel \u6982\u8ff0<\/a><\/li>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=xxqzINAzXo%2Bx4Ac6rcGV4g%3D%3D.gVfXWqmfC7eR8w8kaI8nythJhqLcYvgsUPiKUl21D9E%3D\" rel=\"nofollow\">docker hub<\/a><\/li>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=yMdFnVUVUvpQJhShiuN9gg%3D%3D.cBoGe8vqjD4wMe7BOwH9XdstZHWnTnLVksPmHEI%2F6YM%3D\" rel=\"nofollow\">JMH GitHub<\/a><\/li>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=WntOxWXZktAC3DTwQBxgXg%3D%3D.W14kx%2F8q7n00ImLzMTWNGkJIYj0x60wL7u74pdUeUigIwFZZDFA3PPCU3AtW%2FOIxUnYT6A2uzQwoU94VIt6u4PhlP6Y3EnltDCB2gg3YOu4%3D\" rel=\"nofollow\">Dumpbin refrence<\/a><\/li>\n<\/ol>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000042329696\">https:\/\/segmentfault.com\/a\/1190000042329696<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u4f5c\u8005\uff1avivo \u4e92\u8054\u7f51\u670d\u52a1\u5668\u56e2\u961f- Wei Qianzi\u3001Li Haoxuan \u5728 Java \u53d1\u5c55\u5386\u7a0b\u4e2d\uff0cJN [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[],"tags":[],"class_list":["post-10006277","post","type-post","status-publish","format-standard","hentry"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006277","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006277"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006277\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006277"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006277"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006277"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}