{"id":655,"date":"2025-10-14T01:37:21","date_gmt":"2025-10-14T01:37:21","guid":{"rendered":"https:\/\/boochlin.com\/?p=655"},"modified":"2026-09-20T16:08:46","modified_gmt":"2026-09-20T16:08:46","slug":"inline-noinline-crossinline%ef%bc%9a%e5%ad%98%e5%9c%a8%e5%8d%b3%e5%90%88%e7%90%86","status":"publish","type":"post","link":"https:\/\/boochlin.com\/?p=655","title":{"rendered":"inline, noinline, crossinline\uff1a\u5b58\u5728\u5373\u5408\u7406"},"content":{"rendered":"<blockquote>\n<p><strong>\u300cKotlin \u7de8\u8b6f\u5668\u5718\u968a\u7d55\u5c0d\u4e0d\u662f\u5403\u98fd\u592a\u9592\uff0c\u624d\u767c\u660e <code>inline<\/code>\u3001<code>noinline<\/code>\u3001<code>crossinline<\/code> \u9019\u4e09\u500b\u9577\u5f97\u5f88\u50cf\u7684\u4fee\u98fe\u7b26\u4f86\u6298\u78e8\u9762\u8a66\u8005\u3002\u6bcf\u4e00\u500b\u95dc\u9375\u5b57\u7684\u80cc\u5f8c\uff0c\u90fd\u662f JVM \u5806\u7a4d\u8a18\u61b6\u9ad4\uff08Heap\uff09\u8d64\u5b57\u3001Bytecode \u6307\u4ee4\u5c55\u958b\u8207\u547c\u53eb\u5806\u758a\uff08Stack Frame\uff09\u7269\u7406\u9650\u5236\u7684\u8840\u6dda\u4ee3\u50f9\u3002\u300d<\/strong><\/p>\n<\/blockquote>\n<p><img decoding=\"async\" src=\"https:\/\/boochlin.com\/wp-content\/uploads\/2026\/09\/post_655_featured_opt-300x300.webp\" alt=\"\"><\/p>\n<p>\u6bcf\u6b21\u5728 Code Review \u770b\u5230\u6709\u5f8c\u8f29\u628a\u6240\u6709\u9ad8\u968e\u51fd\u5f0f\u7121\u8166\u52a0\u4e0a <code>inline<\/code>\uff0c\u6216\u8005\u56e0\u70ba\u7de8\u8b6f\u5668\u8df3\u51fa <code>Illegal usage of inline-parameter<\/code> \u5c31\u96a8\u624b\u6309 IDE \u7684 Quick-Fix \u52a0\u4e0a <code>noinline<\/code>\u3001<code>crossinline<\/code>\uff0c\u554f\u4ed6\u70ba\u4ec0\u9ebc\u8981\u52a0\uff0c\u4ed6\u6293\u6293\u982d\u56de\u6211\u4e00\u53e5\u300c\u9019\u6a23\u7de8\u8b6f\u5c31\u6703\u904e\u554a\u300d\uff0c\u6211\u7684\u8840\u58d3\u5927\u6982\u5c31\u6703\u77ac\u9593\u98c6\u7834 160\u3002\uff08\u6c92\u932f\uff0c\u7de8\u8b6f\u6703\u904e\uff0c\u4f46\u4f60\u7522\u51fa\u7684\u4f4d\u5143\u7d44\u78bc\u6b63\u5728\u5077\u5077\u8b00\u6bba CPU \u5feb\u53d6\u548c\u8a18\u61b6\u9ad4\uff09\u3002<\/p>\n<p>Kotlin \u7684\u9ad8\u968e\u51fd\u5f0f\uff08Higher-Order Functions\uff09\u8207 Lambda \u8a9e\u6cd5\u6975\u5176\u512a\u96c5\uff0c\u5ba3\u544a\u5f0f\u5beb\u6cd5\u8b93\u4eba\u6b32\u7f77\u4e0d\u80fd\u3002\u4f46 Java \u865b\u64ec\u6a5f\u5668\uff08JVM\uff09\u6700\u521d\u6839\u672c\u6c92\u6709 Lambda \u9019\u7a2e\u4e00\u7b49\u516c\u6c11\u3002Kotlin \u5728 JVM 6\/8 \u4e0a\u80fd\u8dd1 Lambda\uff0c\u5168\u9760\u7de8\u8b6f\u5668\u5728\u80cc\u5f8c\u5077\u5929\u63db\u65e5\u3002<\/p>\n<p>\u98db\u6a5f\u8d77\u98db\u524d\u5148\u88dd\u5100\u8868\u677f\u3002\u8981\u5fb9\u5e95\u770b\u61c2\u9019\u4e09\u500b\u95dc\u9375\u5b57\uff0c\u4e0d\u8981\u770b\u5b98\u65b9\u6587\u4ef6\u90a3\u4e9b\u62bd\u8c61\u7684\u8a9e\u610f\u63cf\u8ff0\u3002\u6211\u5011\u76f4\u63a5\u628a Bytecode \u812b\u5149\uff0c\u4e0b\u6f5b\u5230 JVM \u5806\u758a\u8207 ART \u8a18\u61b6\u9ad4\u5206\u914d\u5668\uff08ART Allocator\uff09\u7684\u6700\u5e95\u5c64\u3002<\/p>\n<hr>\n<h2>\u6839\u6e90\u554f\u984c\uff1a\u512a\u96c5\u7684 Lambda\uff0c\u5728 JVM \u5e95\u5c64\u6709\u591a\u6c89\u91cd\uff1f<\/h2>\n<p>\u7576\u6211\u5011\u5728 Kotlin \u5beb\u4e0b\u4e00\u500b\u6700\u6a19\u6e96\u7684\u9ad8\u968e\u51fd\u5f0f\u6642\uff1a<\/p>\n<pre><code class=\"hljs language-kotlin\"><span class=\"hljs-comment\">\/\/ \u4e00\u822c\u9ad8\u968e\u51fd\u5f0f<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">calculate<\/span><span class=\"hljs-params\">(a: <span class=\"hljs-type\">Int<\/span>, b: <span class=\"hljs-type\">Int<\/span>, operation: (<span class=\"hljs-type\">Int<\/span>, <span class=\"hljs-type\">Int<\/span>) -&gt; <span class=\"hljs-type\">Int<\/span>)<\/span><\/span>: <span class=\"hljs-built_in\">Int<\/span> {\n    <span class=\"hljs-keyword\">return<\/span> operation(a, b)\n}\n\n<span class=\"hljs-comment\">\/\/ \u547c\u53eb\u7aef<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">test<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n    <span class=\"hljs-keyword\">val<\/span> result = calculate(<span class=\"hljs-number\">10<\/span>, <span class=\"hljs-number\">20<\/span>) { x, y -&gt; x + y }\n}<\/code><\/pre>\n<p>\u8868\u9762\u4e0a\u770b\u8d77\u4f86\u4e7e\u6de8\u4fd0\u843d\uff0c\u4f46\u53ea\u8981\u6211\u5011\u628a\u9019\u6bb5\u7a0b\u5f0f\u78bc\u53cd\u7de8\u8b6f\uff08Decompile\uff09\u6210 JVM \u4f4d\u5143\u7d44\u78bc\uff08Bytecode\uff09\uff0c\u5e95\u5c64\u7684\u771f\u5be6\u6a23\u8c8c\u6703\u8b93\u6240\u6709\u5c0d\u6548\u80fd\u654f\u611f\u7684\u5de5\u7a0b\u5e2b\u5012\u62bd\u4e00\u53e3\u6c23\uff1a<\/p>\n<pre><code class=\"hljs language-plaintext\">\/\/ \u547c\u53eb\u7aef test() \u7684\u771f\u5be6 Bytecode\nNEW com\/example\/MathHelper$test$1\nDUP\nINVOKESPECIAL com\/example\/MathHelper$test$1.&lt;init&gt; ()V\nCHECKCAST kotlin\/jvm\/functions\/Function2\nBIPUSH 10\nBIPUSH 20\nINVOKESTATIC com\/example\/MathHelper.calculate (IILkotlin\/jvm\/functions\/Function2;)I<\/code><\/pre>\n<p>\u800c\u5728 <code>calculate<\/code> \u51fd\u5f0f\u5167\u90e8\uff1a<\/p>\n<pre><code class=\"hljs language-plaintext\">ALOAD 2 \/\/ \u8f09\u5165 operation \u5be6\u4f8b\nILOAD 0\nINVOKESTATIC java\/lang\/Integer.valueOf (I)Ljava\/lang\/Integer; \/\/ \u88dd\u7bb1\uff01\nILOAD 1\nINVOKESTATIC java\/lang\/Integer.valueOf (I)Ljava\/lang\/Integer; \/\/ \u88dd\u7bb1\uff01\nINVOKEINTERFACE kotlin\/jvm\/functions\/Function2.invoke (Ljava\/lang\/Object;Ljava\/lang\/Object;)Ljava\/lang\/Object; \/\/ \u4ecb\u9762\u865b\u64ec\u5206\u6d3e\uff01\nCHECKCAST java\/lang\/Number\nINVOKEVIRTUAL java\/lang\/Number.intValue ()I\nIRETURN<\/code><\/pre>\n<h3>\u6b98\u9177\u7684\u8a18\u61b6\u9ad4\u8d64\u5b57\u7b97\u5f0f\uff1a<\/h3>\n<ol>\n<li><strong>\u7269\u4ef6\u982d\uff08Object Header\uff09\u57fa\u672c\u958b\u92b7<\/strong>\uff1a<br \/>\n\u5728 64 \u4f4d\u5143 JVM \u555f\u7528 Compressed OOPs\uff08\u6307\u6a19\u58d3\u7e2e\uff09\u7684\u6a19\u6e96\u74b0\u5883\u4e0b\uff1a<\/p>\n<ul>\n<li>Mark Word\uff1a\u56fa\u5b9a\u4f54\u7528 8 bytes\u3002<\/li>\n<li>Klass Pointer\uff1a\u4f54\u7528 4 bytes\uff08\u82e5\u95dc\u9589\u58d3\u7e2e\u6216 Heap &gt; 32GB \u5247\u70ba 8 bytes\uff09\u3002<\/li>\n<li>\u4e00\u500b\u7a7a\u7269\u4ef6\u7684\u7269\u4ef6\u982d\u672c\u8eab\u5c31\u5403\u6389 <strong>12 bytes<\/strong>\u3002<\/li>\n<\/ul>\n<\/li>\n<li><strong>\u9589\u5305\u64f7\u53d6\uff08Closure Capturing\uff09\u8207\u8a18\u61b6\u9ad4\u5c0d\u9f4a<\/strong>\uff1a<br \/>\n\u5982\u679c Lambda \u5167\u90e8\u64f7\u53d6\u4e86\u5916\u5c64\u5340\u57df\u8b8a\u6578\uff08\u4f8b\u5982\u64f7\u53d6\u4e86 <code>val factor = 2<\/code> \u6216\u67d0\u500b View \u5f15\u7528\uff09\uff0c\u7de8\u8b6f\u5668\u751f\u6210\u7684\u533f\u540d\u985e\u5225\u5fc5\u9808\u65b0\u589e\u6210\u54e1\u6b04\u4f4d\u4f86\u4fdd\u5b58\u9019\u4e9b\u5f15\u7528\uff1a<\/p>\n<ul>\n<li>\u6bcf\u500b\u7269\u4ef6\u5f15\u7528\u6b04\u4f4d\u4f54\u7528 4 bytes\uff08Compressed OOPs\uff09\u3002<\/li>\n<li>JVM \u898f\u7bc4\u8981\u6c42\u7269\u4ef6\u5927\u5c0f\u5fc5\u9808\u4ee5 8 bytes \u5c0d\u9f4a\uff08Alignment Padding\uff09\u3002<\/li>\n<li>12 bytes \u7269\u4ef6\u982d + 4 bytes \u6b04\u4f4d = 16 bytes\u3002\u82e5\u64f7\u53d6\u5169\u500b\u5f15\u7528\uff1a12 + 8 = 20 bytes\uff0c\u5c0d\u9f4a\u5f8c\u76f4\u63a5\u81a8\u8139\u70ba <strong>24 bytes<\/strong>\uff01<\/li>\n<\/ul>\n<\/li>\n<li><strong>\u57fa\u578b\u5225\u88dd\u7bb1\uff08Primitive Boxing\uff09\u96d9\u91cd\u6253\u64ca<\/strong>\uff1a<br \/>\nKotlin \u7684 <code>(Int, Int) -&gt; Int<\/code> \u5c0d\u61c9\u5230 Java \u5e95\u5c64\u662f\u901a\u7528\u7684 <code>Function2&lt;P1, P2, R&gt;<\/code>\uff0c\u5176 <code>invoke<\/code> \u7c3d\u7ae0\u70ba <code>invoke(Object p1, Object p2): Object<\/code>\u3002<br \/>\n\u539f\u751f\u578b\u5225 <code>Int<\/code> \u88ab\u8feb\u547c\u53eb <code>Integer.valueOf()<\/code> \u9032\u884c\u88dd\u7bb1\u3002\u96d6\u7136 JVM \u5c0d -128 \u5230 127 \u505a\u4e86\u5feb\u53d6\uff0c\u4f46\u4e00\u65e6\u6578\u503c\u8d85\u51fa\u5feb\u53d6\u5340\u9593\uff0cHeap \u4e0a\u53c8\u6703\u786c\u751f\u751f\u591a\u51fa\u5169\u500b 16 bytes \u7684 <code>Integer<\/code> \u7269\u4ef6\uff01<\/li>\n<\/ol>\n<h3>\u70ba\u4ec0\u9ebc JVM \/ ART \u7684\u300c\u9003\u9038\u5206\u6790\uff08Escape Analysis\uff09\u300d\u6551\u4e0d\u4e86\u5b83\uff1f<\/h3>\n<p>\u5f88\u591a\u4eba\u6703\u5929\u771f\u5730\u8a8d\u70ba\uff1a\u300c\u73fe\u4ee3 HotSpot C2 \u6216 Android ART JIT \u4e0d\u662f\u6709\u9003\u9038\u5206\u6790\u55ce\uff1f\u96e3\u9053\u4e0d\u80fd\u900f\u904e\u7d14\u91cf\u66ff\u63db\uff08Scalar Replacement\uff09\u628a\u7269\u4ef6\u6253\u6563\u5230\u66ab\u5b58\u5668\u6216\u547c\u53eb\u5806\u758a\u4e0a\uff1f\u300d<\/p>\n<p>\u5927\u932f\u7279\u932f\u3002\u9003\u9038\u5206\u6790\u8981\u751f\u6548\uff0c\u524d\u63d0\u662f JIT \u80fd\u767e\u5206\u4e4b\u767e\u8b49\u660e\u300c\u8a72\u7269\u4ef6\u4e0d\u6703\u9003\u9038\u51fa\u7576\u524d\u65b9\u6cd5\u4f5c\u7528\u57df\u300d\u3002<br \/>\n\u4f46\u5728\u9ad8\u968e\u51fd\u5f0f\u67b6\u69cb\u4e2d\uff1a<\/p>\n<ul>\n<li><strong>\u8de8\u65b9\u6cd5\u908a\u754c\u50b3\u905e<\/strong>\uff1a\u547c\u53eb\u7aef\u628a Lambda \u5be6\u4f8b\u7576\u6210\u53c3\u6578\u50b3\u905e\u9032 <code>calculate<\/code>\uff0c\u5728 JIT \u7684\u9003\u9038\u5206\u6790\u6f14\u7b97\u6cd5\u773c\u88e1\uff0c\u9019\u672c\u8cea\u4e0a\u5c6c\u65bc <code>ArgEscape<\/code>\u3002<\/li>\n<li><strong>\u4ecb\u9762\u865b\u64ec\u5206\u6d3e\uff08<code>INVOKEINTERFACE<\/code>\uff09<\/strong>\uff1a<code>operation.invoke(...)<\/code> \u662f\u4ecb\u9762\u547c\u53eb\u3002\u9762\u5c0d\u52d5\u614b\u5206\u6d3e\uff0c\u9664\u975e JIT \u7684\u52d5\u614b\u884c\u5167\u5c55\u958b\uff08Inlining\uff09\u80fd\u6210\u529f\u5c07 <code>calculate<\/code> \u8207 <code>invoke<\/code> \u540c\u6642\u884c\u5167\u5c55\u958b\u9032\u547c\u53eb\u7aef\uff0c\u5426\u5247\u9003\u9038\u5206\u6790\u6839\u672c\u7121\u6cd5\u7a7f\u900f\u865b\u64ec\u65b9\u6cd5\u8868\uff08Vtable\uff09\u908a\u754c\uff01<\/li>\n<li>\u4e00\u65e6\u547c\u53eb\u9ede\u51fa\u73fe\u591a\u578b\u614b\uff08Polymorphic Call Site\uff09\u6216\u662f\u4f4d\u5143\u7d44\u78bc\u9ad4\u7a4d\u8d85\u51fa JIT \u884c\u5167\u5c55\u958b\u9580\u6abb\uff0c\u9003\u9038\u5206\u6790\u7acb\u523b\u5ba3\u544a\u653e\u68c4\u3002\u7d14\u91cf\u66ff\u63db\u76f4\u63a5\u5931\u6557\uff0c\u533f\u540d\u7269\u4ef6\u6beb\u7121\u61f8\u5ff5\u5730\u5728 Heap \u4e0a\u5be6\u9ad4\u914d\u7f6e\u3002<\/li>\n<\/ul>\n<h3>\u6848\u767c\u73fe\u5834\uff1a120fps \u8207 RecyclerView \u7684\u5c60\u5bb0\u5834<\/h3>\n<p>\u5728\u4f4e\u983b\u7387\u7684\u6309\u9215\u9ede\u64ca\u4e8b\u4ef6\u88e1\uff0c<code>new<\/code> \u4e00\u500b 24 bytes \u7684\u7269\u4ef6\u78ba\u5be6\u4e0d\u75db\u4e0d\u7662\u3002<br \/>\n\u4f46\u82e5\u9019\u6bb5\u9ad8\u968e\u51fd\u5f0f\u843d\u5728 <strong><code>RecyclerView.Adapter<\/code> \u7684 <code>onBindViewHolder<\/code>\u3001\u81ea\u8a02 View \u7684 <code>onTouchEvent<\/code>\u3001\u6216\u662f\u6bcf\u79d2 120 \u5e40\u7684\u52d5\u756b\u7e6a\u88fd\u8ff4\u5708<\/strong> \u4e2d\uff1a<\/p>\n<p>$$\\text{\u8a18\u61b6\u9ad4\u5783\u573e\u7522\u51fa\u91cf} = 120\\text{ fps} \\times 10\\text{ \u6b21\u547c\u53eb} \\times (24\\text{B Lambda} + 32\\text{B \u88dd\u7bb1}) \\approx 67.2\\text{ KB\/s}$$<\/p>\n<p>\u4f7f\u7528\u8005\u5feb\u901f\u6ed1\u52d5\u87a2\u5e55\u6642\uff0c\u6bcf\u79d2\u5728\u5806\u7a4d\u8a18\u61b6\u9ad4\uff08Young Gen \/ Eden Space\uff09\u5674\u51fa\u6578\u4ee5\u842c\u8a08\u7684\u77ed\u547d\u7269\u4ef6\u3002<br \/>\nAndroid ART \u5206\u914d\u5668\uff08RosAlloc\uff09\u88ab\u8feb\u983b\u7e41\u89f8\u767c\u5783\u573e\u56de\u6536\uff08GC\uff09\uff0c\u5f15\u767c\u56b4\u91cd\u7684 <strong>GC \u6296\u52d5\uff08GC Thrashing\uff09<\/strong> \u8207\u57f7\u884c\u7dd2\u66ab\u505c\uff08Stop-The-World\uff09\u3002\u5373\u4f7f ART \u5177\u5099\u4f75\u767c\u8907\u88fd\u56de\u6536\u5668\uff08Concurrent Copying GC\uff09\uff0c\u4e5f\u7d93\u4e0d\u8d77\u6bcf\u79d2\u5e7e\u842c\u500b\u7269\u4ef6\u7684\u9023\u7e8c\u8f5f\u70b8\u3002\u524d\u53f0 UI \u77ac\u9593\u5361\u9813\u3001\u6389\u5e40\uff0c120Hz \u65d7\u8266\u6a5f\u7576\u5834\u88ab\u62c9\u4f4e\u5230 45fps\u3002<\/p>\n<hr>\n<h2>\u6551\u8d16\uff1a<code>inline<\/code>\uff08\u884c\u5167\u5c55\u958b\uff09\u2014\u2014 \u628a\u7269\u4ef6\u914d\u7f6e\u5fb9\u5e95\u62b9\u6bba<\/h2>\n<p>\u65e2\u7136\u7269\u4ef6\u914d\u7f6e\u9019\u9ebc\u8cb4\uff0c\u90a3\u4e0d\u8981 <code>new<\/code> \u4e0d\u5c31\u5f97\u4e86\uff1f\u9019\u6b63\u662f <strong><code>inline<\/code>\uff08\u884c\u5167\u5c55\u958b\uff09<\/strong> \u7684\u6838\u5fc3\u4f7f\u547d\u3002<\/p>\n<p>\u7576\u4f60\u5728\u51fd\u5f0f\u524d\u9762\u52a0\u4e0a <code>inline<\/code> \u4fee\u98fe\u7b26\uff1a<\/p>\n<pre><code class=\"hljs language-kotlin\"><span class=\"hljs-keyword\">inline<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">calculate<\/span><span class=\"hljs-params\">(a: <span class=\"hljs-type\">Int<\/span>, b: <span class=\"hljs-type\">Int<\/span>, operation: (<span class=\"hljs-type\">Int<\/span>, <span class=\"hljs-type\">Int<\/span>) -&gt; <span class=\"hljs-type\">Int<\/span>)<\/span><\/span>: <span class=\"hljs-built_in\">Int<\/span> {\n    <span class=\"hljs-keyword\">return<\/span> operation(a, b)\n}<\/code><\/pre>\n<p>Kotlin \u7de8\u8b6f\u5668\u5728\u7de8\u8b6f\u671f\u9593\u6703\u57f7\u884c\u300c\u4f4d\u5143\u7d44\u78bc\u5e73\u92ea\uff08Bytecode Flattening\uff09\u300d\uff1a<strong>\u76f4\u63a5\u628a\u51fd\u5f0f\u672c\u9ad4\u4ee5\u53ca\u50b3\u5165\u7684 Lambda \u904b\u7b97\u908f\u8f2f\uff0c\u50cf\u76f4\u63a5\u8907\u88fd\u8cbc\u4e0a\u4e00\u6a23\u5e73\u92ea\u81f3\u547c\u53eb\u7aef\uff01<\/strong><\/p>\n<h3>\u53cd\u7de8\u8b6f\u770b\u771f\u76f8\uff08Bytecode Flattening\uff09\uff1a<\/h3>\n<p>\u547c\u53eb\u7aef\u7de8\u8b6f\u5f8c\u7684 Bytecode \u76f4\u63a5\u8b8a\u6210\u4e86\u9019\u526f\u6a21\u6a23\uff1a<\/p>\n<pre><code class=\"hljs language-plaintext\">BIPUSH 10\nISTORE 1\nBIPUSH 20\nISTORE 2\nILOAD 1\nILOAD 2\nIADD        \/\/ \u76f4\u63a5\u5728\u7576\u524d\u904b\u7b97\u5143\u5806\u758a\u5b8c\u6210\u52a0\u6cd5\uff01\nISTORE 3<\/code><\/pre>\n<p>\u770b\u770b\u767c\u751f\u4e86\u4ec0\u9ebc\u9a5a\u4eba\u7684\u7269\u7406\u8f49\u8b8a\uff1a<\/p>\n<ol>\n<li><strong><code>NEW<\/code> \u8207 <code>DUP<\/code> \u6307\u4ee4\u6b78\u96f6<\/strong>\uff1aHeap \u4e0a\u6c92\u6709\u4efb\u4f55 <code>Function2<\/code> \u7269\u4ef6\u88ab\u751f\u6210\uff0c\u8a18\u61b6\u9ad4\u914d\u7f6e\u958b\u92b7\u70ba 0\u3002<\/li>\n<li><strong><code>INVOKEINTERFACE<\/code> \u6307\u4ee4\u6b78\u96f6<\/strong>\uff1a\u5fb9\u5e95\u6d88\u6ec5\u4ecb\u9762\u65b9\u6cd5\u547c\u53eb\u958b\u92b7\u8207\u865b\u64ec\u65b9\u6cd5\u8868\u67e5\u627e\uff08Vtable Lookup\uff09\u3002<\/li>\n<li><strong>\u88dd\u7bb1\u6210\u672c\u6b78\u96f6<\/strong>\uff1a\u76f4\u63a5\u4f7f\u7528 CPU \u539f\u751f\u7684 <code>ILOAD<\/code> \u8207 <code>IADD<\/code> \u5728\u904b\u7b97\u5143\u5806\u758a\uff08Operand Stack\uff09\u4e0a\u57f7\u884c\u904b\u7b97\uff0c\u5b8c\u5168\u907f\u958b <code>Integer.valueOf()<\/code>\u3002<\/li>\n<li><strong>\u547c\u53eb\u5806\u758a\u6846\u67b6\uff08Stack Frame\uff09\u958b\u92b7\u6d88\u9664<\/strong>\uff1a\u5b8c\u5168\u4e0d\u9700\u8981\u70ba\u51fd\u5f0f\u547c\u53eb\u5efa\u7acb\u65b0\u7684 Stack Frame\uff0c\u908f\u8f2f\u76f4\u63a5\u878d\u9032\u7576\u524d\u547c\u53eb\u7aef\u3002<\/li>\n<\/ol>\n<h3>\u6b0a\u8861\u4ee3\u50f9\uff1a\u4f4d\u5143\u7d44\u78bc\u81a8\u8139\uff08Bytecode Bloat\uff09\u8207 L1I Cache \u6296\u52d5<\/h3>\n<p>\u5982\u679c <code>inline<\/code> \u9019\u9ebc\u795e\uff0c\u70ba\u4ec0\u9ebc\u7de8\u8b6f\u5668\u4e0d\u9810\u8a2d\u628a\u6240\u6709\u51fd\u5f0f\u5168\u90e8\u884c\u5167\u5316\uff1f<br \/>\n\u5929\u4e0b\u6c92\u6709\u767d\u5403\u7684\u5348\u9910\u3002<\/p>\n<ol>\n<li><strong>\u7121 Lambda \u53c3\u6578\u7684\u666e\u901a\u51fd\u5f0f\u56b4\u7981 <code>inline<\/code><\/strong>\uff1a<br \/>\n\u5982\u679c\u4f60\u5c0d\u4e00\u500b\u666e\u901a\u51fd\u5f0f\u52a0\u4e0a <code>inline<\/code>\uff0cKotlin \u7de8\u8b6f\u5668\u6703\u76f4\u63a5\u5674\u8b66\u544a\uff1a<code>Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types.<\/code>\u3002<br \/>\n\u73fe\u4ee3 JIT \u7de8\u8b6f\u5668\u672c\u8eab\u5c31\u5177\u5099\u6975\u70ba\u5f37\u5927\u7684\u65b9\u6cd5\u884c\u5167\u6700\u4f73\u5316\u80fd\u529b\uff0c\u624b\u5beb <code>inline<\/code> \u53ea\u6703\u5f92\u589e\u7de8\u8b6f\u671f\u8ca0\u64d4\u3002<\/li>\n<li><strong>\u4f4d\u5143\u7d44\u78bc\u81a8\u8139\uff08Bytecode Bloat\uff09<\/strong>\uff1a<br \/>\n\u5982\u679c\u4e00\u500b\u88ab\u6a19\u8a18\u70ba <code>inline<\/code> \u7684\u51fd\u5f0f\u9ad4\u7a4d\u9577\u9054 150 \u884c\u4f4d\u5143\u7d44\u78bc\uff0c\u5728\u5c08\u6848\u4e2d\u88ab 50 \u500b\u5730\u65b9\u547c\u53eb\uff0c\u7de8\u8b6f\u5f8c\u7684 Bytecode \u5c31\u6703\u88ab\u8907\u88fd 50 \u4efd\uff01<br \/>\n\u9019\u4e0d\u50c5\u6703\u52a0\u901f\u649e\u4e0a Android DEX \u7684 65,536 \u65b9\u6cd5\u6578\u4e0a\u9650\uff0864K MultiDex \u9580\u6abb\uff09\uff0c\u66f4\u81f4\u547d\u7684\u662f\u5c0d\u786c\u9ad4\u5feb\u53d6\u7684\u7834\u58de\u3002<\/li>\n<li><strong>CPU L1 \u6307\u4ee4\u5feb\u53d6\u884c\u6296\u52d5\uff08I-Cache Thrashing\uff09<\/strong>\uff1a<br \/>\n\u4ee5\u4e3b\u6d41 ARM \u8655\u7406\u5668\uff08\u4f8b\u5982 Cortex-A55 \u6216 Cortex-A78\uff09\u70ba\u4f8b\uff0c\u6838\u5fc3\u7684 L1 \u6307\u4ee4\u5feb\u53d6\uff08L1I Cache\uff09\u901a\u5e38\u50c5\u6709 <strong>32KB \u6216 64KB<\/strong>\uff0c\u5feb\u53d6\u884c\uff08Cache Line\uff09\u901a\u5e38\u70ba 64 bytes\u3002<br \/>\n\u7576\u9f90\u5927\u7684\u884c\u5167\u7a0b\u5f0f\u78bc\u88ab\u56db\u8655\u5e73\u92ea\uff0c\u71b1\u9ede\u8def\u5f91\uff08Hot Path\uff09\u7684\u4e8c\u9032\u4f4d\u6307\u4ee4\u9ad4\u7a4d\u6025\u907d\u81a8\u8139\uff0c\u76f4\u63a5\u5c07\u539f\u672c\u6709\u9650\u7684 L1I \u5feb\u53d6\u884c\u64e0\u7206\uff0c\u5f15\u767c\u56b4\u91cd\u7684 <strong>L1I Cache Miss<\/strong>\u3002CPU \u53d6\u6307\u4ee4\uff08Instruction Fetch\uff09\u88ab\u8feb\u983b\u7e41\u5411 L2\/L3 \u5feb\u53d6\u751a\u81f3 DRAM \u8acb\u6c42\u8cc7\u6599\uff0c\u7ba1\u7dda\uff08Pipeline\uff09\u9677\u5165\u505c\u9813\uff08Stall\uff09\u3002\u539f\u672c\u60f3\u7701\u5e7e\u500b\u7269\u4ef6\u7684\u8a18\u61b6\u9ad4\uff0c\u7d50\u679c\u628a CPU \u6307\u4ee4\u7ba1\u7dda\u62d6\u4e0b\u6c34\u966a\u846c\uff01<\/li>\n<\/ol>\n<blockquote>\n<p><strong>\u9435\u5f8b<\/strong>\uff1a<code>inline<\/code> \u53ea\u8a72\u7528\u5728\u63a5\u53d7 Lambda \u53c3\u6578\u7684\u9ad8\u968e\u51fd\u5f0f\uff0c\u4e14\u51fd\u5f0f\u672c\u9ad4\u5fc5\u9808\u4fdd\u6301\u6975\u5ea6\u7cbe\u7c21\uff08\u5efa\u8b70 10~20 \u884c\u4ee5\u5167\uff09\u3002\u9f90\u5927\u7684\u5546\u696d\u908f\u8f2f\u61c9\u62c6\u5206\u81f3 private \u7684\u975e\u884c\u5167\u8f14\u52a9\u51fd\u5f0f\u4e2d\u3002<\/p>\n<\/blockquote>\n<hr>\n<h2>\u7b2c\u4e00\u500b\u526f\u4f5c\u7528\u8207\u89e3\u6cd5\uff1a<code>noinline<\/code>\uff08\u4fdd\u7559\u7269\u4ef6\u8eab\u4efd\uff09<\/h2>\n<p>\u7576\u51fd\u5f0f\u88ab\u5ba3\u544a\u70ba <code>inline<\/code> \u4e4b\u5f8c\uff0c\u6240\u6709\u7684 Lambda \u53c3\u6578\u9810\u8a2d\u90fd\u6703\u88ab\u884c\u5167\u5c55\u958b\u3002\u4f46\u9019\u7acb\u523b\u5f15\u767c\u4e86\u7b2c\u4e00\u500b\u67b6\u69cb\u56f0\u5883\uff1a<strong>\u5c55\u958b\u5f8c\u7684\u7a0b\u5f0f\u78bc\u4e0d\u518d\u662f\u4e00\u500b\u300c\u7269\u4ef6\u5be6\u9ad4\u300d\uff0c\u5b83\u53ea\u662f\u4e00\u4e32\u88f8\u9732\u7684\u6307\u4ee4\uff01<\/strong><\/p>\n<p>\u5982\u679c\u4f60\u60f3\u628a\u9019\u500b\u50b3\u9032\u4f86\u7684 Lambda \u8ce6\u503c\u7d66\u67d0\u500b\u6210\u54e1\u8b8a\u6578\u3001\u5b58\u5165\u5de5\u4f5c\u4f47\u5217\uff08Work Queue\uff09\u7b49\u5f85\u80cc\u666f\u6392\u7a0b\uff0c\u6216\u8005\u50b3\u905e\u7d66\u53e6\u4e00\u500b\u975e\u884c\u5167\u51fd\u5f0f\uff0c\u7de8\u8b6f\u5668\u6703\u7576\u5834\u5728\u63a7\u5236\u53f0\u5674\u51fa\u7d05\u5b57\u5831\u932f\uff1a<br \/>\n<code>Illegal usage of inline-parameter &#39;backgroundTask&#39;. Add &#39;noinline&#39; modifier to the parameter declaration.<\/code><\/p>\n<p>\u70ba\u4ec0\u9ebc\uff1f\u56e0\u70ba\u5728 JVM \u7684\u8a18\u61b6\u9ad4\u6a21\u578b\u4e2d\uff0c\u4e00\u500b\u8b8a\u6578\u5132\u5b58\u7684\u5fc5\u9808\u662f <strong>\u7269\u4ef6\u5f15\u7528\uff08Object Reference\uff09<\/strong>\uff0c\u4e5f\u5c31\u662f\u4e00\u500b\u6307\u5411 Heap \u4f4d\u5740\u7684 32\/64 \u4f4d\u5143\u6307\u6a19\u3002\u4f60\u600e\u9ebc\u53ef\u80fd\u53bb\u5132\u5b58\u4e00\u4e32\u5df2\u7d93\u88ab\u5e73\u92ea\u5728\u547c\u53eb\u7aef\u7684\u6307\u4ee4\uff1f<\/p>\n<pre><code class=\"hljs language-kotlin\"><span class=\"hljs-keyword\">inline<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">scheduleTask<\/span><span class=\"hljs-params\">(\n    immediateTask: () -&gt; <span class=\"hljs-type\">Unit<\/span>,\n    <span class=\"hljs-keyword\">noinline<\/span> backgroundTask: () -&gt; <span class=\"hljs-type\">Unit<\/span> <span class=\"hljs-comment\">\/\/ \u5fc5\u9808\u5ba3\u544a\u70ba noinline\uff01<\/span>\n)<\/span><\/span> {\n    <span class=\"hljs-comment\">\/\/ immediateTask \u76f4\u63a5\u5728\u7576\u524d\u884c\u5167\u5c55\u958b\u57f7\u884c\uff0c\u4eab\u53d7\u96f6\u914d\u7f6e\u512a\u52e2<\/span>\n    immediateTask()\n\n    <span class=\"hljs-comment\">\/\/ backgroundTask \u9700\u8981\u88ab\u7576\u4f5c\u7269\u4ef6\u50b3\u905e\u7d66\u5176\u4ed6\u57f7\u884c\u7dd2\u6216\u5132\u5b58\u8d77\u4f86<\/span>\n    saveForLater(backgroundTask) \n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">saveForLater<\/span><span class=\"hljs-params\">(task: () -&gt; <span class=\"hljs-type\">Unit<\/span>)<\/span><\/span> {\n    taskQueue.add(task) <span class=\"hljs-comment\">\/\/ \u9019\u88e1\u5fc5\u9808\u662f\u4e00\u500b\u771f\u5be6\u7684 Function0 \u7269\u4ef6\u5f15\u7528\uff01<\/span>\n}<\/code><\/pre>\n<h3><code>noinline<\/code> \u7684\u5fae\u67b6\u69cb\u672c\u8cea\uff1a<\/h3>\n<p><code>noinline<\/code> \u662f <code>inline<\/code> \u51fd\u5f0f\u5167\u90e8\u7684\u4e00\u584a**\u300c\u7269\u4ef6\u4fdd\u7559\u7279\u5340\u300d**\u3002<br \/>\u5b83\u544a\u8a34\u7de8\u8b6f\u5668\uff1a\u300c\u9019\u500b\u51fd\u5f0f\u672c\u9ad4\u548c\u5176\u4ed6 Lambda \u8acb\u7167\u5e38\u884c\u5167\u5c55\u958b\uff0c\u552f\u7368\u6a19\u8a18\u4e86 <code>noinline<\/code> \u7684\u9019\u500b Lambda\uff0c\u8acb\u7dad\u6301\u5176\u539f\u59cb\u7684 JVM <code>Function<\/code> \u7269\u4ef6\u578b\u614b\u3002\u5728\u547c\u53eb\u7aef\u4f9d\u7136\u8001\u8001\u5be6\u5be6\u767c\u51fa <code>NEW Function0<\/code>\u3001<code>DUP<\/code>\u3001<code>INVOKESPECIAL<\/code>\uff0c\u751f\u6210\u4e00\u500b\u5177\u6709\u771f\u5be6\u8a18\u61b6\u9ad4\u4f4d\u5740\u7684\u7269\u4ef6\u6307\u6a19\uff0c\u65b9\u4fbf\u6211\u5f8c\u7e8c\u9032\u884c\u5f15\u7528\u50b3\u905e\u6216\u5132\u5b58\u3002\u300d<\/p>\n<hr>\n<h2>\u7b2c\u4e8c\u500b\u526f\u4f5c\u7528\u8207\u89e3\u6cd5\uff1a<code>crossinline<\/code>\uff08\u547c\u53eb\u5806\u758a\u7269\u7406\u5b78\uff09<\/h2>\n<p>\u9019\u662f\u6240\u6709\u8cc7\u6df1 Android \u67b6\u69cb\u5e2b\u8207\u9762\u8a66\u5b98\u6700\u611b\u6df1\u6316\u7684\u6df1\u6c34\u5340\u3002<\/p>\n<h3>1. \u4ec0\u9ebc\u662f\u300c\u975e\u5c40\u90e8\u8fd4\u56de\uff08Non-local Return\uff09\u300d\uff1f<\/h3>\n<p>\u5728\u6a19\u6e96\u7684 Kotlin \u8a9e\u6cd5\u4e2d\uff0c\u666e\u901a Lambda \u662f\u7d55\u5c0d\u4e0d\u5141\u8a31\u76f4\u63a5\u4f7f\u7528\u7121\u6a19\u7c64 <code>return<\/code> \u4f86\u7d50\u675f\u5916\u5c64\u51fd\u5f0f\u7684\uff1a<\/p>\n<pre><code class=\"hljs language-kotlin\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">ordinaryFunction<\/span><span class=\"hljs-params\">(block: () -&gt; <span class=\"hljs-type\">Unit<\/span>)<\/span><\/span> { block() }\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">test<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n    ordinaryFunction {\n        <span class=\"hljs-comment\">\/\/ return \/\/ \u7de8\u8b6f\u932f\u8aa4\uff01&#x27;return&#x27; is not allowed here<\/span>\n    }\n}<\/code><\/pre>\n<p>\u70ba\u4ec0\u9ebc\u666e\u901a Lambda \u7981\u6b62 <code>return<\/code>\uff1f<br \/>\n\u56e0\u70ba\u5728 JVM Bytecode \u898f\u7bc4\u4e2d\uff0c<code>block()<\/code> \u662f\u900f\u904e <code>INVOKEINTERFACE Function0.invoke()<\/code> \u57f7\u884c\u7684\u3002\u4f60\u5728 <code>invoke()<\/code> \u88e1\u9762\u767c\u51fa\u7684 <code>RETURN<\/code> \u6307\u4ee4\uff0c\u53ea\u80fd\u9000\u51fa\u5b83\u81ea\u5df1\u7684\u5806\u758a\u6846\u67b6\uff08Stack Frame\uff09\uff0c\u7269\u7406\u4e0a\u6839\u672c\u7121\u6cd5\u8de8\u8d8a\u6846\u67b6\u53bb\u76f4\u63a5\u7d50\u675f\u5916\u5c64\u7684 <code>test()<\/code>\uff01<\/p>\n<p>\u4f46\u662f\uff0c\u4e00\u65e6\u51fd\u5f0f\u52a0\u4e0a\u4e86 <code>inline<\/code>\uff1a<\/p>\n<pre><code class=\"hljs language-kotlin\"><span class=\"hljs-keyword\">inline<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">inlineFunction<\/span><span class=\"hljs-params\">(block: () -&gt; <span class=\"hljs-type\">Unit<\/span>)<\/span><\/span> { block() }\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">test<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n    inlineFunction {\n        println(<span class=\"hljs-string\">&quot;Early exit&quot;<\/span>)\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-comment\">\/\/ \u5408\u6cd5\uff01\u9019\u6703\u76f4\u63a5\u7d42\u6b62\u6574\u500b test() \u51fd\u5f0f\uff01<\/span>\n    }\n    println(<span class=\"hljs-string\">&quot;Unreachable&quot;<\/span>) <span class=\"hljs-comment\">\/\/ \u6c38\u9060\u4e0d\u6703\u88ab\u57f7\u884c<\/span>\n}<\/code><\/pre>\n<p>\u70ba\u4ec0\u9ebc\u5408\u6cd5\uff1f\u56e0\u70ba\u7a0b\u5f0f\u78bc\u5e73\u92ea\u4e86\uff01\u7de8\u8b6f\u5668\u5728\u751f\u6210 Bytecode \u6642\uff0c\u76f4\u63a5\u628a Lambda \u5167\u90e8\u7684 <code>return<\/code> \u8f49\u8b6f\u70ba <code>test()<\/code> \u65b9\u6cd5\u672c\u9ad4\u7684 <code>RETURN<\/code> \u6307\u4ee4\uff01\u9019\u5c31\u662f\u6240\u8b02\u7684 <strong>\u975e\u5c40\u90e8\u8fd4\u56de\uff08Non-local Return\uff09<\/strong>\u3002<\/p>\n<hr>\n<h3>2. \u81f4\u547d\u6642\u7a7a\u6096\u8ad6\uff1a\u7576 Lambda \u9047\u5230\u975e\u540c\u6b65\u4e0a\u4e0b\u6587<\/h3>\n<p>\u975e\u5c40\u90e8\u8fd4\u56de\u5728\u5faa\u5e8f\u57f7\u884c\u7684\u55ae\u4e00\u5806\u758a\u4e2d\u904b\u4f5c\u5f97\u5f88\u597d\u3002\u4f46\u5982\u679c\u9019\u500b\u884c\u5167 Lambda \u88ab\u5305\u9032\u4e86**\u9593\u63a5\u4e0a\u4e0b\u6587\uff08\u5982 <code>Runnable<\/code>\u3001\u975e\u540c\u6b65 Worker \u57f7\u884c\u7dd2\u3001\u533f\u540d\u5167\u90e8\u985e\u5225\uff09**\u4e2d\u5ef6\u9072\u57f7\u884c\u5462\uff1f<\/p>\n<pre><code class=\"hljs language-kotlin\"><span class=\"hljs-keyword\">inline<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">runOnWorkerThread<\/span><span class=\"hljs-params\">(block: () -&gt; <span class=\"hljs-type\">Unit<\/span>)<\/span><\/span> {\n    <span class=\"hljs-keyword\">val<\/span> runnable = Runnable {\n        block() <span class=\"hljs-comment\">\/\/ \u5047\u8a2d\u7de8\u8b6f\u5668\u5141\u8a31\u9019\u6a23\u5beb<\/span>\n    }\n    workerThread.post(runnable)\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">outerCaller<\/span><span class=\"hljs-params\">()<\/span><\/span> {\n    runOnWorkerThread {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-comment\">\/\/ \u81f4\u547d\u6096\u8ad6\u7206\u767c\uff01<\/span>\n    }\n}<\/code><\/pre>\n<p>\u8b93\u6211\u5011\u7ad9\u5728 <strong>JVM \u547c\u53eb\u5806\u758a\uff08Call Stack Frame\uff09\u8207\u57f7\u884c\u7dd2\u8a18\u61b6\u9ad4\u67b6\u69cb\u7684\u7269\u7406\u7dad\u5ea6<\/strong> \u4f86\u62c6\u89e3\u9019\u500b\u6b7b\u5c40\uff1a<\/p>\n<pre><code class=\"hljs language-dart\">[\u6642\u9593\u8ef8 <span class=\"hljs-title class_\">T0<\/span>] \u4e3b\u57f7\u884c\u7dd2 (<span class=\"hljs-title class_\">Thread<\/span>-A)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 <span class=\"hljs-title class_\">Stack<\/span> <span class=\"hljs-title class_\">Frame<\/span>: <span class=\"hljs-title function_\">outerCaller<\/span>()    \u2502 \u2500\u2500\u2500&gt; \u547c\u53eb runOnWorkerThread\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 \u5efa\u7acb <span class=\"hljs-title class_\">Runnable<\/span>\uff0c\u4e1f\u5165 workerThread \u4f47\u5217\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n  \u2502\n  \u25bc \u65b9\u6cd5\u57f7\u884c\u5b8c\u7562\uff0c<span class=\"hljs-title class_\">Stack<\/span> <span class=\"hljs-title class_\">Frame<\/span> \u51fa\u68e7\u92b7\u6bc0\uff01 (<span class=\"hljs-title class_\">Popped<\/span> &amp; <span class=\"hljs-title class_\">Destroyed<\/span>)\n\n============================================================\n\n[\u6642\u9593\u8ef8 <span class=\"hljs-title class_\">T1<\/span>: 300ms \u5f8c] \u80cc\u666f\u57f7\u884c\u7dd2 (<span class=\"hljs-title class_\">Thread<\/span>-B)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 <span class=\"hljs-title class_\">Stack<\/span> <span class=\"hljs-title class_\">Frame<\/span>: workerThread.<span class=\"hljs-title function_\">run<\/span>()\u2502 \u2500\u2500\u2500&gt; \u57f7\u884c <span class=\"hljs-title function_\">block<\/span>()\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 \u8a66\u5716\u57f7\u884c non-local <span class=\"hljs-keyword\">return<\/span> \u9000\u51fa <span class=\"hljs-title function_\">outerCaller<\/span>() ... ???\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/code><\/pre>\n<p>\u770b\u770b\u9019\u5f15\u767c\u4e86\u591a\u9ebc\u8352\u8b2c\u7684\u7269\u7406\u77db\u76fe\uff1a<\/p>\n<ol>\n<li><strong>\u6642\u9593\u7dad\u5ea6\u65b7\u5c64\uff08Dead Stack Frame\uff09<\/strong>\uff1a<br \/>\n<code>outerCaller()<\/code> \u7684\u5806\u758a\u6846\u67b6\u65e9\u5728 300 \u6beb\u79d2\u524d\u5c31\u5df2\u7d93\u51fa\u68e7\u7159\u6d88\u96f2\u6563\u4e86\u3002\u6b64\u6642 <code>block()<\/code> \u8a66\u5716 return \u5230\u54ea\u88e1\uff1fJVM \u898f\u7bc4\u6839\u672c\u6c92\u6709\u300c\u8df3\u8f49\u56de\u5df2\u92b7\u6bc0\u5806\u758a\u6846\u67b6\u300d\u7684\u6307\u4ee4\uff01<\/li>\n<li><strong>\u7a7a\u9593\u7dad\u5ea6\u65b7\u5c64\uff08Thread Isolation\uff09<\/strong>\uff1a<br \/>\nJVM \u898f\u7bc4\u660e\u78ba\u5b9a\u7fa9\uff1a<strong>\u6bcf\u500b\u57f7\u884c\u7dd2\u7684\u547c\u53eb\u5806\u758a\u662f\u56b4\u683c\u9694\u96e2\u4e14\u79c1\u6709\u7684\uff08Thread-Isolated\uff09<\/strong>\u3002\u7576\u524d\u7a0b\u5f0f\u78bc\u662f\u5728 Thread-B \u7684 Call Stack \u9802\u7aef\u904b\u4f5c\uff0c\u800c <code>outerCaller()<\/code> \u5c6c\u65bc Thread-A\u3002Thread-B \u7269\u7406\u4e0a\u7d55\u5c0d\u4e0d\u53ef\u80fd\u3001\u4e5f\u7121\u6b0a\u8de8\u57f7\u884c\u7dd2\u53bb\u7ac4\u6539\u6216\u6e05\u7a7a Thread-A \u7684\u5806\u758a\u6307\u6a19\uff08ESP \/ RSP\uff09\uff01<\/li>\n<\/ol>\n<p>\u5982\u679c\u7de8\u8b6f\u5668\u653e\u884c\u9019\u6bb5\u7a0b\u5f0f\u78bc\uff0c\u57f7\u884c\u968e\u6bb5\u5c31\u53ea\u80fd\u7576\u5834\u5f15\u767c\u56b4\u91cd\u7684\u8a18\u61b6\u9ad4\u9055\u898f\u6216\u865b\u64ec\u6a5f\u5668\u5d29\u6f70\uff01<\/p>\n<hr>\n<h3>3. <code>crossinline<\/code> \u7684\u5207\u7d50\u4fdd\u8b49<\/h3>\n<p>Kotlin \u7de8\u8b6f\u5668\u7684\u63a7\u5236\u6d41\u7a0b\u5206\u6790\uff08Control Flow Analysis\uff09\u5728\u7de8\u8b6f\u671f\u5c31\u80fd\u6d1e\u6089\u9019\u500b\u6642\u7a7a\u6096\u8ad6\uff0c\u7576\u5834\u5674\u51fa\u932f\u8aa4\uff1a<br \/>\n<code>Can&#39;t inline &#39;block&#39; here: it may contain non-local returns. Add &#39;crossinline&#39; modifier to parameter declaration.<\/code><\/p>\n<p>\u9019\u6b63\u662f <strong><code>crossinline<\/code><\/strong> \u5b58\u5728\u7684\u552f\u4e00\u7406\u7531\uff1a<\/p>\n<pre><code class=\"hljs language-kotlin\"><span class=\"hljs-keyword\">inline<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">fun<\/span> <span class=\"hljs-title\">runOnWorkerThread<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">crossinline<\/span> block: () -&gt; <span class=\"hljs-type\">Unit<\/span>)<\/span><\/span> {\n    <span class=\"hljs-keyword\">val<\/span> runnable = Runnable {\n        block() <span class=\"hljs-comment\">\/\/ \u7de8\u8b6f\u901a\u904e\uff01<\/span>\n    }\n    workerThread.post(runnable)\n}<\/code><\/pre>\n<ul>\n<li><strong>\u7269\u7406\u627f\u8afe\uff08The Contract\uff09<\/strong>\uff1a<br \/>\n\u5b83\u5411\u7de8\u8b6f\u5668\u7acb\u4e0b\u5207\u7d50\u66f8\u2014\u2014\u300c\u9019\u500b Lambda \u4f9d\u7136\u4fdd\u6301\u884c\u5167\u5c55\u958b\uff08\u5728 <code>Runnable.run()<\/code> \u5167\u90e8\u5e73\u92ea\u7a0b\u5f0f\u78bc\uff0c\u7701\u53bb\u984d\u5916\u7684 <code>Function<\/code> \u7269\u4ef6\u4e2d\u4ecb\uff09\uff0c\u4f46\u6211\u4fdd\u8b49<strong>\u7d55\u4e0d\u6703\u5728\u88e1\u9762\u4f7f\u7528\u975e\u5c40\u90e8 <code>return<\/code><\/strong>\uff01\u300d<\/li>\n<li><strong>\u975c\u614b\u9632\u79a6\u9396\u6b7b<\/strong>\uff1a<br \/>\n\u4e00\u65e6\u6a19\u8a18\u70ba <code>crossinline<\/code>\uff0c\u547c\u53eb\u7aef\u5728 Lambda \u5167\u90e8\u5982\u679c\u5beb\u7121\u6a19\u7c64\u7684 <code>return<\/code>\uff0c\u7de8\u8b6f\u5668\u76f4\u63a5\u6253\u69cd\u3002\u4f60\u53ea\u80fd\u4f7f\u7528\u5340\u57df\u8fd4\u56de\uff08Local Return\uff09<code>return@runOnWorkerThread<\/code>\uff0c\u5b89\u5168\u9000\u51fa\u7576\u524d\u9589\u5305\u3002<\/li>\n<\/ul>\n<p>\u5982\u6b64\u4e00\u4f86\uff0c\u65e2\u7dad\u6301\u4e86\u884c\u5167\u5e73\u92ea\u7684\u6975\u81f4\u6548\u80fd\uff0c\u53c8\u5728\u547c\u53eb\u5806\u758a\u7269\u7406\u5b78\u7684\u7dad\u5ea6\u4e0a\u56fa\u82e5\u91d1\u6e6f\u3002<\/p>\n<hr>\n<h2>\u95dc\u9375\u5b57\u5fae\u67b6\u69cb\u6c7a\u7b56\u77e9\u9663<\/h2>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\u4fee\u98fe\u7b26<\/th>\n<th align=\"center\">\u4f4d\u5143\u7d44\u78bc\u884c\u5167\u5c55\u958b<\/th>\n<th align=\"center\">Heap \u7269\u4ef6\u914d\u7f6e\u6210\u672c<\/th>\n<th align=\"center\">\u80fd\u5426\u7576\u7269\u4ef6\u50b3\u905e\/\u5132\u5b58<\/th>\n<th align=\"center\">\u975e\u5c40\u90e8\u8fd4\u56de (Non-local Return)<\/th>\n<th align=\"left\">\u5178\u578b\u9069\u7528\u5834\u666f<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\"><strong>(\u7121\u4fee\u98fe\u7b26)<\/strong><\/td>\n<td align=\"center\">\u5426<\/td>\n<td align=\"center\">\u6bcf\u6b21\u547c\u53eb <code>new Function<\/code> (16~24B+)<\/td>\n<td align=\"center\">\u53ef\u4ee5<\/td>\n<td align=\"center\">\u56b4\u683c\u7981\u6b62<\/td>\n<td align=\"left\">\u666e\u901a\u696d\u52d9\u908f\u8f2f\u3001\u975e\u6548\u80fd\u654f\u611f\u8def\u5f91<\/td>\n<\/tr>\n<tr>\n<td align=\"left\"><strong><code>inline<\/code><\/strong><\/td>\n<td align=\"center\">\u662f<\/td>\n<td align=\"center\"><strong>0 \u7269\u4ef6\u914d\u7f6e (\u5b8c\u5168\u5e73\u92ea)<\/strong><\/td>\n<td align=\"center\">\u5931\u53bb\u7269\u4ef6\u8eab\u4efd<\/td>\n<td align=\"center\">\u5141\u8a31 (\u76f4\u63a5\u9000\u51fa\u5916\u5c64\u51fd\u5f0f)<\/td>\n<td align=\"left\">\u9ad8\u983b\u547c\u53eb\u9ad8\u968e\u51fd\u5f0f\u3001\u96c6\u5408\u904b\u7b97\u5b50 (<code>map<\/code>\/<code>filter<\/code>)<\/td>\n<\/tr>\n<tr>\n<td align=\"left\"><strong><code>noinline<\/code><\/strong><\/td>\n<td align=\"center\">\u5340\u57df\u95dc\u9589<\/td>\n<td align=\"center\">\u751f\u6210\u771f\u5be6 <code>Function<\/code> \u7269\u4ef6<\/td>\n<td align=\"center\">\u53ef\u4ee5<\/td>\n<td align=\"center\">\u56b4\u683c\u7981\u6b62<\/td>\n<td align=\"left\">\u9700\u8981\u628a\u67d0\u500b Lambda \u5b58\u5165\u4f47\u5217\u6216\u50b3\u7d66\u4ed6\u4eba\u6642<\/td>\n<\/tr>\n<tr>\n<td align=\"left\"><strong><code>crossinline<\/code><\/strong><\/td>\n<td align=\"center\">\u662f<\/td>\n<td align=\"center\"><strong>0 \u7269\u4ef6\u914d\u7f6e (\u9593\u63a5\u5e73\u92ea)<\/strong><\/td>\n<td align=\"center\">\u5931\u53bb\u7269\u4ef6\u8eab\u4efd<\/td>\n<td align=\"center\">\u56b4\u683c\u7981\u6b62 (\u50c5\u5141\u8a31 <code>return@label<\/code>)<\/td>\n<td align=\"left\">Lambda \u5728\u975e\u540c\u6b65\u57f7\u884c\u7dd2\u3001<code>Runnable<\/code> \u6216\u533f\u540d\u985e\u5225\u4e2d\u5ef6\u9072\u57f7\u884c<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr>\n<h2>\u5de5\u4f4d\u5927\u5be6\u8a71<\/h2>\n<ol>\n<li><strong>\u4e0d\u8981\u5c0d\u7121 Lambda \u53c3\u6578\u7684\u666e\u901a\u51fd\u5f0f\u6a19\u8a18 <code>inline<\/code><\/strong>\uff1a\u73fe\u4ee3 JVM \/ ART \u7684 JIT \u7de8\u8b6f\u5668\u672c\u8eab\u5c31\u6703\u5c0d\u5c0f\u578b\u666e\u901a\u65b9\u6cd5\u505a\u884c\u5167\u6700\u4f73\u5316\uff0c\u624b\u5beb <code>inline<\/code> \u53ea\u6703\u5f92\u589e\u4f4d\u5143\u7d44\u78bc\u9ad4\u7a4d\u4e26\u6536\u5230\u7de8\u8b6f\u5668\u8b66\u544a\u3002<\/li>\n<li><strong>\u51fd\u5f0f\u9ad4\u7a4d\u904e\u5927\u6642\uff0c\u5207\u52ff\u7121\u8166 <code>inline<\/code><\/strong>\uff1a\u8acb\u96a8\u6642\u7262\u8a18 L1 \u6307\u4ee4\u5feb\u53d6\u53ea\u6709 32KB\u3002\u904e\u5ea6\u884c\u5167\u5316\u9020\u6210\u7684 I-Cache Thrashing\uff0c\u8db3\u4ee5\u628a\u4f60\u5728\u8a18\u61b6\u9ad4\u7701\u4e0b\u7684\u6bcf\u4e00\u5fae\u79d2\u6548\u80fd\u901a\u901a\u5410\u56de\u53bb\u3002<\/li>\n<li><strong>\u7576\u7de8\u8b6f\u5668\u63d0\u793a <code>Illegal usage of inline-parameter<\/code> \u6642<\/strong>\uff1a\u4ee3\u8868\u4f60\u9700\u8981\u4fdd\u7559\u7269\u4ef6\u5f15\u7528\uff0c\u8acb\u7528 <code>noinline<\/code>\u3002<\/li>\n<li><strong>\u7576\u7de8\u8b6f\u5668\u63d0\u793a <code>Can&#39;t inline... non-local returns<\/code> \u6642<\/strong>\uff1a\u4ee3\u8868 Lambda \u8655\u65bc\u9593\u63a5\u6216\u975e\u540c\u6b65\u4e0a\u4e0b\u6587\uff0c\u8acb\u7528 <code>crossinline<\/code>\u3002<\/li>\n<\/ol>\n<p>\u8a9e\u6cd5\u7cd6\u7684\u80cc\u5f8c\u5168\u662f JVM \u5806\u758a\u6307\u6a19\u7684\u79fb\u52d5\u3001\u8a18\u61b6\u9ad4\u5c0d\u9f4a\u8207\u66ab\u5b58\u5668\u6392\u7a0b\u3002\u628a\u9019\u4e09\u8005\u7684\u7269\u7406\u908a\u754c\u60f3\u900f\u5fb9\uff0c\u5728\u8ffd\u67e5\u6548\u80fd\u74f6\u9838\u8207\u7de8\u8b6f\u932f\u8aa4\u6642\uff0c\u81ea\u7136\u80fd\u4e00\u64ca\u5fc5\u6bba\u3002<\/p>\n<p>\u611f\u8b1d\u89c0\u770b\uff0c\u6536\u5de5\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u300cKotlin \u7de8\u8b6f\u5668\u5718\u968a\u7d55\u5c0d\u4e0d\u662f\u5403\u98fd\u592a\u9592\uff0c\u624d\u767c\u660e inline\u3001noinline\u3001crossinline \u9019 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1245,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[86],"tags":[192,236],"_links":{"self":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/655"}],"collection":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=655"}],"version-history":[{"count":13,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/655\/revisions"}],"predecessor-version":[{"id":1612,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/posts\/655\/revisions\/1612"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=\/wp\/v2\/media\/1245"}],"wp:attachment":[{"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=655"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=655"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/boochlin.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=655"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}