{"id":104552,"date":"2026-09-12T18:01:25","date_gmt":"2026-09-12T10:01:25","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/104552.html"},"modified":"2026-09-12T18:01:25","modified_gmt":"2026-09-12T10:01:25","slug":"mmkv-%e6%ba%90%e7%a0%81%e7%ba%a7%e5%89%96%e6%9e%90%ef%bc%88%e5%9f%ba%e4%ba%8e-v1-3-16-%e7%9c%9f%e5%ae%9e%e6%ba%90%e7%a0%81%ef%bc%89","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/104552.html","title":{"rendered":"MMKV \u6e90\u7801\u7ea7\u5256\u6790\uff08\u57fa\u4e8e v1.3.16 \u771f\u5b9e\u6e90\u7801\uff09"},"content":{"rendered":"<p>\u5206\u6790\u5bf9\u8c61<\/p>\n<ul>\n<li>Core\/&#xff1a;\u8de8\u5e73\u53f0 C&#043;&#043; \u6838\u5fc3&#xff08;Android \/ iOS \/ macOS \/ HarmonyOS \/ Win32 \u5171\u7528&#xff09;<\/li>\n<li>Android\/MMKV\/mmkv\/src\/main\/java\/&#xff1a;Android Java \u58f3\u5c42<\/li>\n<li>Android\/MMKV\/mmkv\/src\/main\/cpp\/native-bridge.cpp&#xff1a;JNI \u6865\u63a5\u5c42<\/li>\n<\/ul>\n<p>**\u6e90\u7801\u7248\u672c&#xff1a;v1.3.16 https:\/\/github.com\/Tencent\/MMKV\/releases#release-v1.3.16 \u5199\u4f5c\u539f\u5219&#xff1a;\u672c\u6587\u6240\u6709\u7ed3\u8bba\u5747\u53ef\u56de\u6eaf\u5230\u6e90\u7801&#xff0c;\u51fd\u6570\u4e0e\u4ee3\u7801\u5757\u540e\u6807\u6ce8 \u6587\u4ef6:\u884c\u53f7&#xff08;1-based&#xff09;\u3002\u51e1\u4e0e\u6d41\u4f20\u751a\u5e7f\u7684\u300c\u516b\u80a1\u8bf4\u6cd5\u300d\u4e0d\u7b26\u4e4b\u5904&#xff0c;\u5747\u663e\u5f0f\u6807\u6ce8 \u3010\u7ea0\u504f\u3011\u3002<\/p>\n<hr \/>\n<h3>\u76ee\u5f55<\/h3>\n<li>\u603b\u4f53\u67b6\u6784\u4e0e\u5206\u5c42<\/li>\n<li>\u521d\u59cb\u5316\u94fe\u8def&#xff1a;Java \u2192 JNI \u2192 C&#043;&#043;<\/li>\n<li>\u5b9e\u4f8b\u7ba1\u7406\u4e0e\u7f13\u5b58&#xff08;\u4e0d\u662f LRU&#xff09;<\/li>\n<li>mmap \u4e0e\u6587\u4ef6\u5e03\u5c40<\/li>\n<li>\u5e8f\u5217\u5316\u5c42&#xff1a;MiniPBCoder \/ CodedInOutData \/ KeyValueHolder<\/li>\n<li>\u5199\u8def\u5f84\u5168\u94fe\u8def<\/li>\n<li>\u8bfb\u8def\u5f84\u5168\u94fe\u8def<\/li>\n<li>\u591a\u8fdb\u7a0b\u4e00\u81f4\u6027\u4e0e\u56db\u5c42\u9501\u6a21\u578b<\/li>\n<li>\u7a7a\u95f4\u7ba1\u7406&#xff1a;\u6269\u5bb9\u3001\u91cd\u6574\u4e0e\u6536\u7f29<\/li>\n<li>\u6570\u636e\u5b89\u5168&#xff1a;CRC \u6821\u9a8c\u4e0e\u81ea\u52a8\u81ea\u6108<\/li>\n<li>AES-CFB128 \u52a0\u5bc6<\/li>\n<li>\u8fdb\u9636\u80fd\u529b&#xff1a;\u8fc7\u671f\u3001compareBeforeSet\u3001\u5185\u5bb9\u901a\u77e5\u3001ashmem<\/li>\n<li>\u4e0e SharedPreferences \u7684\u6e90\u7801\u7ea7\u5bf9\u6bd4<\/li>\n<li>\u9762\u8bd5\u9898\u6e90\u7801\u7ea7\u7cbe\u8bb2&#xff08;Q1\u2013Q8 &#043; \u8bef\u533a\u6e05\u5355&#xff09;<\/li>\n<li>\u9644\u5f55 A&#xff1a;\u5173\u952e\u6e90\u7801\u7d22\u5f15\u8868<\/li>\n<li>\u9644\u5f55 B&#xff1a;\u4e00\u56fe\u6d41\u603b\u7ed3<\/li>\n<hr \/>\n<h3>1. \u603b\u4f53\u67b6\u6784\u4e0e\u5206\u5c42<\/h3>\n<p>MMKV \u4e0d\u662f\u4e00\u4e2a\u300cAndroid \u5e93\u300d&#xff0c;\u800c\u662f\u4e00\u4e2a \u5e26 Java\/OC \u8584\u58f3\u7684 C&#043;&#043; \u5e93\u3002\u7406\u89e3\u6e90\u7801\u7684\u7b2c\u4e00\u6b65&#xff0c;\u662f\u660e\u786e\u804c\u8d23\u8fb9\u754c&#xff1a;Java \u5c42\u51e0\u4e4e\u4e0d\u505a\u4efb\u4f55\u5b58\u50a8\u903b\u8f91&#xff0c;\u5b83\u53ea\u505a\u4e09\u4ef6\u4e8b\u2014\u2014\u52a0\u8f7d so\u3001\u6301\u6709 native \u6307\u9488\u3001\u7f16\u89e3\u7801\u53c2\u6570\u3002<\/p>\n<p>  #mermaid-svg-d2r8TYjVd03u6zxr{font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-d2r8TYjVd03u6zxr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-d2r8TYjVd03u6zxr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-d2r8TYjVd03u6zxr .error-icon{fill:#552222;}#mermaid-svg-d2r8TYjVd03u6zxr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d2r8TYjVd03u6zxr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-d2r8TYjVd03u6zxr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d2r8TYjVd03u6zxr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d2r8TYjVd03u6zxr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-d2r8TYjVd03u6zxr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d2r8TYjVd03u6zxr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d2r8TYjVd03u6zxr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d2r8TYjVd03u6zxr .marker.cross{stroke:#333333;}#mermaid-svg-d2r8TYjVd03u6zxr svg{font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d2r8TYjVd03u6zxr p{margin:0;}#mermaid-svg-d2r8TYjVd03u6zxr .label{font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;color:#333;}#mermaid-svg-d2r8TYjVd03u6zxr .cluster-label text{fill:#333;}#mermaid-svg-d2r8TYjVd03u6zxr .cluster-label span{color:#333;}#mermaid-svg-d2r8TYjVd03u6zxr .cluster-label span p{background-color:transparent;}#mermaid-svg-d2r8TYjVd03u6zxr .label text,#mermaid-svg-d2r8TYjVd03u6zxr span{fill:#333;color:#333;}#mermaid-svg-d2r8TYjVd03u6zxr .node rect,#mermaid-svg-d2r8TYjVd03u6zxr .node circle,#mermaid-svg-d2r8TYjVd03u6zxr .node ellipse,#mermaid-svg-d2r8TYjVd03u6zxr .node polygon,#mermaid-svg-d2r8TYjVd03u6zxr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-d2r8TYjVd03u6zxr .rough-node .label text,#mermaid-svg-d2r8TYjVd03u6zxr .node .label text,#mermaid-svg-d2r8TYjVd03u6zxr .image-shape .label,#mermaid-svg-d2r8TYjVd03u6zxr .icon-shape .label{text-anchor:middle;}#mermaid-svg-d2r8TYjVd03u6zxr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-d2r8TYjVd03u6zxr .rough-node .label,#mermaid-svg-d2r8TYjVd03u6zxr .node .label,#mermaid-svg-d2r8TYjVd03u6zxr .image-shape .label,#mermaid-svg-d2r8TYjVd03u6zxr .icon-shape .label{text-align:center;}#mermaid-svg-d2r8TYjVd03u6zxr .node.clickable{cursor:pointer;}#mermaid-svg-d2r8TYjVd03u6zxr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-d2r8TYjVd03u6zxr .arrowheadPath{fill:#333333;}#mermaid-svg-d2r8TYjVd03u6zxr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-d2r8TYjVd03u6zxr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-d2r8TYjVd03u6zxr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d2r8TYjVd03u6zxr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-d2r8TYjVd03u6zxr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d2r8TYjVd03u6zxr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-d2r8TYjVd03u6zxr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-d2r8TYjVd03u6zxr .cluster text{fill:#333;}#mermaid-svg-d2r8TYjVd03u6zxr .cluster span{color:#333;}#mermaid-svg-d2r8TYjVd03u6zxr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-d2r8TYjVd03u6zxr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-d2r8TYjVd03u6zxr rect.text{fill:none;stroke-width:0;}#mermaid-svg-d2r8TYjVd03u6zxr .icon-shape,#mermaid-svg-d2r8TYjVd03u6zxr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d2r8TYjVd03u6zxr .icon-shape p,#mermaid-svg-d2r8TYjVd03u6zxr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-d2r8TYjVd03u6zxr .icon-shape .label rect,#mermaid-svg-d2r8TYjVd03u6zxr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d2r8TYjVd03u6zxr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-d2r8TYjVd03u6zxr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-d2r8TYjVd03u6zxr :root{&#8211;mermaid-font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;}<\/p>\n<p>         <span class=\"edgeLabel\"><\/span><\/p>\n<p>         <span class=\"edgeLabel\"><\/p>\n<p>nativeHandle (long &#061; C&#043;&#043; \u5bf9\u8c61\u6307\u9488)<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"edgeLabel\"><\/span><\/p>\n<p>         <span class=\"edgeLabel\"><\/span><\/p>\n<p>         <span class=\"edgeLabel\"><\/span><\/p>\n<p>         <span class=\"edgeLabel\"><\/span><\/p>\n<p>         <span class=\"edgeLabel\"><\/span><\/p>\n<p>         <span class=\"edgeLabel\"><\/span><\/p>\n<p>         <span class=\"edgeLabel\"><\/span><\/p>\n<p>         <span class=\"edgeLabel\"><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>\u4e1a\u52a1\u4ee3\u7801kv.encode(key, value)<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>Java \u58f3\u5c42MMKV.java<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>JNI \u6865\u63a5native-bridge.cpp<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>C&#043;&#043; \u95e8\u9762MMKV.cpp<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>IO \u4e0e\u589e\u91cf\u5f15\u64ceMMKV_IO.cpp<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>\u5185\u5b58\u6620\u5c04\u6587\u4ef6MemoryFile.cpp<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>protobuf \u7f16\u89e3\u7801MiniPBCoder \/ CodedInOutData<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>\u8de8\u8fdb\u7a0b\u9501InterProcessLock(.cpp\/_Android.cpp)<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>AES-CFB128aes\/AESCrypt.cpp<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>CRC32crc32\/Checksum.h<\/p>\n<p><\/span><\/p>\n<p>         <span class=\"nodeLabel\"><\/p>\n<p>\u78c1\u76d8\u6587\u4ef6mmap_id &#043; mmap_id.crc<\/p>\n<p><\/span><\/p>\n<p>\u5173\u952e\u7c7b\u4e0e\u804c\u8d23<\/p>\n<table>\n<tr>\u5c42\u6587\u4ef6\u804c\u8d23<\/tr>\n<tbody>\n<tr>\n<td>Java<\/td>\n<td>Android\/&#8230;\/com\/tencent\/mmkv\/MMKV.java<\/td>\n<td>implements SharedPreferences, SharedPreferences.Editor&#xff08;MMKV.java:52&#xff09;&#xff0c;native \u65b9\u6cd5\u58f0\u660e\u96c6\u4e2d\u5728 MMKV.java:1642\u20131751<\/td>\n<\/tr>\n<tr>\n<td>JNI<\/td>\n<td>Android\/&#8230;\/cpp\/native-bridge.cpp<\/td>\n<td>JNI_OnLoad \u52a8\u6001\u6ce8\u518c&#xff08;native-bridge.cpp:59&#xff09;\u3001RegisterNatives \u8868&#xff08;native-bridge.cpp:1101 \u8d77&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>Core \u95e8\u9762<\/td>\n<td>Core\/MMKV.cpp<\/td>\n<td>\u751f\u547d\u5468\u671f\u3001set\/get API\u3001CRC \u52a9\u624b\u3001\u5b9e\u4f8b\u5b57\u5178<\/td>\n<\/tr>\n<tr>\n<td>Core IO<\/td>\n<td>Core\/MMKV_IO.cpp<\/td>\n<td>\u52a0\u8f7d\u3001\u589e\u91cf\u5199\u3001\u591a\u8fdb\u7a0b\u540c\u6b65\u3001\u6269\u5bb9\u91cd\u6574&#xff08;\u5168\u5e93\u6700\u6838\u5fc3\u7684 1900 \u884c&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>Core \u6587\u4ef6<\/td>\n<td>Core\/MemoryFile.cpp &#043; _Android.cpp<\/td>\n<td>fd \u7ba1\u7406\u3001mmap\/munmap\u3001ftruncate\u3001msync\u3001ashmem<\/td>\n<\/tr>\n<tr>\n<td>Core \u9501<\/td>\n<td>Core\/InterProcessLock.cpp &#043; _Android.cpp<\/td>\n<td>\u53ef\u9012\u5f52\u7684 flock\/fcntl \u5c01\u88c5<\/td>\n<\/tr>\n<tr>\n<td>Core \u7f16\u7801<\/td>\n<td>Core\/MiniPBCoder.cpp\u3001CodedInputData.cpp\u3001CodedOutputData.cpp<\/td>\n<td>\u624b\u5199 protobuf wire-format \u5b50\u96c6<\/td>\n<\/tr>\n<tr>\n<td>Core \u5143\u4fe1\u606f<\/td>\n<td>Core\/MMKVMetaInfo.hpp<\/td>\n<td>.crc \u6587\u4ef6\u7684\u5185\u5b58\u7ed3\u6784&#xff08;\u957f\u5ea6\u3001CRC\u3001sequence\u3001IV\u3001flags&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u4e00\u53e5\u8bdd\u603b\u7eb2&#xff1a;MMKV &#061; mmap \u63d0\u4f9b\u7684\u300c\u53ef\u6301\u4e45\u5316\u5185\u5b58\u300d &#043; \u300c\u8ffd\u52a0\u5f0f protobuf \u8bb0\u5f55\u6d41\u300d &#043; \u300c\u5185\u5b58\u54c8\u5e0c\u7d22\u5f15\u300d &#043; \u300c.crc \u5143\u6587\u4ef6\u505a\u6821\u9a8c\u4e0e\u8de8\u8fdb\u7a0b\u4fe1\u4ee4\u300d &#043; \u300cflock \u505a\u4e92\u65a5\u300d\u3002<\/p>\n<hr \/>\n<h3>2. \u521d\u59cb\u5316\u94fe\u8def&#xff1a;Java \u2192 JNI \u2192 C&#043;&#043;<\/h3>\n<h4>2.1 Java \u4fa7&#xff1a;MMKV.initialize(context)<\/h4>\n<p>MMKV.java:91 \u662f\u6700\u5e38\u7528\u7684\u5165\u53e3&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Android\/MMKV\/mmkv\/src\/main\/java\/com\/tencent\/mmkv\/MMKV.java:91<\/span><br \/>\n<span class=\"token keyword\">public<\/span> <span class=\"token keyword\">static<\/span> <span class=\"token class-name\">String<\/span> <span class=\"token function\">initialize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token annotation punctuation\">&#064;NonNull<\/span> <span class=\"token class-name\">Context<\/span> context<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token class-name\">String<\/span> rootDir <span class=\"token operator\">&#061;<\/span> context<span class=\"token punctuation\">.<\/span><span class=\"token function\">getFilesDir<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">getPath<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> <span class=\"token string\">&#034;\/mmkv&#034;<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token class-name\">MMKVLogLevel<\/span> logLevel <span class=\"token operator\">&#061;<\/span> <span class=\"token class-name\">Build<\/span><span class=\"token punctuation\">.<\/span><span class=\"token constant\">DEBUG<\/span> <span class=\"token operator\">?<\/span> <span class=\"token class-name\">LevelDebug<\/span> <span class=\"token operator\">:<\/span> <span class=\"token class-name\">LevelError<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token function\">initialize<\/span><span class=\"token punctuation\">(<\/span>context<span class=\"token punctuation\">,<\/span> rootDir<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">,<\/span> logLevel<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u771f\u6b63\u5e72\u6d3b\u7684\u662f\u5168\u53c2\u91cd\u8f7d MMKV.java:192&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ MMKV.java:192&#xff08;\u8282\u9009&#xff09;<\/span><br \/>\n<span class=\"token keyword\">public<\/span> <span class=\"token keyword\">static<\/span> <span class=\"token class-name\">String<\/span> <span class=\"token function\">initialize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token annotation punctuation\">&#064;NonNull<\/span> <span class=\"token class-name\">Context<\/span> context<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">String<\/span> rootDir<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">LibLoader<\/span> loader<span class=\"token punctuation\">,<\/span><br \/>\n                                <span class=\"token class-name\">MMKVLogLevel<\/span> logLevel<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">MMKVHandler<\/span> handler<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>isDebugBuild<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token function\">enableProcessModeChecker<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ MMKV.java:199&#xff0c;\u4ec5 debug \u5305\u5f00\u542f\u8fdb\u7a0b\u6a21\u5f0f\u68c0\u67e5<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token class-name\">String<\/span> ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">doInitialize<\/span><span class=\"token punctuation\">(<\/span>rootDir<span class=\"token punctuation\">,<\/span> cacheDir<span class=\"token punctuation\">,<\/span> loader<span class=\"token punctuation\">,<\/span> logLevel<span class=\"token punctuation\">,<\/span> gWantLogReDirecting<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>doInitialize&#xff08;MMKV.java:216&#xff09;\u8d1f\u8d23 \u52a0\u8f7d\u52a8\u6001\u5e93 \u5e76\u8c03\u7528 native&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ MMKV.java:216<\/span><br \/>\n<span class=\"token keyword\">private<\/span> <span class=\"token keyword\">static<\/span> <span class=\"token class-name\">String<\/span> <span class=\"token function\">doInitialize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">String<\/span> rootDir<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">String<\/span> cacheDir<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">LibLoader<\/span> loader<span class=\"token punctuation\">,<\/span><br \/>\n                                   <span class=\"token class-name\">MMKVLogLevel<\/span> logLevel<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">boolean<\/span> wantLogReDirecting<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>loader <span class=\"token operator\">!&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        loader<span class=\"token punctuation\">.<\/span><span class=\"token function\">loadLibrary<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;c&#043;&#043;_shared&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        loader<span class=\"token punctuation\">.<\/span><span class=\"token function\">loadLibrary<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;mmkv&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token class-name\">System<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">loadLibrary<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;c&#043;&#043;_shared&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token class-name\">System<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">loadLibrary<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;mmkv&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>          <span class=\"token comment\">\/\/ MMKV.java:226<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>gInstance <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        gInstance <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token function\">jniInitialize<\/span><span class=\"token punctuation\">(<\/span>rootDir<span class=\"token punctuation\">,<\/span> cacheDir<span class=\"token punctuation\">,<\/span> logLevel<span class=\"token punctuation\">.<\/span><span class=\"token function\">ordinal<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> wantLogReDirecting<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> rootDir<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u6ce8\u610f\u4e24\u70b9<\/p>\n<ul>\n<li>cacheDir \u88ab\u4f20\u4e0b\u53bb&#xff0c;\u7528\u4e8e .tmp \u76ee\u5f55&#xff08;\u539f\u5b50\u5199\u6587\u4ef6\u65f6\u5148\u5199\u4e34\u65f6\u6587\u4ef6\u518d rename&#xff0c;\u89c1 Core\/MemoryFile.cpp \u7684 copyFile&#xff09;\u3002<\/li>\n<li>\u6574\u4e2a Java \u5c42\u7528 gInstance \u505a\u5355\u4f8b&#xff0c;jniInitialize \u53ea\u4f1a\u771f\u6b63\u6267\u884c\u4e00\u6b21\u3002<\/li>\n<\/ul>\n<h4>2.2 JNI \u4fa7&#xff1a;\u52a8\u6001\u6ce8\u518c\u800c\u975e\u540d\u5b57\u5339\u914d<\/h4>\n<p>native-bridge.cpp:59 \u7684 JNI_OnLoad \u5728 System.loadLibrary \u65f6\u88ab\u7cfb\u7edf\u56de\u8c03&#xff0c;\u968f\u540e registerNativeMethods&#xff08;native-bridge.cpp:1158&#xff09;\u7528\u4e00\u5f20\u663e\u5f0f\u8868\u628a Java native \u65b9\u6cd5\u7ed1\u5b9a\u5230 C \u51fd\u6570&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Android\/&#8230;\/cpp\/native-bridge.cpp:1101&#xff08;\u8868\u8282\u9009&#xff09;<\/span><br \/>\n<span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;jniInitialize&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;(Ljava\/lang\/String;Ljava\/lang\/String;IZ)V&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> mmkv<span class=\"token double-colon punctuation\">::<\/span>jniInitialize_2<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n<span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;encodeBool&#034;<\/span><span class=\"token punctuation\">,<\/span>   <span class=\"token string\">&#034;(JLjava\/lang\/String;Z)Z&#034;<\/span><span class=\"token punctuation\">,<\/span>                     <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> _encodeBool<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n<span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><\/p>\n<p>\u4e3a\u4ec0\u4e48\u7528 RegisterNatives \u800c\u4e0d\u53bb\u8c03 JNI_OnLoad&#xff1f;<\/p>\n<li>\u7b26\u53f7\u4e0d\u7528\u6309 Java_com_tencent_mmkv_MMKV_xxx \u89c4\u5219\u547d\u540d&#xff0c;C&#043;&#043; \u4fa7\u53ef\u81ea\u7531\u653e\u8fdb namespace mmkv&#xff1b;<\/li>\n<li>\u7b26\u53f7\u4e0d\u5bfc\u51fa&#xff0c;\u9006\u5411\u540e\u96be\u4ee5\u5b9a\u4f4d&#xff0c;\u8fd9\u662f\u7b2c\u4e00\u5c42\u81ea\u4fdd\u62a4&#xff1b;<\/li>\n<li>\u67e5\u8868\u6bd4\u6309\u540d\u89e3\u6790\u5feb&#xff08;\u5bf9\u9996\u6b21\u8c03\u7528\u6709\u610f\u4e49&#xff09;\u3002<\/li>\n<p>jniInitialize_2&#xff08;native-bridge.cpp:143&#xff09;\u628a\u8def\u5f84\u8f6c\u6210 std::string \u540e\u8c03\u7528 MMKV::initializeMMKV(&#8230;)&#xff0c;\u5e76\u628a cacheDir \u5b58\u8fdb\u5168\u5c40 g_android_tmpDir&#xff08;native-bridge.cpp:153&#xff09;\u3002<\/p>\n<h4>2.3 Core \u4fa7&#xff1a;\u4e00\u6b21\u6027\u7684 initialize()<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:200<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">initializeMMKV<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> MMKVPath_t <span class=\"token operator\">&amp;<\/span>rootDir<span class=\"token punctuation\">,<\/span> MMKVLogLevel logLevel<span class=\"token punctuation\">,<\/span> mmkv<span class=\"token double-colon punctuation\">::<\/span>LogHandler handler<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>g_runtimeLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token class-name\">ThreadLock<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">ThreadOnce<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>once_control<span class=\"token punctuation\">,<\/span> initialize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ \u53ea\u6267\u884c\u4e00\u6b21<\/span><br \/>\n    g_rootDir <span class=\"token operator\">&#061;<\/span> rootDir<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">mkPath<\/span><span class=\"token punctuation\">(<\/span>g_rootDir<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                   <span class=\"token comment\">\/\/ \u9012\u5f52\u5efa\u76ee\u5f55<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u88ab ThreadOnce \u4fdd\u62a4\u7684\u90a3\u4e2a\u9759\u6001 initialize()&#xff08;Core\/MMKV.cpp:160&#xff09;\u505a\u4e86 \u6027\u80fd\u5173\u952e\u7684\u4e00\u6b65&#xff1a;\u8fd0\u884c\u65f6\u6307\u4ee4\u96c6\u63a2\u6d4b&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:160<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token function\">initialize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    g_instanceDic <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> unordered_map<span class=\"token operator\">&lt;<\/span>string<span class=\"token punctuation\">,<\/span> MMKV <span class=\"token operator\">*<\/span><span class=\"token operator\">&gt;<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    g_instanceLock <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token function\">ThreadLock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    g_instanceLock<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">initialize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>    mmkv<span class=\"token double-colon punctuation\">::<\/span>DEFAULT_MMAP_SIZE <span class=\"token operator\">&#061;<\/span> mmkv<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">getPageSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>       <span class=\"token comment\">\/\/ :165 \u901a\u5e38 &#061; 4096<\/span><br \/>\n    <span class=\"token function\">MMKVInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;version %s, page size %d, arch %s&#034;<\/span><span class=\"token punctuation\">,<\/span> MMKV_VERSION<span class=\"token punctuation\">,<\/span> DEFAULT_MMAP_SIZE<span class=\"token punctuation\">,<\/span> MMKV_ABI<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token macro property\"><span class=\"token directive-hash\">#<\/span><span class=\"token directive keyword\">if<\/span> <span class=\"token expression\"><span class=\"token function\">defined<\/span><span class=\"token punctuation\">(<\/span>__aarch64__<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token function\">defined<\/span><span class=\"token punctuation\">(<\/span>__linux__<span class=\"token punctuation\">)<\/span><\/span><\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> hwcaps <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">getauxval<\/span><span class=\"token punctuation\">(<\/span>AT_HWCAP<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                   <span class=\"token comment\">\/\/ :170<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>hwcaps <span class=\"token operator\">&amp;<\/span> HWCAP_AES<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>                            <span class=\"token comment\">\/\/ :172<\/span><br \/>\n        openssl<span class=\"token double-colon punctuation\">::<\/span>AES_set_encrypt_key <span class=\"token operator\">&#061;<\/span> openssl_aes_armv8_set_encrypt_key<span class=\"token punctuation\">;<\/span><br \/>\n        openssl<span class=\"token double-colon punctuation\">::<\/span>AES_encrypt <span class=\"token operator\">&#061;<\/span> openssl_aes_armv8_encrypt<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>hwcaps <span class=\"token operator\">&amp;<\/span> HWCAP_CRC32<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        CRC32 <span class=\"token operator\">&#061;<\/span> mmkv<span class=\"token double-colon punctuation\">::<\/span>armv8_crc32<span class=\"token punctuation\">;<\/span>                       <span class=\"token comment\">\/\/ :184 \u786c\u4ef6 CRC32<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#<\/span><span class=\"token directive keyword\">endif<\/span><\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u4e09\u4e2a\u9ad8\u9891\u8003\u70b9\u85cf\u5728\u91cc\u9762&#xff1a;<\/p>\n<ul>\n<li>DEFAULT_MMAP_SIZE &#061; getPageSize()&#xff1a;\u300cMMKV \u6309\u5185\u5b58\u9875&#xff08;4KB&#xff09;\u4e3a\u7c92\u5ea6\u5206\u914d\/\u6269\u5c55\u300d\u8fd9\u53e5\u8bdd\u7684\u6e90\u7801\u51fa\u5904\u3002\u540c\u65f6\u5b83\u4e5f\u662f\u300c\u5355\u6587\u4ef6\u6700\u5c0f\u6620\u5c04\u5927\u5c0f\u300d\u3002<\/li>\n<li>CRC32 \u4e0e AES_* \u662f \u51fd\u6570\u6307\u9488&#xff0c;\u5728 aarch64 \u4e0a\u88ab\u66ff\u6362\u6210 ARMv8 \u786c\u4ef6\u6307\u4ee4\u5b9e\u73b0\u3002\u6240\u4ee5\u300cMMKV \u7684 CRC \u6821\u9a8c\u5c45\u7136\u4e0d\u5f71\u54cd\u6027\u80fd\u300d\u7684\u5e95\u6c14\u6765\u81ea CRC32 \u6307\u4ee4&#xff0c;\u800c\u4e0d\u662f\u8f6f\u4ef6\u67e5\u8868\u3002<\/li>\n<li>\u6574\u4e2a\u521d\u59cb\u5316\u7528 ThreadOnce&#xff0c;\u591a\u7ebf\u7a0b\u5e76\u53d1 initialize \u5b89\u5168\u3002<\/li>\n<\/ul>\n<hr \/>\n<h3>3. \u5b9e\u4f8b\u7ba1\u7406\u4e0e\u7f13\u5b58&#xff08;\u4e0d\u662f LRU&#xff09;<\/h3>\n<h4>3.1 mmkvWithID \u7684\u771f\u5b9e\u7f13\u5b58\u7ed3\u6784<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:60<\/span><br \/>\nunordered_map<span class=\"token operator\">&lt;<\/span>string<span class=\"token punctuation\">,<\/span> MMKV <span class=\"token operator\">*<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token operator\">*<\/span>g_instanceDic<span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:233<\/span><br \/>\nMMKV <span class=\"token operator\">*<\/span><span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">mmkvWithID<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> string <span class=\"token operator\">&amp;<\/span>mmapID<span class=\"token punctuation\">,<\/span> MMKVMode mode<span class=\"token punctuation\">,<\/span> string <span class=\"token operator\">*<\/span>cryptKey<span class=\"token punctuation\">,<\/span><br \/>\n                       MMKVPath_t <span class=\"token operator\">*<\/span>rootPath<span class=\"token punctuation\">,<\/span> size_t expectedCapacity<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>g_instanceLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                 <span class=\"token comment\">\/\/ :238<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> mmapKey <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">mmapedKVKey<\/span><span class=\"token punctuation\">(<\/span>mmapID<span class=\"token punctuation\">,<\/span> rootPath<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> itr <span class=\"token operator\">&#061;<\/span> g_instanceDic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">find<\/span><span class=\"token punctuation\">(<\/span>mmapKey<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>     <span class=\"token comment\">\/\/ :241<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>itr <span class=\"token operator\">!&#061;<\/span> g_instanceDic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">end<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        MMKV <span class=\"token operator\">*<\/span>kv <span class=\"token operator\">&#061;<\/span> itr<span class=\"token operator\">-&gt;<\/span>second<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> kv<span class=\"token punctuation\">;<\/span>                               <span class=\"token comment\">\/\/ \u547d\u4e2d\u76f4\u63a5\u590d\u7528<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> kv <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token function\">MMKV<\/span><span class=\"token punctuation\">(<\/span>mmapID<span class=\"token punctuation\">,<\/span> mode<span class=\"token punctuation\">,<\/span> cryptKey<span class=\"token punctuation\">,<\/span> rootPath<span class=\"token punctuation\">,<\/span> expectedCapacity<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>g_instanceDic<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">[<\/span>mmapKey<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> kv<span class=\"token punctuation\">;<\/span>              <span class=\"token comment\">\/\/ :257<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> kv<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h4>\u3010\u7ea0\u504f \u00b7 \u91cd\u8981\u3011MMKV \u7684[ket-value]\u7f13\u5b58 \u4e0d\u662f LRU<\/h4>\n<p>\u7f51\u4e0a\u79f0\u300cMMKV \u7528 LRU \u6dd8\u6c70\u5b9e\u4f8b\u3001\u81ea\u52a8 munmap \u91ca\u653e\u5185\u5b58\u300d\u3002v1.3.16 \u6e90\u7801\u4e2d\u4e0d\u5b58\u5728\u4efb\u4f55 LRU \u7ed3\u6784&#xff1a;<\/p>\n<ul>\n<li>\u5bb9\u5668\u662f\u88f8\u7684 unordered_map&lt;string, MMKV *&gt;&#xff08;Core\/MMKV.cpp:60&#xff09;&#xff0c;\u6ca1\u6709\u8bbf\u95ee\u8ba1\u6570\u3001\u6ca1\u6709\u6dd8\u6c70\u961f\u5217&#xff1b;<\/li>\n<li>\u5b9e\u4f8b\u4e00\u65e6 new \u51fa\u6765\u5c31\u5e38\u9a7b&#xff0c;\u53ea\u6709\u4e09\u5904\u4f1a munmap&#xff1a;\n<li>MMKV::onExit()&#xff08;Core\/MMKV.cpp:262&#xff09;\u2014\u2014\u904d\u5386\u5b57\u5178 sync() &#043; clearMemoryCache() &#043; delete&#xff1b;<\/li>\n<li>MMKV::clearMemoryCache(mmapID) \u9759\u6001\/\u5b9e\u4f8b\u7248\u672c&#xff08;Core\/MMKV.cpp:302&#xff09;&#xff1b;<\/li>\n<li>MemoryFile::truncate() \u5185\u90e8\u4e3a\u91cd\u65b0\u6620\u5c04\u800c\u505a\u7684\u4e34\u65f6 munmap&#xff08;Core\/MemoryFile.cpp:173&#xff09;\u3002<\/li>\n<\/li>\n<\/ul>\n<p>\u771f\u5b9e\u7ed3\u8bba&#xff1a;MMKV \u7684\u300c\u5185\u5b58\u5360\u7528\u300d&#061; \u6240\u6709\u5df2\u521b\u5efa\u5b9e\u4f8b\u7684\u6587\u4ef6\u6620\u5c04\u4e4b\u548c\u3002\u56e0\u4e3a mmap \u7684\u662f MAP_SHARED \u6587\u4ef6\u9875&#xff0c;\u8fd9\u4e9b\u9875\u662f\u53ef\u56de\u6536\u7684 page cache&#xff0c;\u5185\u5b58\u7d27\u5f20\u65f6\u5185\u6838\u53ef\u4ee5\u76f4\u63a5\u6362\u51fa\u800c\u4e0d\u4e22\u6570\u636e&#xff0c;\u6240\u4ee5\u5e38\u9a7b\u6620\u5c04 \u2260 \u5e38\u9a7b RSS \u538b\u529b\u3002\u8fd9\u624d\u662f MMKV \u4e0d\u9700\u8981 LRU \u7684\u539f\u56e0\u3002<\/p>\n<h4>3.2 Java \u4fa7\u7684 nativeHandle<\/h4>\n<p>Java \u5c42\u7684 MMKV \u5bf9\u8c61\u53ea\u662f\u4e00\u4e2a \u6307\u9488\u5305\u88c5&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ MMKV.java:601<\/span><br \/>\n<span class=\"token keyword\">private<\/span> <span class=\"token keyword\">static<\/span> <span class=\"token class-name\">MMKV<\/span> <span class=\"token function\">checkProcessMode<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">long<\/span> handle<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">String<\/span> mmapID<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">int<\/span> mode<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">throws<\/span> <span class=\"token class-name\">RuntimeException<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>handle <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">throw<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">RuntimeException<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;Fail to create an MMKV instance [&#034;<\/span> <span class=\"token operator\">&#043;<\/span> mmapID <span class=\"token operator\">&#043;<\/span> <span class=\"token string\">&#034;] in JNI&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>isProcessModeCheckerEnabled<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token punctuation\">(<\/span>handle<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">synchronized<\/span> <span class=\"token punctuation\">(<\/span>checkedHandleSet<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>checkedHandleSet<span class=\"token punctuation\">.<\/span><span class=\"token function\">contains<\/span><span class=\"token punctuation\">(<\/span>handle<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span><span class=\"token function\">checkProcessMode<\/span><span class=\"token punctuation\">(<\/span>handle<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>      <span class=\"token comment\">\/\/ \u8c03 native \u63a2\u6d4b<\/span><br \/>\n                <span class=\"token keyword\">throw<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">IllegalArgumentException<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;Opening a multi-process MMKV instance [&#034;<\/span><br \/>\n                        <span class=\"token operator\">&#043;<\/span> mmapID <span class=\"token operator\">&#043;<\/span> <span class=\"token string\">&#034;] with SINGLE_PROCESS_MODE!&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n            checkedHandleSet<span class=\"token punctuation\">.<\/span><span class=\"token function\">add<\/span><span class=\"token punctuation\">(<\/span>handle<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token punctuation\">(<\/span>handle<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<ul>\n<li>handle &#061; C&#043;&#043; \u4fa7 MMKV* \u7684 reinterpret_cast&lt;int64_t&gt;&#xff1b;<\/li>\n<li>\u5b9e\u4f8b\u7ea7 native \u65b9\u6cd5\u7b2c\u4e00\u4e2a\u53c2\u6570\u4e00\u5f8b\u662f long handle&#xff08;MMKV.java:1642\u20131751 \u7684 private static native \u58f0\u660e\u5757&#xff09;&#xff1b;\u5e26 _2 \u540e\u7f00\u7684\u91cd\u8f7d\u591a\u4e00\u4e2a int expireDurationInSecond&#xff0c;\u5bf9\u5e94 C&#043;&#043; \u7684 set(value, key, expireDuration)&#xff1b;<\/li>\n<li>Java \u5bf9\u8c61\u53ef\u4ee5\u88ab GC&#xff0c;C&#043;&#043; \u5b9e\u4f8b\u4e0d\u4f1a\u2014\u2014\u6240\u4ee5\u300cMMKV \u6cc4\u6f0f Activity\u300d\u7684\u98ce\u9669\u70b9\u5728 Java \u5c42&#xff1a;MMKV \u5bf9\u8c61\u4e0d\u6301\u6709 Context&#xff08;initialize \u53ea\u7528\u4e86\u4e00\u6b21 getFilesDir()&#xff09;&#xff0c;\u8fd9\u662f\u5b83\u5929\u751f\u4e0d\u6cc4\u6f0f\u7684\u539f\u56e0&#xff0c;\u800c\u4e0d\u662f\u300c\u7528\u4e86\u5f31\u5f15\u7528\u300d\u3002<\/li>\n<\/ul>\n<h4>\u3010\u7ea0\u504f\u3011\u300cMMKV \u7528\u5f31\u5f15\u7528\u5173\u8054 Context\u300d<\/h4>\n<p>MMKV.java \u4e2d \u6ca1\u6709 WeakReference&lt;Context&gt;\u3002\u5b83\u5728 initialize(Context) \u91cc\u53ea\u540c\u6b65\u8bfb\u53d6 context.getFilesDir() \u548c getCacheDir() \u4e24\u4e2a\u5b57\u7b26\u4e32&#xff0c;\u4e4b\u540e\u4e0e Context \u518d\u65e0\u5173\u7cfb\u3002\u6b63\u786e\u8bf4\u6cd5\u662f&#xff1a;MMKV \u4e0d\u957f\u671f\u6301\u6709 Context&#xff0c;\u56e0\u6b64\u4e0d\u5b58\u5728 Activity \u6cc4\u6f0f\u8def\u5f84\u3002<\/p>\n<h4>3.3 MMKVMode \u4f4d\u5b9a\u4e49<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.h<\/span><br \/>\n<span class=\"token keyword\">enum<\/span> <span class=\"token class-name\">MMKVMode<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    MMKV_SINGLE_PROCESS <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1<\/span> <span class=\"token operator\">&lt;&lt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    MMKV_MULTI_PROCESS  <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1<\/span> <span class=\"token operator\">&lt;&lt;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    MMKV_CONTEXT_MODE_MULTI_PROCESS <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1<\/span> <span class=\"token operator\">&lt;&lt;<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">,<\/span>   <span class=\"token comment\">\/\/ Android \u79c1\u6709<\/span><br \/>\n    MMKV_ASHMEM         <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1<\/span> <span class=\"token operator\">&lt;&lt;<\/span> <span class=\"token number\">3<\/span><span class=\"token punctuation\">,<\/span>               <span class=\"token comment\">\/\/ \u5171\u4eab\u5185\u5b58(\u533f\u540d)\u6a21\u5f0f<\/span><br \/>\n    MMKV_BACKUP         <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1<\/span> <span class=\"token operator\">&lt;&lt;<\/span> <span class=\"token number\">4<\/span><span class=\"token punctuation\">,<\/span>               <span class=\"token comment\">\/\/ \u53ea\u8bfb\u5907\u4efd\u7528<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>\u5176\u4e2d MMKV_ASHMEM \u53ea\u5728 Android \u6709\u610f\u4e49&#xff08;Core\/MMKV_Android.cpp:90 \u8d77\u7684\u79c1\u6709\u6784\u9020\u51fd\u6570&#xff09;&#xff0c;\u7528\u4e8e \u8de8\u5e94\u7528\u5171\u4eab&#xff08;\u914d\u5408 MMKVContentProvider \u4f20 fd&#xff09;&#xff1b;MMKV_BACKUP \u7528\u4e8e backupTo() \u65f6\u4ee5\u53ea\u8bfb\u65b9\u5f0f\u52a0\u8f7d\u3002<\/p>\n<hr \/>\n<h3>4. mmap \u4e0e\u6587\u4ef6\u5e03\u5c40<\/h3>\n<h4>4.1 \u4e00\u4e2a MMKV \u5b9e\u4f8b &#061; \u4e24\u4e2a\u6587\u4ef6<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:81&#xff08;\u6784\u9020\u51fd\u6570\u521d\u59cb\u5316\u5217\u8868&#xff0c;\u8282\u9009&#xff09;<\/span><br \/>\n<span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">MMKV<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> string <span class=\"token operator\">&amp;<\/span>mmapID<span class=\"token punctuation\">,<\/span> MMKVMode mode<span class=\"token punctuation\">,<\/span> string <span class=\"token operator\">*<\/span>cryptKey<span class=\"token punctuation\">,<\/span> MMKVPath_t <span class=\"token operator\">*<\/span>rootPath<span class=\"token punctuation\">,<\/span> size_t expectedCapacity<span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token operator\">:<\/span> <span class=\"token function\">m_mmapID<\/span><span class=\"token punctuation\">(<\/span>mmapID<span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_path<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">mappedKVPathWithID<\/span><span class=\"token punctuation\">(<\/span>m_mmapID<span class=\"token punctuation\">,<\/span> mode<span class=\"token punctuation\">,<\/span> rootPath<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>      <span class=\"token comment\">\/\/ \u6570\u636e\u6587\u4ef6<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_crcPath<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">crcPathWithID<\/span><span class=\"token punctuation\">(<\/span>m_mmapID<span class=\"token punctuation\">,<\/span> mode<span class=\"token punctuation\">,<\/span> rootPath<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>        <span class=\"token comment\">\/\/ \u5143\u6587\u4ef6&#xff1a;&lt;id&gt;.crc<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_dic<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_dicCrypt<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_expectedCapacity<\/span><span class=\"token punctuation\">(<\/span>std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token generic-function\"><span class=\"token function\">max<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>DEFAULT_MMAP_SIZE<span class=\"token punctuation\">,<\/span><br \/>\n                            <span class=\"token generic-function\"><span class=\"token function\">roundUp<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>expectedCapacity<span class=\"token punctuation\">,<\/span> DEFAULT_MMAP_SIZE<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>   <span class=\"token comment\">\/\/ :87<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_file<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token function\">MemoryFile<\/span><span class=\"token punctuation\">(<\/span>m_path<span class=\"token punctuation\">,<\/span> m_expectedCapacity<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>        <span class=\"token comment\">\/\/ :88<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_metaFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token function\">MemoryFile<\/span><span class=\"token punctuation\">(<\/span>m_crcPath<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>                     <span class=\"token comment\">\/\/ :89<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_metaInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token function\">MMKVMetaInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>                            <span class=\"token comment\">\/\/ :90<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_crypter<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_lock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token function\">ThreadLock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>                                  <span class=\"token comment\">\/\/ :92 \u8fdb\u7a0b\u5185\u4e92\u65a5\u9501<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_fileLock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token function\">FileLock<\/span><span class=\"token punctuation\">(<\/span>m_metaFile<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFd<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>             <span class=\"token comment\">\/\/ :93 \u2605\u9501\u52a0\u5728 .crc \u7684 fd \u4e0a<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_sharedProcessLock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token function\">InterProcessLock<\/span><span class=\"token punctuation\">(<\/span>m_fileLock<span class=\"token punctuation\">,<\/span> SharedLockType<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>     <span class=\"token comment\">\/\/ :94<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_exclusiveProcessLock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">new<\/span> <span class=\"token function\">InterProcessLock<\/span><span class=\"token punctuation\">(<\/span>m_fileLock<span class=\"token punctuation\">,<\/span> ExclusiveLockType<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token comment\">\/\/ :95<\/span><br \/>\n    <span class=\"token punctuation\">,<\/span> <span class=\"token function\">m_isInterProcess<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>mode <span class=\"token operator\">&amp;<\/span> MMKV_MULTI_PROCESS<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">!&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>      <span class=\"token comment\">\/\/ :96<\/span><\/p>\n<p>\u6784\u9020\u51fd\u6570\u5c3e\u90e8\u4e24\u884c\u975e\u5e38\u91cd\u8981&#xff0c;\u5b83\u4eec\u89e3\u91ca\u4e86\u4e00\u4e2a\u5e38\u89c1\u7591\u95ee&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:117<\/span><br \/>\nm_sharedProcessLock<span class=\"token operator\">-&gt;<\/span>m_enable <span class=\"token operator\">&#061;<\/span> m_isInterProcess<span class=\"token punctuation\">;<\/span><br \/>\nm_exclusiveProcessLock<span class=\"token operator\">-&gt;<\/span>m_enable <span class=\"token operator\">&#061;<\/span> m_isInterProcess<span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :118<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:120  sensitive zone<\/span><br \/>\n<span class=\"token comment\">\/*{<br \/>\n    SCOPED_LOCK(m_sharedProcessLock);<br \/>\n    loadFromFile();<br \/>\n}*\/<\/span>                                                     <span class=\"token comment\">\/\/ :124 \u2605\u88ab\u6ce8\u91ca\u6389\u4e86<\/span><\/p>\n<ul>\n<li>\u5355\u8fdb\u7a0b\u6a21\u5f0f\u4e0b\u6587\u4ef6\u9501\u662f\u7a7a\u64cd\u4f5c&#xff08;m_enable &#061;&#061; false&#xff09;&#xff0c;\u4e0d\u4ea7\u751f\u4efb\u4f55 flock \u7cfb\u7edf\u8c03\u7528&#xff0c;\u6027\u80fd\u4e0e\u7eaf\u5185\u5b58 map \u51e0\u4e4e\u4e00\u81f4&#xff1b;<\/li>\n<li>\u6784\u9020\u51fd\u6570\u4e0d\u52a0\u8f7d\u6570\u636e&#xff0c;loadFromFile() \u88ab\u663e\u5f0f\u6ce8\u91ca\u6389&#xff08;Core\/MMKV.cpp:121-124&#xff0c;Android \u7248\u540c\u6837\u6ce8\u91ca\u5728 Core\/MMKV_Android.cpp:84-88\u3001:133-137&#xff09;\u2192 MMKV \u662f \u61d2\u52a0\u8f7d&#xff08;lazy load&#xff09;&#xff1a;\u7b2c\u4e00\u6b21 get\/set \u624d loadFromFile() \u8bfb meta\u3001\u6821\u9a8c CRC\u3001\u626b\u63cf\u8bb0\u5f55\u3001\u5efa\u5b57\u5178\u3002\u8fd9\u662f\u300c\u521b\u5efa MMKV \u5b9e\u4f8b\u51e0\u4e4e\u96f6\u6210\u672c\u300d\u7684\u6e90\u7801\u4f9d\u636e\u3002<\/li>\n<\/ul>\n<p>\u3010\u7cbe\u5ea6\u63d0\u793a\u3011\u61d2\u7684\u662f\u300c\u89e3\u7801\u300d&#xff0c;\u4e0d\u662f\u300cmmap\u300d\u3002 \u6784\u9020\u51fd\u6570\u521d\u59cb\u5316\u5217\u8868\u91cc\u7684 m_file(new MemoryFile(m_path, m_expectedCapacity))&#xff08;Core\/MMKV.cpp:88&#xff09;\u5c31\u5df2\u7ecf open &#043; ftruncate &#043; zeroFill &#043; mmap \u4e86&#xff1a;MemoryFile \u6784\u9020\u51fd\u6570 \u2192 reloadFromFile()&#xff08;POSIX Core\/MemoryFile.cpp:53-55 \/ Android Core\/MemoryFile_Android.cpp:73-76&#xff09;\u2192 getFileSize \u2192 truncate(roundSize) \u2192 mmap()&#xff08;Core\/MemoryFile.cpp:195-205&#xff09;\u3002 \u88ab\u63a8\u8fdf\u7684\u53ea\u662f\u8bfb\u61c2\u6587\u4ef6\u5185\u5bb9\u8fd9\u4e00\u6b65&#xff1a;m_actualSize &#061; 0\u3001m_output &#061; nullptr&#xff08;Core\/MMKV.cpp:97-98&#xff09;\u3001m_dic \u662f\u7a7a map\u3002\u6240\u4ee5\u51c6\u786e\u8868\u8ff0\u662f\u300c\u5efa\u6620\u5c04\u5728\u6784\u9020\u671f&#xff0c;\u89e3\u5b57\u5178\u5728\u9996\u6b21\u8bbf\u95ee\u300d\u3002<\/p>\n<p>\u4f5c\u8005\u672c\u4eba\u5728\u6e90\u7801\u91cc\u7559\u4e86\u6ce8\u91ca\u627f\u8ba4\u8fd9\u4e2a\u8bbe\u8ba1&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:73-82  loadFromFile() \u5f00\u5934<\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">reloadFromFile<\/span><span class=\"token punctuation\">(<\/span>m_expectedCapacity<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_isInterProcess<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token comment\">\/\/ the file size may change by other process between instance creation and loadFromFile<\/span><br \/>\n    <span class=\"token comment\">\/\/ because we have lazy load                                    \/\/ :77 \u2605\u5b98\u65b9\u6ce8\u91ca&#xff1a;\u6211\u4eec\u5c31\u662f\u61d2\u52a0\u8f7d<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> actualFileSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getActualFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>actualFileSize <span class=\"token operator\">!&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">reloadFromFile<\/span><span class=\"token punctuation\">(<\/span>m_expectedCapacity<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :80 \u6784\u9020\u671f\u4e4b\u540e\u6587\u4ef6\u88ab\u522b\u4eba\u6dfb\u52a0\u5185\u5bb9 \u2192 \u91cd\u65b0 mmap<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u5373&#xff1a;\u56e0\u4e3a\u6784\u9020\u671f\u53ea mmap \u4e0d\u8bfb&#xff0c;\u4ece\u300c\u521b\u5efa\u5b9e\u4f8b\u300d\u5230\u300c\u9996\u6b21\u8bbf\u95ee\u300d\u8fd9\u6bb5\u65f6\u95f4\u91cc\u522b\u7684\u8fdb\u7a0b\u53ef\u80fd\u5df2\u7ecf\u628a\u6587\u4ef6\u6269\u5bb9&#xff0c;\u6240\u4ee5 loadFromFile() \u5fc5\u987b\u56de\u5934\u6bd4\u5bf9\u771f\u5b9e\u6587\u4ef6\u5927\u5c0f\u5e76\u6309\u9700\u91cd\u65b0\u6620\u5c04 \u2014\u2014 \u8fd9\u6bb5\u9632\u5fa1\u4ee3\u7801\u7684\u5b58\u5728\u672c\u8eab\u5c31\u662f\u61d2\u52a0\u8f7d\u8bbe\u8ba1\u7684\u8bc1\u636e\u3002<\/p>\n<p>\u61d2\u52a0\u8f7d\u7684\u5f00\u5173\u4e0e\u6d88\u8d39\u70b9&#xff08;\u4e00\u4e2a bool \u4e32\u8d77\u5168\u94fe\u8def&#xff09;&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ \u7f6e\u4f4d&#xff1a;\u6784\u9020\u51fd\u6570&#xff08;\u4e09\u5904\u6784\u9020\u51fd\u6570\u90fd\u4e00\u6837&#xff09;<\/span><br \/>\nm_needLoadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span>            <span class=\"token comment\">\/\/ Core\/MMKV.cpp:111 \/ MMKV_Android.cpp:76, :125<\/span><\/p>\n<p><span class=\"token comment\">\/\/ \u6d88\u8d39&#xff1a;\u552f\u4e00\u8bfb\u8be5\u6807\u5fd7\u7684\u5730\u65b9<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">checkLoadData<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>          <span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:305<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_needLoadFromFile<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>         <span class=\"token comment\">\/\/ :306<\/span><br \/>\n        <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_sharedProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        m_needLoadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :309 \u2605\u53ea\u52a0\u8f7d\u8fd9\u4e00\u6b21<\/span><br \/>\n        <span class=\"token function\">loadFromFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>               <span class=\"token comment\">\/\/ :310<\/span><br \/>\n        <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_isInterProcess<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>          <span class=\"token comment\">\/\/ :313 \u5355\u8fdb\u7a0b&#xff1a;\u4e4b\u540e checkLoadData \u76f4\u63a5 return&#xff0c;\u96f6\u5f00\u9500<\/span><br \/>\n        <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token comment\">\/\/ \u591a\u8fdb\u7a0b&#xff1a;\u6bd4 sequence \/ crcDigest \/ fileSize&#xff0c;\u89c1\u7b2c 8 \u7ae0<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ \u590d\u4f4d&#xff1a;\u786e\u8ba4\u65e0\u9700\u91cd\u8f7d<\/span><br \/>\nm_needLoadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span>           <span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:143&#xff08;loadFromFile \u7ed3\u5c3e&#xff09;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ \u53cd\u5411\u7f6e\u4f4d&#xff1a;\u4e3b\u52a8\u4e22\u5f03\u5185\u5b58\u5b57\u5178&#xff0c;\u903c\u4e0b\u6b21\u8bbf\u95ee\u91cd\u65b0 load<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">clearMemoryCache<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">bool<\/span> keepSpace<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>   <span class=\"token comment\">\/\/ Core\/MMKV.cpp:302<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_needLoadFromFile<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>         <span class=\"token comment\">\/\/ :304 \u672c\u6765\u5c31\u6ca1\u52a0\u8f7d\u8fc7 \u2192 \u4ec0\u4e48\u90fd\u4e0d\u7528\u505a<\/span><br \/>\n    m_needLoadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span>                  <span class=\"token comment\">\/\/ :308<\/span><\/p>\n<p>checkLoadData() \u88ab\u585e\u5728\u6bcf\u4e00\u4e2a\u4f1a\u78b0\u6570\u636e\u7684\u5165\u53e3\u7b2c\u4e00\u884c&#xff0c;\u8fd9\u5c31\u662f\u300c\u9996\u6b21 get\/set \u624d\u771f\u6b63\u52a0\u8f7d\u300d\u7684\u5b9e\u73b0\u65b9\u5f0f<\/p>\n<table>\n<tr>\u5165\u53e3\u4f4d\u7f6e\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>setDataForKey<\/td>\n<td>Core\/MMKV_IO.cpp:587<\/td>\n<td>\u2605\u6240\u6709 encode \u7684\u516c\u5171\u4e0b\u6e38<\/td>\n<\/tr>\n<tr>\n<td>getRawDataForKey<\/td>\n<td>Core\/MMKV_IO.cpp:544<\/td>\n<td>\u2605\u6240\u6709 decode \u7684\u516c\u5171\u4e0b\u6e38<\/td>\n<\/tr>\n<tr>\n<td>reKey \/ trim \/ clearAll<\/td>\n<td>Core\/MMKV_IO.cpp:1348 \/ :1418 \/ :1462<\/td>\n<td>\u6362\u5bc6\u94a5\u3001\u7f29\u5bb9\u3001\u6e05\u7a7a<\/td>\n<\/tr>\n<tr>\n<td>containsKey \/ count \/ totalSize \/ actualSize<\/td>\n<td>Core\/MMKV.cpp:1052 \/ :1067 \/ :1083 \/ :1089<\/td>\n<td>\u8fde\u5143\u4fe1\u606f\u67e5\u8be2\u4e5f\u8981\u5148\u4fdd\u8bc1\u5df2\u52a0\u8f7d<\/td>\n<\/tr>\n<tr>\n<td>removeValueForKey \/ allKeys \/ removeValuesForKeys<\/td>\n<td>Core\/MMKV.cpp:1099 \/ :1108 \/ :1138<\/td>\n<td>\u5220\u9664\u540c\u6837\u8981\u5148\u5efa\u597d\u5b57\u5178<\/td>\n<\/tr>\n<tr>\n<td>checkReSetCryptKey<\/td>\n<td>Core\/MMKV.cpp:372\u3001:381\u3001:389<\/td>\n<td>\u6362\u5bc6\u94a5\u524d\u4e09\u5904\u515c\u5e95\u52a0\u8f7d<\/td>\n<\/tr>\n<tr>\n<td>checkContentChanged<\/td>\n<td>Core\/MMKV.cpp:291<\/td>\n<td>\u624b\u52a8\u89e6\u53d1\u4e00\u6b21\u540c\u6b65&#xff08;\u53ef\u7528\u6765\u9884\u70ed&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>enableAutoKeyExpire \/ disableAutoKeyExpire \/ getExpireTimeForKey<\/td>\n<td>Core\/MMKV_IO.cpp:1629 \/ :1697 \/ :1763<\/td>\n<td>TTL \u76f8\u5173\u63a5\u53e3<\/td>\n<\/tr>\n<tr>\n<td>getDataWithoutMTimeForKey<\/td>\n<td>Core\/MMKV_IO.cpp:1788<\/td>\n<td>\u5f00\u4e86\u8fc7\u671f\u65f6\u7684\u8bfb\u8def\u5f84&#xff08;\u89c1 :566-569 \u5206\u6d41&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u4e00\u53e5\u8bdd\u9762\u8bd5\u7248&#xff1a;\u6784\u9020\u51fd\u6570\u53ea\u505a\u300c\u5f00\u6587\u4ef6 &#043; \u6491\u5230\u9875\u5bf9\u9f50\u5927\u5c0f &#043; MAP_SHARED \u6620\u5c04 &#043; \u5efa\u9501 &#043; \u5efa\u7a7a\u5b57\u5178\u300d&#xff0c;loadFromFile() \u5728\u4e09\u4e2a\u5e73\u53f0\u7684\u6784\u9020\u51fd\u6570\u91cc\u90fd\u88ab\u6ce8\u91ca\u6389&#xff1b;\u771f\u6b63\u89e3\u6790\u9760 checkLoadData() \u5728\u9996\u4e2a encode\/decode \u91cc\u6309 m_needLoadFromFile \u89e6\u53d1\u4e00\u6b21\u3002\u6240\u4ee5 MMKV.mmkvWithID(&#034;x&#034;) \u5faa\u73af\u521b\u5efa 100 \u4e2a\u5b9e\u4f8b\u4e0d\u5361&#xff0c;\u4f46\u7b2c\u4e00\u6b21 decodeInt \u4f1a\u4e3a\u300c\u8001\u7528\u6237\u7684\u5927\u6587\u4ef6\u300d\u4ed8\u51fa\u4e00\u6b21\u6027\u4ee3\u4ef7 \u2014\u2014 \u60f3\u628a\u8fd9\u4e2a\u4ee3\u4ef7\u632a\u51fa\u5173\u952e\u8def\u5f84&#xff0c;\u5c31\u5728\u542f\u52a8\u540e\u53f0\u7ebf\u7a0b\u63d0\u524d\u8c03\u4e00\u6b21 checkContentChanged() \u6216\u4efb\u610f decode\u3002<\/p>\n<h4>4.2 \u6570\u636e\u6587\u4ef6\u7684\u7269\u7406\u5e03\u5c40<\/h4>\n<p>\u504f\u79fb 0                                                        \u504f\u79fb fileSize<br \/>\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502 4B Fixed32   \u2502 4B ItemSizeHolder\u2502  KV record #1         \u2502 free \u2502<br \/>\n\u2502 actualSize   \u2502 (\u968f\u673a\u4f2a\u88c5\u957f\u5ea6)   \u2502  KV record #2         \u2502 space\u2502<br \/>\n\u2502 (\u8001\u5f0f\u517c\u5bb9)   \u2502                  \u2502  &#8230;                  \u2502      \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2518<br \/>\n        \u2191                \u2191<br \/>\n   oldStyleWrite     m_output \u4ece<br \/>\n   ActualSize()      \u8fd9\u91cc\u5f00\u59cb\u8ffd\u52a0<\/p>\n<p>\u6bcf\u6761 KV \u8bb0\u5f55\u662f\u7eaf protobuf wire-format \u7684 \u957f\u5ea6\u524d\u7f00\u5bf9&#xff1a;<\/p>\n<p>[varint32 keyLen][key bytes][varint32 valueLen][value bytes]<\/p>\n<p>\u5bf9\u5e94\u6e90\u7801\u91cc\u53cd\u590d\u51fa\u73b0\u7684\u4e09\u4e2a\u5c3a\u5bf8\u5e38\u91cf&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/PBUtility.h<\/span><br \/>\n<span class=\"token keyword\">constexpr<\/span> <span class=\"token keyword\">uint32_t<\/span> Fixed32Size <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">pbFixed32Size<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ &#061; 4<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:348<\/span><br \/>\n<span class=\"token keyword\">constexpr<\/span> <span class=\"token keyword\">uint32_t<\/span> ItemSizeHolderSize <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">4<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>Core\/MMKV_IO.cpp:473 \u7684 oldStyleWriteActualSize() \u6bcf\u6b21\u90fd\u4f1a\u628a actualSize \u4ee5 memcpy \u5199\u8fdb\u6587\u4ef6\u5934 4 \u5b57\u8282&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:473<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">oldStyleWriteActualSize<\/span><span class=\"token punctuation\">(<\/span>size_t actualSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token function\">memcpy<\/span><span class=\"token punctuation\">(<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token operator\">&amp;<\/span>actualSize<span class=\"token punctuation\">,<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u8fd9 4 \u5b57\u8282\u5b58\u5728\u7406\u7531\u662f\u300c\u964d\u7ea7\u517c\u5bb9\u300d&#xff1a;\u8001\u7248\u672c MMKV \u53ea\u8ba4\u6587\u4ef6\u5934\u957f\u5ea6\u3002checkDataValid()&#xff08;Core\/MMKV_IO.cpp:230&#xff09;\u4f1a\u7528\u5b83\u505a downgrade\/upgrade \u68c0\u6d4b&#xff0c;\u672c\u6587\u7b2c 10 \u7ae0\u5c55\u5f00\u3002<\/p>\n<p>\u771f\u6b63\u7684\u6743\u5a01\u957f\u5ea6\u548c CRC \u4e0d\u5728\u6570\u636e\u6587\u4ef6\u91cc&#xff0c;\u800c\u5728 .crc \u5143\u6587\u4ef6\u91cc\u3002 \u8fd9\u662f MMKV \u6570\u636e\u5b89\u5168\u8bbe\u8ba1\u7684\u5173\u952e&#xff1a;\u6570\u636e\u6587\u4ef6\u662f\u300c\u53ef\u8ffd\u52a0\u7684\u88f8\u533a\u300d&#xff0c;\u5143\u6587\u4ef6\u662f\u300c\u4e00\u9875\u7eb8\u7684\u8d26\u672c\u300d&#xff0c;\u8d26\u672c\u4e00\u6b21\u5199\u5b8c\u6574\u9875&#xff08;4KB \u539f\u5b50\u6027&#xff09;&#xff0c;\u6240\u4ee5\u5929\u7136\u6297\u534a\u5199\u3002<\/p>\n<h4>4.3 .crc&#xff08;meta&#xff09;\u6587\u4ef6\u7684\u5185\u5b58\u7ed3\u6784<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKVMetaInfo.hpp&#xff08;\u8282\u9009&#xff0c;\u5b57\u6bb5\u987a\u5e8f\u5373\u843d\u76d8\u987a\u5e8f&#xff09;<\/span><br \/>\n<span class=\"token keyword\">uint32_t<\/span> m_crcDigest <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span>                       <span class=\"token comment\">\/\/ :54 \u6570\u636e\u533a\u7684 CRC32<\/span><br \/>\n<span class=\"token keyword\">uint32_t<\/span> m_version <span class=\"token operator\">&#061;<\/span> MMKVVersionSequence<span class=\"token punctuation\">;<\/span>       <span class=\"token comment\">\/\/ :55<\/span><br \/>\n<span class=\"token keyword\">uint32_t<\/span> m_sequence <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ full write-back count   :56<\/span><br \/>\n<span class=\"token keyword\">uint8_t<\/span>  m_vector<span class=\"token punctuation\">[<\/span>AES_KEY_LEN<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>            <span class=\"token comment\">\/\/ :57 AES-CFB \u7684 IV<\/span><br \/>\n<span class=\"token keyword\">uint32_t<\/span> m_actualSize <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span>                      <span class=\"token comment\">\/\/ :58<\/span><\/p>\n<p><span class=\"token comment\">\/\/ confirmed info: it&#039;s been synced to file      :60<\/span><br \/>\n<span class=\"token keyword\">struct<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">uint32_t<\/span> lastActualSize <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">uint32_t<\/span> lastCRCDigest <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">uint32_t<\/span> _reserved<span class=\"token punctuation\">[<\/span><span class=\"token number\">16<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span> m_lastConfirmedMetaInfo<span class=\"token punctuation\">;<\/span>                      <span class=\"token comment\">\/\/ :65<\/span><\/p>\n<p><span class=\"token keyword\">uint64_t<\/span> m_flags <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span>                           <span class=\"token comment\">\/\/ :67  \u5982 EnableKeyExipre<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKVMetaInfo.hpp:81  \u70ed\u8def\u5f84\u4e0a\u7684\u300c\u5feb\u5199\u300d&#xff1a;\u53ea\u6539\u4e24\u4e2a\u5b57\u6bb5<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token function\">writeCRCAndActualSizeOnly<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>ptr<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> other <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span>MMKVMetaInfo <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> ptr<span class=\"token punctuation\">;<\/span><br \/>\n    other<span class=\"token operator\">-&gt;<\/span>m_crcDigest <span class=\"token operator\">&#061;<\/span> m_crcDigest<span class=\"token punctuation\">;<\/span><br \/>\n    other<span class=\"token operator\">-&gt;<\/span>m_actualSize <span class=\"token operator\">&#061;<\/span> m_actualSize<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKVMetaInfo.hpp:94<\/span><br \/>\n<span class=\"token keyword\">static_assert<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span>MMKVMetaInfo<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token number\">4<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">1024<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;MMKVMetaInfo lager than one pagesize&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>static_assert \u90a3\u4e00\u884c\u662f\u8bbe\u8ba1\u7684\u7075\u9b42\u7ea6\u675f&#xff1a;\u6574\u4e2a meta \u7ed3\u6784\u5fc5\u987b \u2264 \u4e00\u4e2a\u5185\u5b58\u9875\u3002\u56e0\u4e3a\u5185\u6838\u5bf9\u300c\u5355\u9875\u5bf9\u9f50\u5199\u300d\u5728\u5b9e\u8df5\u4e2d\u53ef\u89c6\u4e3a\u539f\u5b50&#xff0c;\u4e8e\u662f \u8de8\u8fdb\u7a0b\u8bfb meta \u4e0d\u9700\u8981\u8bfb\u5230\u6495\u88c2\u6570\u636e&#xff0c;\u4e5f\u4e0d\u9700\u8981\u989d\u5916\u7684\u7ba1\u9053\/\u4fe1\u53f7\u91cf\u3002<\/p>\n<h4>4.4 mmap() \u672c\u4f53<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MemoryFile.cpp:195<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MemoryFile<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">mmap<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> oldPtr <span class=\"token operator\">&#061;<\/span> m_ptr<span class=\"token punctuation\">;<\/span><br \/>\n    m_ptr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">char<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">mmap<\/span><span class=\"token punctuation\">(<\/span>m_ptr<span class=\"token punctuation\">,<\/span> m_size<span class=\"token punctuation\">,<\/span> PROT_READ <span class=\"token operator\">|<\/span> PROT_WRITE<span class=\"token punctuation\">,<\/span> MAP_SHARED<span class=\"token punctuation\">,<\/span> m_diskFile<span class=\"token punctuation\">.<\/span>m_fd<span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_ptr <span class=\"token operator\">&#061;&#061;<\/span> MAP_FAILED<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;fail to mmap [%s], %s&#034;<\/span><span class=\"token punctuation\">,<\/span> m_diskFile<span class=\"token punctuation\">.<\/span>m_path<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">strerror<\/span><span class=\"token punctuation\">(<\/span>errno<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        m_ptr <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token function\">MMKVInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;mmap to address [%p], oldPtr [%p], [%s]&#034;<\/span><span class=\"token punctuation\">,<\/span> m_ptr<span class=\"token punctuation\">,<\/span> oldPtr<span class=\"token punctuation\">,<\/span> m_diskFile<span class=\"token punctuation\">.<\/span>m_path<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h4>\u3010\u7ea0\u504f \u00b7 \u91cd\u8981\u3011MMKV \u4e0d\u662f\u300c\u5199\u65f6\u590d\u5236&#xff08;COW&#xff09;\u300d&#xff0c;\u4e5f\u4e0d\u5b58\u5728\u300c\u4fee\u6539\u65f6\u521b\u5efa\u65b0\u5185\u5b58\u9875\u300d<\/h4>\n<p>\u4e0a\u9762\u7684 MAP_SHARED \u5c31\u662f\u53cd\u8bc1&#xff1a;MAP_SHARED \u7684\u6620\u5c04\u9875 \u76f4\u63a5\u5c31\u662f page cache \u4e2d\u7684\u90a3\u4e2a\u7269\u7406\u9875&#xff0c;\u6240\u6709\u6620\u5c04\u540c\u4e00\u6587\u4ef6\u7684\u8fdb\u7a0b\u770b\u5230\u540c\u4e00\u4efd\u6570\u636e&#xff0c;\u5199\u5165\u7acb\u5373\u5bf9\u5f7c\u6b64\u53ef\u89c1&#xff0c;\u7531\u5185\u6838\u5f02\u6b65\u56de\u5199\u3002<\/p>\n<ul>\n<li>\u5982\u679c\u7528 MAP_PRIVATE \u624d\u662f COW \u2014\u2014 \u90a3\u5199\u5165\u4e0d\u4f1a\u843d\u76d8&#xff0c;\u8fdb\u7a0b\u4e00\u9000\u51fa\u6570\u636e\u5c31\u6ca1\u4e86&#xff0c;\u591a\u8fdb\u7a0b\u4e5f\u5f7b\u5e95\u5931\u6548\u3002MMKV \u7edd\u4e0d\u53ef\u80fd\u7528 COW\u3002<\/li>\n<li>\u300c\u5199\u5165\u5d29\u6e83\u5bfc\u81f4\u6570\u636e\u4e0d\u4e22\u300d\u7684\u771f\u6b63\u539f\u56e0\u662f&#xff1a;\u810f\u9875\u5728\u5185\u6838 page cache \u91cc&#xff0c;\u8fdb\u7a0b\u6302\u6389\u4e0d\u5f71\u54cd\u5185\u6838\u628a\u9875\u56de\u5199&#xff1b;\u800c \u5d29\u6e83\u77ac\u95f4\u53ea\u53ef\u80fd\u4e22\u6389\u300c\u8fd8\u6ca1\u5199\u5165 mmap \u7684\u5b57\u8282\u300d&#xff0c;write() \u5230\u6620\u5c04\u533a\u7684 memcpy \u662f\u540c\u6b65\u5b8c\u6210\u7684\u3002<\/li>\n<\/ul>\n<p>\u6b63\u786e\u8868\u8ff0&#xff1a;\u300c\u5199\u5165 &#061; \u5bf9\u7528\u6237\u6001\u53ef\u89c1\u3001\u5185\u6838\u6258\u7ba1\u7684\u5171\u4eab\u9875\u505a memcpy&#xff0c;\u810f\u9875\u7531\u5185\u6838\u5f02\u6b65 writeback&#xff1b;\u56e0\u6b64\u65e2\u6709\u5185\u5b58\u901f\u5ea6&#xff0c;\u53c8\u6709\u843d\u76d8\u8bed\u4e49\u300d\u3002<\/p>\n<h4>4.5 \u7a7a\u95f4\u6269\u5bb9&#xff1a;truncate \u4e0e\u300c\u586b\u96f6\u300d<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MemoryFile.cpp&#xff08;truncate \u4e3b\u5e72&#xff0c;\u8282\u9009&#xff09;<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MemoryFile<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">truncate<\/span><span class=\"token punctuation\">(<\/span>size_t newSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> oldSize <span class=\"token operator\">&#061;<\/span> m_size<span class=\"token punctuation\">;<\/span><br \/>\n    m_size <span class=\"token operator\">&#061;<\/span> size<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token comment\">\/\/ round up \u5230 page \u6574\u6570\u500d &#043; ftruncate<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_size <span class=\"token operator\">&lt;<\/span> DEFAULT_MMAP_SIZE <span class=\"token operator\">||<\/span> <span class=\"token punctuation\">(<\/span>m_size <span class=\"token operator\">%<\/span> DEFAULT_MMAP_SIZE <span class=\"token operator\">!&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        m_size <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>m_size <span class=\"token operator\">\/<\/span> DEFAULT_MMAP_SIZE<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> DEFAULT_MMAP_SIZE<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">ftruncate<\/span><span class=\"token punctuation\">(<\/span>m_diskFile<span class=\"token punctuation\">.<\/span>m_fd<span class=\"token punctuation\">,<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>off_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>m_size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">!&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;fail to truncate [%s] to size %zu, %s&#034;<\/span><span class=\"token punctuation\">,<\/span> m_diskFile<span class=\"token punctuation\">.<\/span>m_path<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> m_size<span class=\"token punctuation\">,<\/span> <span class=\"token function\">strerror<\/span><span class=\"token punctuation\">(<\/span>errno<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        m_size <span class=\"token operator\">&#061;<\/span> oldSize<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_size <span class=\"token operator\">&gt;<\/span> oldSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token comment\">\/\/\u6269\u5bb9\u7684\u7a7a\u95f4\u586b0<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span><span class=\"token function\">zeroFillFile<\/span><span class=\"token punctuation\">(<\/span>m_diskFile<span class=\"token punctuation\">.<\/span>m_fd<span class=\"token punctuation\">,<\/span> oldSize<span class=\"token punctuation\">,<\/span> m_size <span class=\"token operator\">&#8211;<\/span> oldSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;fail to zeroFile [%s] to size %zu, %s&#034;<\/span><span class=\"token punctuation\">,<\/span> m_diskFile<span class=\"token punctuation\">.<\/span>m_path<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> m_size<span class=\"token punctuation\">,<\/span> <span class=\"token function\">strerror<\/span><span class=\"token punctuation\">(<\/span>errno<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            m_size <span class=\"token operator\">&#061;<\/span> oldSize<span class=\"token punctuation\">;<\/span><\/p>\n<p>            <span class=\"token comment\">\/\/ redo ftruncate to its previous size<\/span><br \/>\n            <span class=\"token keyword\">int<\/span> status <span class=\"token operator\">&#061;<\/span> <span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">ftruncate<\/span><span class=\"token punctuation\">(<\/span>m_diskFile<span class=\"token punctuation\">.<\/span>m_fd<span class=\"token punctuation\">,<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>off_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>m_size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>status <span class=\"token operator\">!&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;failed to truncate back [%s] to size %zu, %s&#034;<\/span><span class=\"token punctuation\">,<\/span> m_diskFile<span class=\"token punctuation\">.<\/span>m_path<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> m_size<span class=\"token punctuation\">,<\/span> <span class=\"token function\">strerror<\/span><span class=\"token punctuation\">(<\/span>errno<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;success to truncate [%s] back to size %zu&#034;<\/span><span class=\"token punctuation\">,<\/span> m_diskFile<span class=\"token punctuation\">.<\/span>m_path<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> m_size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;after truncate, file size &#061; %zu&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">getActualFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><\/p>\n<p>            <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_ptr<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">munmap<\/span><span class=\"token punctuation\">(<\/span>m_ptr<span class=\"token punctuation\">,<\/span> oldSize<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">!&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;fail to munmap [%s], %s&#034;<\/span><span class=\"token punctuation\">,<\/span> m_diskFile<span class=\"token punctuation\">.<\/span>m_path<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">strerror<\/span><span class=\"token punctuation\">(<\/span>errno<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">mmap<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>ret<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token function\">doCleanMemoryCache<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">true<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> ret<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>mmkv::zeroFillFile(fd, offset, size)&#xff08;Core\/MemoryFile.cpp \u5c3e\u90e8\u5de5\u5177\u51fd\u6570&#xff09;\u6bcf\u6b21\u5199 4096 \u5b57\u8282 0 \u628a\u65b0\u533a\u95f4\u300c\u5360\u4f4f\u300d\u3002\u539f\u56e0&#xff1a;ftruncate \u5728\u5f88\u591a\u6587\u4ef6\u7cfb\u7edf\u4e2d&#xff0c;\u53ea\u662f\u903b\u8f91\u4e0a\u8c03\u6574\u4e86\u6587\u4ef6\u5927\u5c0f&#xff0c;\u5c5e\u4e8e\u201c\u7a00\u758f\u6587\u4ef6&#xff08;Sparse File&#xff09;\u201d\u5904\u7406\u3002\u5982\u679c\u4ec5\u4ec5 ftruncate&#xff0c;\u64cd\u4f5c\u7cfb\u7edf\u53ef\u80fd\u5e76\u6ca1\u6709\u771f\u6b63\u4e3a\u8fd9\u5757\u65b0\u6269\u5c55\u7684\u533a\u57df\u5206\u914d\u7269\u7406\u78c1\u76d8\u5757\u3002\u5982\u679c\u5728\u540e\u7eed\u5199\u5165\u8fc7\u7a0b\u4e2d&#xff0c;\u78c1\u76d8\u7a7a\u95f4\u6b63\u597d\u8017\u5c3d&#xff0c;\u539f\u672c ftruncate \u6210\u529f\u7684\u64cd\u4f5c\u4f1a\u5bfc\u81f4\u968f\u540e\u7684 write \u6216\u5185\u5b58\u6620\u5c04\u8bbf\u95ee\u89e6\u53d1 SIGBUS \u4fe1\u53f7&#xff0c;\u4ece\u800c\u5bfc\u81f4\u7a0b\u5e8f\u5d29\u6e83\u3002\u901a\u8fc7 zeroFillFile \u8fdb\u884c\u663e\u5f0f\u5199\u5165&#xff0c;\u76f8\u5f53\u4e8e\u5f3a\u5236\u89e6\u53d1\u4e86\u6587\u4ef6\u7cfb\u7edf\u7684\u7269\u7406\u5757\u5206\u914d\u3002\u5982\u679c\u7a7a\u95f4\u4e0d\u8db3&#xff0c;\u8fd9\u4e2a\u8fc7\u7a0b\u4f1a\u76f4\u63a5\u8fd4\u56de\u5931\u8d25&#xff0c;MMKV \u53ef\u4ee5\u53ca\u65f6\u6355\u83b7\u5e76\u5904\u7406\u9519\u8bef&#xff0c;\u800c\u4e0d\u662f\u5728\u540e\u7eed\u5173\u952e\u7684\u8bfb\u5199\u6d41\u7a0b\u4e2d\u5d29\u6e83\u3002<\/p>\n<h4>4.6 reloadFromFile&#xff1a;\u53e6\u4e00\u8fdb\u7a0b\u6269\u5bb9\u540e\u5982\u4f55\u8ddf\u4e0a<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MemoryFile.cpp:207<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MemoryFile<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">reloadFromFile<\/span><span class=\"token punctuation\">(<\/span>size_t expectedCapacity<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_diskFile<span class=\"token punctuation\">.<\/span><span class=\"token function\">open<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        FileLock <span class=\"token function\">fileLock<\/span><span class=\"token punctuation\">(<\/span>m_diskFile<span class=\"token punctuation\">.<\/span>m_fd<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        InterProcessLock <span class=\"token function\">lock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>fileLock<span class=\"token punctuation\">,<\/span> SharedLockType<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>lock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                  <span class=\"token comment\">\/\/ :224 \u5148\u62ff\u5171\u4eab\u9501\u8bfb size<\/span><br \/>\n        mmkv<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span>m_diskFile<span class=\"token punctuation\">.<\/span>m_fd<span class=\"token punctuation\">,<\/span> m_size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>          <span class=\"token comment\">\/\/ :226<\/span><br \/>\n        size_t expectedSize <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token generic-function\"><span class=\"token function\">max<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>DEFAULT_MMAP_SIZE<span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token generic-function\"><span class=\"token function\">roundUp<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>expectedCapacity<span class=\"token punctuation\">,<\/span> DEFAULT_MMAP_SIZE<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_size <span class=\"token operator\">&lt;<\/span> expectedSize <span class=\"token operator\">||<\/span> <span class=\"token punctuation\">(<\/span>m_size <span class=\"token operator\">%<\/span> DEFAULT_MMAP_SIZE <span class=\"token operator\">!&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            InterProcessLock <span class=\"token function\">exclusiveLock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>fileLock<span class=\"token punctuation\">,<\/span> ExclusiveLockType<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>exclusiveLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                     <span class=\"token comment\">\/\/ :231 \u9700\u8981\u653e\u5927 \u2192 \u5347\u7ea7\u4e3a\u72ec\u5360<\/span><br \/>\n            size_t roundSize <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>m_size <span class=\"token operator\">\/<\/span> DEFAULT_MMAP_SIZE<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> DEFAULT_MMAP_SIZE<span class=\"token punctuation\">;<\/span><br \/>\n            roundSize <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token generic-function\"><span class=\"token function\">max<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>expectedSize<span class=\"token punctuation\">,<\/span> roundSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token function\">truncate<\/span><span class=\"token punctuation\">(<\/span>roundSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                             <span class=\"token comment\">\/\/ :235<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">mmap<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                               <span class=\"token comment\">\/\/ :237 \u76f4\u63a5\u6620\u5c04<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>ret<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">doCleanMemoryCache<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">true<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u8fd9\u91cc\u51fa\u73b0\u4e86 shared \u2192 exclusive \u7684\u9501\u5347\u7ea7&#xff0c;\u4e5f\u6b63\u662f FileLock \u5fc5\u987b\u505a\u6210\u300c\u53ef\u9012\u5f52 &#043; \u80fd\u4e34\u65f6\u8ba9\u51fa\u5171\u4eab\u9501\u300d\u7684\u539f\u56e0&#xff08;\u89c1 8.2&#xff09;\u3002<\/p>\n<h4>4.7 msync&#xff1a;MMKV \u5230\u5e95\u4ec0\u4e48\u65f6\u5019\u843d\u76d8<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MemoryFile.cpp:184<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MemoryFile<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">msync<\/span><span class=\"token punctuation\">(<\/span>SyncFlag syncFlag<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_ptr<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> ret <span class=\"token operator\">&#061;<\/span> <span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">msync<\/span><span class=\"token punctuation\">(<\/span>m_ptr<span class=\"token punctuation\">,<\/span> m_size<span class=\"token punctuation\">,<\/span> syncFlag <span class=\"token operator\">?<\/span> MS_SYNC <span class=\"token operator\">:<\/span> MS_ASYNC<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ret <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;fail to msync [%s], %s&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:1169<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">sync<\/span><span class=\"token punctuation\">(<\/span>SyncFlag flag<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">msync<\/span><span class=\"token punctuation\">(<\/span>flag<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    m_metaFile<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">msync<\/span><span class=\"token punctuation\">(<\/span>flag<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>      <span class=\"token comment\">\/\/ \u5143\u6587\u4ef6\u4e5f\u8981\u540c\u6b65&#xff0c;\u5426\u5219\u91cd\u542f\u540e meta \u6bd4\u6570\u636e\u65e7<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u65e5\u5e38 encode() \u4e0d\u4f1a\u8c03\u7528 msync&#xff08;\u9664\u4e86\u91cd\u6574\u8def\u5f84 doFullWriteBack \u4f1a sync(MMKV_SYNC)&#xff09;\u3002\u843d\u76d8\u5b8c\u5168\u4ea4\u7ed9\u5185\u6838\u3002MMKV.sync(Async) \/ MMKV.sync(Sync) \u662f\u7ed9\u300c\u5e94\u7528\u5373\u5c06\u9000\u540e\u53f0\u3001\u60f3\u7acb\u523b\u5237\u76d8\u300d\u7684\u53ef\u9009\u4fdd\u9669\u3002<\/p>\n<hr \/>\n<h3>5. \u5e8f\u5217\u5316\u5c42&#xff1a;MiniPBCoder \/ CodedInOutData \/ KeyValueHolder<\/h3>\n<h4>5.1 \u300cprotobuf\u300d\u5230\u5e95\u7528\u5230\u4e86\u4ec0\u4e48\u7a0b\u5ea6<\/h4>\n<p>MMKV \u6ca1\u6709\u5f15\u5165\u5b8c\u6574 protobuf \u8fd0\u884c\u65f6&#xff0c;\u800c\u662f\u5728 Core\/protobuf \u76f8\u5173\u6587\u4ef6\u91cc\u624b\u5199\u4e86 wire-format \u7684\u4e00\u4e2a\u5b50\u96c6&#xff1a;varint\u3001fixed32\u3001length-delimited\u3002\u597d\u5904\u662f\u96f6 .proto\u3001\u96f6\u751f\u6210\u4ee3\u7801\u3001\u4f53\u79ef\u6781\u5c0f&#xff1b;\u4ee3\u4ef7\u662f\u5b83\u4e0d\u662f\u901a\u7528\u7684 protobuf&#xff0c;\u800c\u662f\u300cprotobuf \u7f16\u7801\u683c\u5f0f\u7684 KV \u6d41\u300d\u3002<\/p>\n<h4>5.2 \u7d22\u5f15\u7ed3\u6784 MMKVMap<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKVPredef.h:228<\/span><br \/>\n<span class=\"token keyword\">using<\/span> MMKVMap <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span>unordered_map<span class=\"token operator\">&lt;<\/span>std<span class=\"token double-colon punctuation\">::<\/span>string<span class=\"token punctuation\">,<\/span> mmkv<span class=\"token double-colon punctuation\">::<\/span>KeyValueHolder<span class=\"token punctuation\">,<\/span> KeyHasher<span class=\"token punctuation\">,<\/span> KeyEqualer<span class=\"token operator\">&gt;<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token comment\">\/\/ Core\/MMKVPredef.h:229<\/span><br \/>\n<span class=\"token keyword\">using<\/span> MMKVMapCrypt <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span>unordered_map<span class=\"token operator\">&lt;<\/span>std<span class=\"token double-colon punctuation\">::<\/span>string<span class=\"token punctuation\">,<\/span> mmkv<span class=\"token double-colon punctuation\">::<\/span>KeyValueHolderCrypt<span class=\"token punctuation\">,<\/span> KeyHasher<span class=\"token punctuation\">,<\/span> KeyEqualer<span class=\"token operator\">&gt;<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>KeyHasher \/ KeyEqualer \u5e26 is_transparent \u6807\u8bb0&#xff0c;\u542f\u7528 C&#043;&#043;14 \u5f02\u6784\u67e5\u627e&#xff1a;\u7528\u4e00\u4e2a string_view\/\u4e34\u65f6 buffer \u53bb\u67e5 map&#xff0c;\u4e0d\u4f1a\u56e0\u4e3a\u67e5\u8be2\u800c\u6784\u9020 std::string\u3002\u8bfb\u53d6\u8def\u5f84\u4e0a\u5c11\u4e00\u6b21\u5806\u5206\u914d\u3002<\/p>\n<h4>5.3 KeyValueHolder&#xff1a;\u5185\u5b58\u91cc\u53ea\u5b58\u300c\u5750\u6807\u300d&#xff0c;\u4e0d\u5b58\u503c<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/KeyValueHolder.h:30<\/span><br \/>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#<\/span><span class=\"token directive keyword\">pragma<\/span> <span class=\"token expression\"><span class=\"token function\">pack<\/span><span class=\"token punctuation\">(<\/span>push<span class=\"token punctuation\">,<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><\/span><\/span><\/p>\n<p><span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">KeyValueHolder<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">uint16_t<\/span> computedKVSize<span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ internal use only   :33 \u5934\u90e8 varint \u5360\u7684\u5b57\u8282\u6570<\/span><br \/>\n    <span class=\"token keyword\">uint16_t<\/span> keySize<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">uint32_t<\/span> valueSize<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">uint32_t<\/span> offset<span class=\"token punctuation\">;<\/span>                                <span class=\"token comment\">\/\/ :36 \u76f8\u5bf9\u6570\u636e\u533a\u8d77\u70b9\u7684\u504f\u79fb<\/span><\/p>\n<p>    MMBuffer <span class=\"token function\">toMMBuffer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>basePtr<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">const<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ :41<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>KeyValueHolder.cpp \u91cc toMMBuffer() \u7684\u6838\u5fc3\u5c31\u4e00\u884c\u7b97\u672f&#xff1a;<\/p>\n<p><span class=\"token keyword\">return<\/span> <span class=\"token function\">MMBuffer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> basePtr <span class=\"token operator\">&#043;<\/span> offset <span class=\"token operator\">&#043;<\/span> computedKVSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> valueSize<span class=\"token punctuation\">,<\/span> MMBufferNoCopy<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>\u8fd9\u662f MMKV \u8bfb\u53d6\u5feb\u7684\u672c\u8d28&#xff1a;m_dic \u662f\u4e00\u5f20 key \u2192 (offset, size) \u7684\u8868&#xff0c;\u8bfb\u503c &#061; \u5728 mmap \u533a\u5185\u505a\u4e00\u6b21 \u96f6\u62f7\u8d1d\u89c6\u56fe\u6784\u9020&#xff0c;\u65e2\u4e0d memcpy \u4e5f\u4e0d\u53cd\u5e8f\u5217\u5316\u6574\u8868\u3002<\/p>\n<p>#pragma pack(1) &#043; uint16_t \u662f\u4e3a\u4e86\u628a\u6bcf\u4e2a holder \u538b\u5230 12 \u5b57\u8282\u3002\u5b57\u5178\u6709 10 \u4e07\u6761\u65f6&#xff0c;\u7d27\u51d1\u5e03\u5c40\u80fd\u7701\u4e0b\u6570 MB \u5e38\u9a7b\u5185\u5b58\u3002<\/p>\n<h4>5.4 \u52a0\u5bc6\u6a21\u5f0f\u7684\u4e09\u6001 holder&#xff08;\u4e00\u4e2a\u7cbe\u5de7\u8bbe\u8ba1&#xff09;<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/KeyValueHolder.h:46<\/span><br \/>\n<span class=\"token keyword\">enum<\/span> <span class=\"token class-name\">KeyValueHolderType<\/span> <span class=\"token operator\">:<\/span> <span class=\"token keyword\">uint8_t<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    KeyValueHolderType_Direct<span class=\"token punctuation\">,<\/span>  <span class=\"token comment\">\/\/ store value directly<\/span><br \/>\n    KeyValueHolderType_Memory<span class=\"token punctuation\">,<\/span>  <span class=\"token comment\">\/\/ store value in the heap memory<\/span><br \/>\n    KeyValueHolderType_Offset<span class=\"token punctuation\">,<\/span>  <span class=\"token comment\">\/\/ store value by offset<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/KeyValueHolder.h:53&#xff08;union \u4e09\u9009\u4e00&#xff09;<\/span><br \/>\n<span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">KeyValueHolderCrypt<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    KeyValueHolderType type <span class=\"token operator\">&#061;<\/span> KeyValueHolderType_Direct<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">union<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">struct<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">uint8_t<\/span> pbKeyValueSize<span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">uint16_t<\/span> keySize<span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">uint32_t<\/span> valueSize<span class=\"token punctuation\">;<\/span><br \/>\n                 <span class=\"token keyword\">uint32_t<\/span> offset<span class=\"token punctuation\">;<\/span> AESCryptStatus cryptStatus<span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :59 Offset \u6001<\/span><br \/>\n        <span class=\"token keyword\">struct<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">uint8_t<\/span> paddedSize<span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">uint8_t<\/span> paddedValue<span class=\"token punctuation\">[<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>    <span class=\"token comment\">\/\/ :66 Direct \u6001&#xff1a;\u503c\u5185\u8054\u5728 map \u91cc<\/span><br \/>\n        <span class=\"token keyword\">struct<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">uint32_t<\/span> memSize<span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>memPtr<span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>                <span class=\"token comment\">\/\/ :71 Memory \u6001&#xff1a;\u503c\u5728\u5806\u4e0a<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">static<\/span> <span class=\"token keyword\">constexpr<\/span> size_t <span class=\"token function\">MediumBufferSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token number\">256<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>     <span class=\"token comment\">\/\/ :81<\/span><br \/>\n    <span class=\"token keyword\">static<\/span> <span class=\"token keyword\">bool<\/span> <span class=\"token function\">isValueStoredAsOffset<\/span><span class=\"token punctuation\">(<\/span>size_t valueSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> valueSize <span class=\"token operator\">&gt;<\/span> <span class=\"token function\">MediumBufferSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span> <span class=\"token comment\">\/\/ :85<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<h5>5.4.1 \u5148\u628a\u5c3a\u5bf8\u8d26\u7b97\u6e05\u695a&#xff1a;SmallBufferSize() &#061;&#061; 27<\/h5>\n<p><span class=\"token comment\">\/\/ Core\/KeyValueHolder.cpp:60-66  KeyValueHolderCrypt(MMBuffer&amp;&amp;)<\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">.<\/span>type <span class=\"token operator\">&#061;&#061;<\/span> MMBuffer<span class=\"token double-colon punctuation\">::<\/span>MMBufferType_Small<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">static_assert<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">SmallBufferSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&gt;&#061;<\/span> <span class=\"token class-name\">MMBuffer<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">SmallBufferSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                  <span class=\"token string\">&#034;KeyValueHolderCrypt can&#039;t hold MMBuffer&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>        <span class=\"token comment\">\/\/ :62<\/span><br \/>\n    type <span class=\"token operator\">&#061;<\/span> KeyValueHolderType_Direct<span class=\"token punctuation\">;<\/span><br \/>\n    paddedSize <span class=\"token operator\">&#061;<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span><span class=\"token keyword\">uint8_t<\/span><span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">memcpy<\/span><span class=\"token punctuation\">(<\/span>paddedValue<span class=\"token punctuation\">,<\/span> data<span class=\"token punctuation\">.<\/span><span class=\"token function\">getPtr<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> data<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>               <span class=\"token comment\">\/\/ :66 \u5185\u8054&#xff0c;\u6c38\u4e0d\u8d8a\u754c<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>MMBuffer \u81ea\u5df1\u7684 SSO \u5bb9\u91cf\u662f sizeof(MMBuffer) &#8211; offsetof(paddedBuffer) &#061; 16&#xff08;Android\/Linux 64 \u4f4d&#xff09;\u300124&#xff08;Apple 64 \u4f4d&#xff09;\u300110&#xff08;32 \u4f4d&#xff0c;\u89c1 Core\/MMBuffer.h:62-63 \u6ce8\u91ca&#xff09;\u300227 \u2265 24 \u6052\u6210\u7acb&#xff0c;\u6240\u4ee5\u4efb\u4f55\u300cMMBuffer \u5b58\u5728\u6808\u4e0a\u300d\u7684\u503c\u90fd\u4fdd\u8bc1\u80fd\u585e\u8fdb holder&#xff0c;\u7f16\u8bd1\u671f\u5c31\u675c\u7edd\u4e86 memcpy \u8d8a\u754c\u3002<\/p>\n<h5>5.4.2 \u4e24\u4e2a\u9608\u503c\u3001\u4e24\u4e2a\u51b3\u7b56\u70b9&#xff08;\u4e0d\u662f\u300c256 \u4e00\u4e2a\u6807\u51c6\u300d&#xff09;<\/h5>\n<table>\n<tr>\u51b3\u7b56\u5224\u636e\u6e90\u7801\u4f4d\u7f6e\u9608\u503c<\/tr>\n<tbody>\n<tr>\n<td>\u662f\u5426\u8d70 Offset \u6001<\/td>\n<td>isValueStoredAsOffset(valueSize) \u2192 valueSize &gt; 256<\/td>\n<td>Core\/KeyValueHolder.h:85&#xff1b;\u8c03\u7528\u70b9 Core\/MMKV_IO.cpp:593, 620, 649, 849, 931\u3001Core\/CodedInputDataCrypt.cpp:255<\/td>\n<td>MediumBufferSize() &#061; 256<\/td>\n<\/tr>\n<tr>\n<td>\u975e Offset \u65f6\u9009 Direct \u8fd8\u662f Memory<\/td>\n<td>length &lt;&#061; SmallBufferSize()<\/td>\n<td>Core\/KeyValueHolder.cpp:45\u3001:61<\/td>\n<td>SmallBufferSize() &#061; 27<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u4e09\u6001\u7684\u771f\u5b9e\u5212\u5206\u533a\u95f4&#xff08;valueSize \u6307\u52a0\u5bc6\u8bb0\u5f55\u91cc value \u90a3\u6bb5\u7684\u957f\u5ea6&#xff0c;\u542b\u5b83\u81ea\u5df1\u7684 varint \u5934&#xff0c;\u89c1 MMKV_IO.cpp:592-593 \u7684 sizeNeededForData &#061; pbRawVarint32Size(len) &#043; len&#xff09;&#xff1a;<\/p>\n<ul>\n<li>0 ~ 27 B \u2192 Direct \u6001&#xff1a;\u503c\u5185\u8054\u5728 unordered_map \u8282\u70b9\u91cc&#xff0c;\u65e0\u989d\u5916\u5206\u914d&#xff1b;<\/li>\n<li>28 ~ 256 B \u2192 Memory \u6001&#xff1a;\u503c\u6302\u5728 void *memPtr&#xff1b;<\/li>\n<li>&gt; 256 B \u2192 Offset \u6001&#xff1a;\u5185\u5b58\u91cc\u53ea\u7559 offset &#043; keySize &#043; valueSize &#043; pbKeyValueSize &#043; cryptStatus\u3002<\/li>\n<\/ul>\n<p>\u8fb9\u754c\u7ec6\u8282&#xff1a;&gt; \u662f\u4e25\u683c\u5927\u4e8e&#xff0c;\u6240\u4ee5\u6070\u597d 256 \u5b57\u8282\u8d70\u7684\u662f\u975e Offset \u6001&#xff1b;27 \u8fd9\u4e00\u4fa7\u662f &lt;&#061;&#xff0c;\u542b 27\u3002<\/p>\n<h5>5.4.3 \u4e09\u6001\u5206\u522b\u5728\u54ea\u513f\u88ab\u521b\u5efa<\/h5>\n<table>\n<tr>\u5165\u53e3\u4ea7\u7269\u5173\u952e\u4ee3\u7801<\/tr>\n<tbody>\n<tr>\n<td>\u9996\u6b21\u52a0\u8f7d\/\u589e\u91cf\u89e3\u7801 CodedInputDataCrypt::readData<\/td>\n<td>&gt;256 \u2192 Offset&#xff1b;\u5426\u5219\u5148\u4e50\u89c2\u5199 type &#061; Direct&#xff08;:268&#xff09;&#xff0c;\u518d\u88ab :269 \u7684\u6784\u9020\u8fd4\u56de\u503c\u6574\u4f53\u8986\u76d6 \u2192 \u5b9e\u9645\u53ef\u80fd\u5347\u7ea7\u6210 Memory<\/td>\n<td>Core\/CodedInputDataCrypt.cpp:255-272<\/td>\n<\/tr>\n<tr>\n<td>\u5199\u5165\u5df2\u5b58\u5728\u7684 key&#xff08;\u52a0\u5bc6\u6a21\u5f0f\u8986\u76d6&#xff09;<\/td>\n<td>isValueStoredAsOffset \u5206\u53c9&#xff1a;Offset \u2192 (keySize, valueSize, offset) &#043; memcpy(&amp;cryptStatus, &amp;t_status, &#8230;)&#xff1b;\u5426\u5219 \u2192 KeyValueHolderCrypt(std::move(data))<\/td>\n<td>Core\/MMKV_IO.cpp:619-627<\/td>\n<\/tr>\n<tr>\n<td>\u5199\u5165\u65b0 key<\/td>\n<td>\u540c\u4e0a\u5206\u53c9&#xff0c;\u8d70 emplace<\/td>\n<td>Core\/MMKV_IO.cpp:649-657<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Core\/KeyValueHolder.h:87-90 \u90a3\u4e09\u4e2a\u6784\u9020\u51fd\u6570\u7684\u5206\u5de5\u975e\u5e38\u5e72\u51c0&#xff1a;(const void*, size_t) \u53ea\u4ea7 Direct \u6216 Memory&#xff1b;(MMBuffer&amp;&amp;) \u53ea\u4ea7 Direct \u6216 Memory&#xff1b;(keyLength, valueLength, offset) \u53ea\u4ea7 Offset&#xff08;:85-89&#xff0c;\u521d\u59cb\u5316\u5217\u8868\u91cc\u5199\u6b7b type(KeyValueHolderType_Offset)&#xff09;\u3002<\/p>\n<h5>5.4.4 \u8bfb\u8def\u5f84\u7684\u5206\u6c34\u5cad&#xff1a;toMMBuffer() \u2014\u2014 \u4e09\u6001\u771f\u6b63\u7684\u6536\u76ca\u4e0d\u5728\u7701\u5185\u5b58<\/h5>\n<p><span class=\"token comment\">\/\/ Core\/KeyValueHolder.cpp:155-168<\/span><br \/>\nMMBuffer <span class=\"token class-name\">KeyValueHolderCrypt<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">toMMBuffer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>basePtr<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">const<\/span> AESCrypt <span class=\"token operator\">*<\/span>crypter<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>type <span class=\"token operator\">&#061;&#061;<\/span> KeyValueHolderType_Direct<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token function\">MMBuffer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> paddedValue<span class=\"token punctuation\">,<\/span> paddedSize<span class=\"token punctuation\">,<\/span> MMBufferNoCopy<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :157<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>type <span class=\"token operator\">&#061;&#061;<\/span> KeyValueHolderType_Memory<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token function\">MMBuffer<\/span><span class=\"token punctuation\">(<\/span>memPtr<span class=\"token punctuation\">,<\/span> memSize<span class=\"token punctuation\">,<\/span> MMBufferNoCopy<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                    <span class=\"token comment\">\/\/ :159<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> realPtr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> basePtr <span class=\"token operator\">&#043;<\/span> offset<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> position <span class=\"token operator\">&#061;<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>pbKeyValueSize <span class=\"token operator\">&#043;<\/span> keySize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> realSize <span class=\"token operator\">&#061;<\/span> position <span class=\"token operator\">&#043;<\/span> valueSize<span class=\"token punctuation\">;<\/span>                                    <span class=\"token comment\">\/\/ :163<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> kvBuffer <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">MMBuffer<\/span><span class=\"token punctuation\">(<\/span>realPtr<span class=\"token punctuation\">,<\/span> realSize<span class=\"token punctuation\">,<\/span> MMBufferNoCopy<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> decrypter <span class=\"token operator\">&#061;<\/span> crypter<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">cloneWithStatus<\/span><span class=\"token punctuation\">(<\/span>cryptStatus<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>              <span class=\"token comment\">\/\/ :165 \u2605\u6062\u590d\u89e3\u5bc6\u73b0\u573a<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token function\">decryptBuffer<\/span><span class=\"token punctuation\">(<\/span>decrypter<span class=\"token punctuation\">,<\/span> kvBuffer<span class=\"token punctuation\">,<\/span> position<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                 <span class=\"token comment\">\/\/ :166 \u2605\u73b0\u573a\u89e3\u5bc6<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u8fd9\u662f\u6574\u6bb5\u8bbe\u8ba1\u91cc\u6700\u8be5\u8bb2\u51fa\u6765\u7684\u4e00\u70b9&#xff1a;Direct \/ Memory \u6001\u91cc\u5b58\u7684\u662f\u5df2\u7ecf\u89e3\u5bc6\u597d\u7684\u660e\u6587&#xff08;basePtr\/crypter \u4e24\u4e2a\u53c2\u6570\u5728 :157\u3001:159 \u5206\u652f\u91cc\u538b\u6839\u6ca1\u7528\u5230&#xff0c;\u8c03\u7528\u65b9\u751a\u81f3\u76f4\u63a5\u4f20 nullptr, nullptr \u2014\u2014 \u89c1 Core\/MMKV_IO.cpp:372&#xff09;\u3002\u4e5f\u5c31\u662f\u8bf4&#xff1a;<\/p>\n<ul>\n<li>Direct \/ Memory \u6001 &#061; \u4e00\u6b21\u89e3\u5bc6\u3001\u7ec8\u8eab\u547d\u4e2d\u3002\u4e4b\u540e\u6bcf\u6b21 decodeXxx \u90fd\u662f\u96f6\u62f7\u8d1d\u8fd4\u56de\u5185\u5b58\u89c6\u56fe&#xff0c;O(1)&#xff0c;\u5b8c\u5168\u4e0d\u505a AES \u8fd0\u7b97&#xff0c;\u4e5f\u4e0d\u78b0 mmap \u533a&#xff1b;<\/li>\n<li>Offset \u6001 &#061; \u6bcf\u6b21\u8bfb\u90fd\u8981\u73b0\u573a\u89e3\u5bc6&#xff1a;cloneWithStatus() \u590d\u5236\u4e00\u4e2a\u89e3\u5bc6\u5668\u5e76\u6062\u590d\u5230\u8fd9\u6761\u8bb0\u5f55\u4e4b\u524d\u7684 keystream \u72b6\u6001&#xff0c;\u518d decryptBuffer() \u987a\u5e8f\u8df3\u8fc7 position \u5b57\u8282&#xff08;Core\/KeyValueHolder.cpp:133-153 \u90a3\u4e2a 16 \u5b57\u8282\u6b65\u8fdb\u5faa\u73af&#xff09;\u624d\u80fd\u53d6\u5230\u503c\u3002<\/li>\n<\/ul>\n<p>\u6240\u4ee5\u4e09\u6001\u7684\u6392\u5e8f\u4e0d\u662f\u300c\u8d8a\u5c0f\u8d8a\u7701\u5185\u5b58\u300d&#xff0c;\u800c\u662f\u300c\u8d8a\u5c0f\u8d8a\u503e\u5411\u4e8e\u7528\u5185\u5b58\u6362 CPU\u300d\u3002\u914d\u7f6e\u9879\u7edd\u5927\u591a\u6570\u662f\u51e0\u5b57\u8282\u5230\u51e0\u5341\u5b57\u8282&#xff0c;\u76f4\u63a5\u4ee5\u660e\u6587\u5e38\u9a7b&#xff0c;\u628a\u6d41\u5bc6\u7801\u968f\u673a\u8bbf\u95ee\u5dee\u7684\u7f3a\u9677\u4e00\u6b21\u6027\u7ed5\u6389\u3002<\/p>\n<h5>5.4.5 \u4e3a\u4ec0\u4e48 Offset \u6001\u975e\u8981\u80cc 17 \u5b57\u8282\u7684 cryptStatus<\/h5>\n<p>AES-CFB128 \u662f\u6d41\u5f0f\u7528\u6cd5&#xff1a;\u7b2c n \u4e2a\u5b57\u8282\u7684 keystream \u4f9d\u8d56\u524d\u9762\u6240\u6709\u5757\u53cd\u9988\u51fa\u6765\u7684 m_vector&#xff08;IV&#xff09;\u4e0e m_number&#xff08;\u5757\u5185\u6e38\u6807&#xff09;&#xff0c;\u5b9a\u4e49\u89c1 Core\/aes\/AESCrypt.h:48-51\u3002\u5149\u6709 offset \u662f\u89e3\u4e0d\u51fa\u503c\u7684 \u2014\u2014 \u5fc5\u987b\u77e5\u9053\u300c\u89e3\u5230 offset \u5904\u4e3a\u6b62&#xff0c;\u6d41\u8d70\u5230\u54ea\u4e00\u6b65\u4e86\u300d\u3002 cryptStatus \u5c31\u662f\u8fd9\u4e2a\u5b58\u6863\u70b9\u3002\u5b83\u5728\u5199\u5165\u65f6\u7531 thread_local AESCryptStatus t_status&#xff08;Core\/MMKV_IO.cpp:577&#xff09;\u6293\u62cd\u3001memcpy \u8fdb holder&#xff08;:622\u3001:653&#xff09;&#xff0c;\u4e8e\u662f\u4efb\u610f\u4e00\u6761 Offset \u8bb0\u5f55\u90fd\u80fd\u88ab\u72ec\u7acb\u3001\u4e71\u5e8f\u5730\u89e3\u5bc6&#xff0c;\u4e0d\u5fc5\u4ece\u5934\u626b\u6587\u4ef6\u3002<\/p>\n<h5>5.4.6 \u91cd\u6574\u65f6\u4e09\u6001\u5f85\u9047\u4e0d\u540c&#xff1a;\u660e\u6587\u503c\u662f\u300c\u5f71\u5b50\u526f\u672c\u300d<\/h5>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:366-374  prepareEncode(MMKVMapCrypt&amp;)<\/span><br \/>\n<span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>itr <span class=\"token operator\">:<\/span> dic<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>kvHolder <span class=\"token operator\">&#061;<\/span> itr<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>kvHolder<span class=\"token punctuation\">.<\/span>type <span class=\"token operator\">&#061;&#061;<\/span> KeyValueHolderType_Offset<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        totalSize <span class=\"token operator\">&#043;&#061;<\/span> kvHolder<span class=\"token punctuation\">.<\/span>pbKeyValueSize <span class=\"token operator\">&#043;<\/span> kvHolder<span class=\"token punctuation\">.<\/span>keySize <span class=\"token operator\">&#043;<\/span> kvHolder<span class=\"token punctuation\">.<\/span>valueSize<span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :369 \u7559\u5728\u539f\u5730\u5f85 memmove<\/span><br \/>\n        smallestOffet <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">min<\/span><span class=\"token punctuation\">(<\/span>smallestOffet<span class=\"token punctuation\">,<\/span> kvHolder<span class=\"token punctuation\">.<\/span>offset<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        vec<span class=\"token punctuation\">.<\/span><span class=\"token function\">emplace_back<\/span><span class=\"token punctuation\">(<\/span>itr<span class=\"token punctuation\">.<\/span>first<span class=\"token punctuation\">,<\/span> kvHolder<span class=\"token punctuation\">.<\/span><span class=\"token function\">toMMBuffer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>            <span class=\"token comment\">\/\/ :372 \u660e\u6587\u91cd\u65b0\u5e8f\u5217\u5316<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<ul>\n<li>memmoveDictionary \u53ea\u628a Offset \u6001 \u6536\u8fdb vec \u53c2\u4e0e\u642c\u79fb&#xff08;Core\/MMKV_IO.cpp:1171-1174&#xff09;&#xff0c;\u642c\u5b8c\u91cd\u7b97 offset \u5e76\u91cd\u65b0 getCurStatus(cryptStatus)&#xff08;:1216-1225&#xff09;&#xff1b;<\/li>\n<li>Direct \/ Memory \u6001\u7684\u660e\u6587\u5219\u88ab MiniPBCoder::encodeDataWithObject(vec) \u91cd\u65b0\u7f16\u7801&#xff0c;\u5728 memmoveDictionary \u5c3e\u90e8\u91cd\u65b0\u52a0\u5bc6\u5199\u5230\u6587\u4ef6\u672b\u5c3e&#xff08;:1227-1239&#xff09;&#xff0c;\u800c holder \u81ea\u8eab\u7684 type \u548c\u5185\u5b58\u91cc\u7684\u660e\u6587\u7eb9\u4e1d\u4e0d\u52a8\u3002<\/li>\n<\/ul>\n<p>\u7ed3\u8bba&#xff1a;\u6587\u4ef6\u91cc\u90a3\u6761 Direct\/Memory \u8bb0\u5f55\u53ea\u662f\u5185\u5b58\u660e\u6587\u7684\u5f71\u5b50\u526f\u672c&#xff0c;\u7528\u6765\u4fdd\u8bc1\u5d29\u6e83\u540e\u8fd8\u80fd\u91cd\u5efa&#xff1b;\u8fd0\u884c\u671f\u8bfb\u5b83\u4e00\u5f8b\u8d70\u5185\u5b58\u3002toTuple()&#xff08;Core\/KeyValueHolder.h:102-104&#xff09;\u53ea\u66b4\u9732 Offset \u5206\u652f\u5b57\u6bb5&#xff0c;\u6b63\u662f\u8fd9\u5957\u5206\u5de5\u7684\u4f53\u73b0\u3002<\/p>\n<h5>5.4.7 \u751f\u547d\u5468\u671f\u7ea6\u675f&#xff08;union \u624b\u5de5\u7ba1\u7406 tagged union \u7684\u4ee3\u4ef7&#xff09;<\/h5>\n<ul>\n<li>\u7981\u6b62\u62f7\u8d1d&#xff1a;KeyValueHolderCrypt(const&amp;) &#061; delete\u3001operator&#061;(const&amp;) &#061; delete&#xff08;Core\/KeyValueHolder.h:107-108&#xff09;&#xff0c;\u56e0\u4e3a Memory \u6001\u6301\u6709\u88f8 void*&#xff0c;\u62f7\u4e00\u4efd\u5c31\u4f1a double free&#xff1b;<\/li>\n<li>\u53ea\u5141\u8bb8 move&#xff1a;move()&#xff08;Core\/KeyValueHolder.cpp:91-112&#xff09;\u91cc Direct\/Offset \u662f POD \u76f4\u63a5 memcpy \u6574\u5757&#xff08;:104-105&#xff09;&#xff0c;Memory \u624d\u8f6c\u79fb\u6307\u9488\u5e76\u628a\u6e90\u7f6e\u7a7a&#xff08;:106-110&#xff09;&#xff1b;<\/li>\n<li>\u6790\u6784\u6309 tag \u91ca\u653e&#xff1a;if (type &#061;&#061; KeyValueHolderType_Memory &amp;&amp; memPtr) free(memPtr);&#xff08;Core\/KeyValueHolder.cpp:114-118&#xff09;&#xff1b;<\/li>\n<li>\u957f\u5ea6\u53d6\u503c\u5fc5\u987b\u5206\u53c9&#xff1a;realValueSize()&#xff08;:120-130&#xff09;\u4e09\u6001\u5206\u522b\u8fd4\u56de paddedSize \/ valueSize \/ memSize \u2014\u2014 \u76f4\u63a5\u8bfb valueSize \u4f1a\u5728 Direct \u6001\u8bfb\u5230\u810f\u6570\u636e&#xff0c;\u8fd9\u662f\u8bfb union \u6700\u5178\u578b\u7684\u5751\u3002<\/li>\n<\/ul>\n<h5>5.4.8 \u4e0e\u5e38\u89c1\u8bf4\u6cd5\u7684\u5dee\u5f02&#xff08;\u3010\u7ea0\u504f\u3011&#xff09;<\/h5>\n<table>\n<tr>\u6d41\u4f20\u8bf4\u6cd5\u6e90\u7801\u5b9e\u9645<\/tr>\n<tbody>\n<tr>\n<td>\u300c\u6838\u5fc3\u5224\u65ad\u6807\u51c6\u662f MediumBufferSize() 256 \u5b57\u8282\u300d<\/td>\n<td>256 \u53ea\u51b3\u5b9a\u8981\u4e0d\u8981 Offset \u6001&#xff1b;Direct \u4e0e Memory \u7684\u5206\u754c\u662f\u53e6\u4e00\u4e2a\u5e38\u91cf SmallBufferSize() &#061; 27&#xff08;Core\/KeyValueHolder.cpp:45&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u300cMemory \u6001\u628a\u6570\u636e\u590d\u5236\u5230\u5806\u4e0a\u300d<\/td>\n<td>\u53ea\u5bf9\u89e3\u7801\u8def\u5f84\u6210\u7acb&#xff08;Core\/KeyValueHolder.cpp:52-56 \u786e\u5b9e malloc &#043; memcpy&#xff09;\u3002\u5199\u5165\u8def\u5f84\u662f\u96f6\u62f7\u8d1d\u63a5\u7ba1&#xff1a;KeyValueHolderCrypt(std::move(data)) \u76f4\u63a5 memPtr &#061; data.getPtr(); data.detach();&#xff08;:80-81&#xff09;&#xff0c;\u590d\u7528 MMBuffer \u5df2\u6709\u7684\u5806\u5757&#xff1b;\u53ea\u6709 Apple \u7684 NSData \u624d\u9000\u56de memcpy&#xff08;:71-78&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u300cDirect \u6001\u662f\u4e3a\u4e86\u7701\u4e00\u6b21\u6307\u9488\u8df3\u8f6c\u300d<\/td>\n<td>\u66f4\u4e3b\u8981\u7684\u6536\u76ca\u662f\u514d\u89e3\u5bc6&#xff1a;toMMBuffer() \u7684 Direct \u5206\u652f\u6839\u672c\u4e0d\u4f7f\u7528 crypter&#xff08;Core\/KeyValueHolder.cpp:156-157&#xff09;&#xff0c;\u5b58\u7684\u662f\u660e\u6587<\/td>\n<\/tr>\n<tr>\n<td>\u300c\u4e09\u6001\u662f\u4e3a\u4e86\u8ffd\u6c42\u6781\u81f4\u5b58\u50a8\u6548\u7387\u300d<\/td>\n<td>\u4e09\u6001\u4f18\u5316\u7684\u5bf9\u8c61\u662f\u5185\u5b58\u5b57\u5178\u7684\u5e38\u9a7b\u5b57\u8282\u6570 &#043; \u8bfb\u653e\u5927&#xff0c;\u8ddf\u78c1\u76d8\u5360\u7528\u65e0\u5173 \u2014\u2014 \u4e0d\u7ba1\u54ea\u4e2a\u6001&#xff0c;\u6587\u4ef6\u91cc\u90fd\u5b9e\u6253\u5b9e\u5199\u7740\u4e00\u4efd\u5b8c\u6574\u8bb0\u5f55&#xff08;MMKV_IO.cpp:372\/:1227-1239&#xff09;\u3002\u7701\u7684\u662f RAM \u548c\u89e3\u5bc6 CPU&#xff0c;\u4e0d\u662f\u78c1\u76d8<\/td>\n<\/tr>\n<tr>\n<td>\u300c\u975e\u52a0\u5bc6\u6a21\u5f0f\u4e5f\u8fd9\u6837\u300d<\/td>\n<td>\u4e09\u6001\u53ea\u5b58\u5728\u4e8e\u52a0\u5bc6\u6a21\u5f0f\u3002KeyValueHolder&#xff08;Core\/KeyValueHolder.h:32-42&#xff09;\u6c38\u8fdc\u53ea\u6709 offset \u4e00\u79cd\u5f62\u6001&#xff08;12 \u5b57\u8282&#xff09;&#xff0c;\u56e0\u4e3a\u4e0d\u9700\u89e3\u5bc6\u65f6\u300c\u53ea\u5b58\u5750\u6807\u300d\u672c\u8eab\u5c31\u662f\u96f6\u62f7\u8d1d\u6700\u4f18\u89e3&#xff0c;\u5185\u8054\u660e\u6587\u53cd\u800c\u8981\u989d\u5916\u7ef4\u62a4\u4e24\u4efd\u526f\u672c<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u4e00\u53e5\u8bdd\u9762\u8bd5\u7248&#xff1a;\u52a0\u5bc6\u6a21\u5f0f\u4e0b holder \u662f\u4e2a 29 \u5b57\u8282\u7684 tagged union&#xff0c;type \u4e00\u5b57\u8282\u51b3\u5b9a\u5269\u4e0b 28 \u5b57\u8282\u600e\u4e48\u89e3\u8bfb\u3002&gt; 256B \u8d70 Offset \u6001&#xff0c;\u53ea\u5b58\u5750\u6807\u52a0\u4e00\u4efd 17 \u5b57\u8282\u7684 AES \u5b58\u6863\u70b9&#xff0c;\u8bfb\u65f6\u73b0\u573a\u89e3\u5bc6&#xff1b;\u2264 27B \u8d70 Direct \u6001\u628a\u660e\u6587\u5185\u8054\u8fdb map \u8282\u70b9&#xff08;\u8e6d union \u5c3e\u90e8\u7a7a\u95f4&#xff0c;\u96f6\u989d\u5916\u5206\u914d&#xff09;&#xff1b;\u4e2d\u95f4\u90a3\u6863\u8d70 Memory \u6001&#xff0c;\u5199\u5165\u65f6\u9760 detach() \u767d\u5ad6 MMBuffer \u7684\u5806\u5757\u3002\u672c\u8d28\u662f\u7528\u5c11\u91cf\u5e38\u9a7b\u660e\u6587&#xff0c;\u6362\u6389\u6d41\u5f0f AES \u65e0\u6cd5\u968f\u673a\u8bbf\u95ee\u7684\u7f3a\u9677\u3002<\/p>\n<h4>5.5 CodedOutputData&#xff1a;\u5f80 mmap \u533a\u300c\u5199\u6307\u9488\u63a8\u8fdb\u300d<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/CodedOutputData.h \/ .cpp<\/span><br \/>\n<span class=\"token keyword\">class<\/span> <span class=\"token class-name\">CodedOutputData<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">void<\/span> <span class=\"token function\">writeData<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> MMBuffer <span class=\"token operator\">&amp;<\/span>data<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>          <span class=\"token comment\">\/\/ &#061; writeRawVarint32(len) &#043; memcpy<\/span><br \/>\n    <span class=\"token keyword\">void<\/span> <span class=\"token function\">writeRawData<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> MMBuffer <span class=\"token operator\">&amp;<\/span>data<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>       <span class=\"token comment\">\/\/ \u53ea memcpy&#xff0c;\u4e0d\u5e26\u957f\u5ea6\u524d\u7f00<\/span><br \/>\n    <span class=\"token keyword\">void<\/span> <span class=\"token function\">seek<\/span><span class=\"token punctuation\">(<\/span>size_t extraLength<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                 <span class=\"token comment\">\/\/ \u5199\u6307\u9488 &#043;&#061; extraLength<\/span><br \/>\n    <span class=\"token keyword\">void<\/span> <span class=\"token function\">setPosition<\/span><span class=\"token punctuation\">(<\/span>size_t position<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>             <span class=\"token comment\">\/\/ \u5199\u6307\u9488 &#061; position<\/span><br \/>\n    size_t <span class=\"token function\">spaceLeft<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span><span class=\"token function\">curWritePointer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>\u8d8a\u754c\u4fdd\u62a4\u662f \u629b\u5f02\u5e38&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/CodedOutputData.cpp: writeRawByte<\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_position <span class=\"token operator\">&gt;<\/span> m_size<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">throw<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">out_of_range<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;out of bound&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>MMKV_IO.cpp \u7684 append \u8def\u5f84\u5916\u9762\u5957\u4e86 try\/catch(&#8230;)&#xff08;\u89c1 6.3&#xff09;&#xff0c;\u6240\u4ee5\u8d8a\u754c\u4f1a\u88ab\u4f18\u96c5\u5730\u8f6c\u6210\u300c\u5199\u5931\u8d25\u8fd4\u56de false\u300d&#xff0c;\u800c\u4e0d\u662f\u5d29\u6e83\u3002\u6ce8\u610f\u987a\u5e8f&#xff1a;doAppendDataWithKey \u5148 ensureMemorySize(size) \u518d\u5199&#xff0c;\u5f02\u5e38\u53ea\u662f\u6700\u540e\u4e00\u9053\u9632\u7ebf\u3002<\/p>\n<h4>5.6 \u89e3\u7801&#xff1a;decodeOneMap \u4e0e\u300c\u5220\u9664\u4e5f\u662f\u8ffd\u52a0\u300d<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MiniPBCoder.cpp:506<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MiniPBCoder<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">decodeOneMap<\/span><span class=\"token punctuation\">(<\/span>MMKVMap <span class=\"token operator\">&amp;<\/span>dic<span class=\"token punctuation\">,<\/span> size_t position<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> greedy<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> block <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span>position<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">(<\/span>MMKVMap <span class=\"token operator\">&amp;<\/span>dictionary<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>position<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            m_inputData<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">seek<\/span><span class=\"token punctuation\">(<\/span>position<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>      <span class=\"token comment\">\/\/ :509 \u589e\u91cf\u89e3\u7801&#xff1a;\u8df3\u8fc7\u5df2\u6709\u524d\u7f00<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            m_inputData<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">readInt32<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>         <span class=\"token comment\">\/\/ :511 \u5168\u91cf\u89e3\u7801&#xff1a;\u5403\u6389 ItemSizeHolder<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">while<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_inputData<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">isAtEnd<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            KeyValueHolder kvHolder<span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">const<\/span> <span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>key <span class=\"token operator\">&#061;<\/span> m_inputData<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">readString<\/span><span class=\"token punctuation\">(<\/span>kvHolder<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                m_inputData<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">readData<\/span><span class=\"token punctuation\">(<\/span>kvHolder<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>kvHolder<span class=\"token punctuation\">.<\/span>valueSize <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                    dictionary<span class=\"token punctuation\">[<\/span>key<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">move<\/span><span class=\"token punctuation\">(<\/span>kvHolder<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                    <span class=\"token keyword\">auto<\/span> itr <span class=\"token operator\">&#061;<\/span> dictionary<span class=\"token punctuation\">.<\/span><span class=\"token function\">find<\/span><span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>itr <span class=\"token operator\">!&#061;<\/span> dictionary<span class=\"token punctuation\">.<\/span><span class=\"token function\">end<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                        dictionary<span class=\"token punctuation\">.<\/span><span class=\"token function\">erase<\/span><span class=\"token punctuation\">(<\/span>itr<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>        <span class=\"token comment\">\/\/ :523 \u2605valueSize&#061;&#061;0 \u8868\u793a\u5220\u9664<\/span><br \/>\n                    <span class=\"token punctuation\">}<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>greedy<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">block<\/span><span class=\"token punctuation\">(<\/span>dic<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token punctuation\">}<\/span>        <span class=\"token comment\">\/\/ :530 \u5c3d\u529b\u6062\u590d<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            MMKVMap tmpDic<span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token function\">block<\/span><span class=\"token punctuation\">(<\/span>tmpDic<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            dic<span class=\"token punctuation\">.<\/span><span class=\"token function\">swap<\/span><span class=\"token punctuation\">(<\/span>tmpDic<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                           <span class=\"token comment\">\/\/ :542 \u2605\u8981\u4e48\u5168\u6210&#xff0c;\u8981\u4e48\u5168\u4e0d\u52a8<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u4e09\u4e2a\u5fc5\u8003\u70b9&#xff1a;<\/p>\n<li>\u5220\u9664 &#061; \u8ffd\u52a0\u4e00\u6761 valueSize &#061;&#061; 0 \u7684\u5893\u7891\u8bb0\u5f55\u3002MMKV \u5168\u7a0b\u53ea\u6709 append&#xff0c;\u6ca1\u6709\u539f\u5730\u5220\u9664&#xff1b;\u7a7a\u4f4d\u9760\u7b2c 9 \u7ae0\u7684\u300c\u91cd\u6574\u300d\u56de\u6536\u3002\u8fd9\u4e0e LSM-tree \u7684\u601d\u8def\u4e00\u81f4\u3002<\/li>\n<li>greedy \u4e0e non-greedy \u7684\u533a\u522b\u5c31\u662f\u300c\u6570\u636e\u6062\u590d\u7b56\u7565\u300d\u3002\u6b63\u5e38\u52a0\u8f7d\u8d70 decodeMap&#xff08;\u975e greedy&#xff0c;\u5148\u5efa\u4e34\u65f6\u5b57\u5178\u518d swap&#xff0c;\u9047\u5230\u635f\u574f\u5b57\u8282\u5219\u6574\u8868\u653e\u5f03&#xff09;&#xff1b;CRC \u6821\u9a8c\u5931\u8d25\u4f46\u7528\u6237\u9009\u62e9 OnErrorRecover \u65f6\u8d70 greedyDecodeMap&#xff0c;\u628a\u635f\u574f\u70b9\u4e4b\u524d\u80fd\u89e3\u6790\u51fa\u6765\u7684\u8bb0\u5f55\u5168\u90e8\u7559\u4e0b&#xff0c;\u5c3d\u53ef\u80fd\u62a2\u6551\u6570\u636e\u3002\u89c1 Core\/MMKV_IO.cpp:103-121\u3002<\/li>\n<li>position !&#061; 0 \u5c31\u662f \u591a\u8fdb\u7a0b\u589e\u91cf\u540c\u6b65\u7684\u89e3\u7801\u5165\u53e3&#xff08;partialLoadFromFile \u4f20 oldActualSize&#xff09;\u3002<\/li>\n<hr \/>\n<h3>6. \u5199\u8def\u5f84\u5168\u94fe\u8def<\/h3>\n<p>\u4ee5 kv.encode(&#034;name&#034;, true) \u4e3a\u4f8b&#xff0c;\u5b8c\u6574\u8c03\u7528\u94fe&#xff1a;<\/p>\n<p>     &#034;MemoryFile.cpp&#034;<\/p>\n<p>     &#034;MMKV_IO.cpp&#034;<\/p>\n<p>     &#034;MMKV.cpp&#034;<\/p>\n<p>     &#034;native-bridge.cpp&#034;<\/p>\n<p>     &#034;MMKV.java&#034;<\/p>\n<p>      &#034;MemoryFile.cpp&#034;<\/p>\n<p>      &#034;MMKV_IO.cpp&#034;<\/p>\n<p>      &#034;MMKV.cpp&#034;<\/p>\n<p>      &#034;native-bridge.cpp&#034;<\/p>\n<p>      &#034;MMKV.java&#034;<\/p>\n<p>  #mermaid-svg-h5DsdzQJGxstEDeS{font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-h5DsdzQJGxstEDeS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-h5DsdzQJGxstEDeS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-h5DsdzQJGxstEDeS .error-icon{fill:#552222;}#mermaid-svg-h5DsdzQJGxstEDeS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-h5DsdzQJGxstEDeS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-h5DsdzQJGxstEDeS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-h5DsdzQJGxstEDeS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-h5DsdzQJGxstEDeS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-h5DsdzQJGxstEDeS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-h5DsdzQJGxstEDeS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-h5DsdzQJGxstEDeS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-h5DsdzQJGxstEDeS .marker.cross{stroke:#333333;}#mermaid-svg-h5DsdzQJGxstEDeS svg{font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-h5DsdzQJGxstEDeS p{margin:0;}#mermaid-svg-h5DsdzQJGxstEDeS .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-h5DsdzQJGxstEDeS text.actor&gt;tspan{fill:black;stroke:none;}#mermaid-svg-h5DsdzQJGxstEDeS .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-h5DsdzQJGxstEDeS .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-h5DsdzQJGxstEDeS .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-h5DsdzQJGxstEDeS .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-h5DsdzQJGxstEDeS #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-h5DsdzQJGxstEDeS .sequenceNumber{fill:white;}#mermaid-svg-h5DsdzQJGxstEDeS #sequencenumber{fill:#333;}#mermaid-svg-h5DsdzQJGxstEDeS #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-h5DsdzQJGxstEDeS .messageText{fill:#333;stroke:none;}#mermaid-svg-h5DsdzQJGxstEDeS .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-h5DsdzQJGxstEDeS .labelText,#mermaid-svg-h5DsdzQJGxstEDeS .labelText&gt;tspan{fill:black;stroke:none;}#mermaid-svg-h5DsdzQJGxstEDeS .loopText,#mermaid-svg-h5DsdzQJGxstEDeS .loopText&gt;tspan{fill:black;stroke:none;}#mermaid-svg-h5DsdzQJGxstEDeS .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-h5DsdzQJGxstEDeS .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-h5DsdzQJGxstEDeS .noteText,#mermaid-svg-h5DsdzQJGxstEDeS .noteText&gt;tspan{fill:black;stroke:none;}#mermaid-svg-h5DsdzQJGxstEDeS .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-h5DsdzQJGxstEDeS .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-h5DsdzQJGxstEDeS .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-h5DsdzQJGxstEDeS .actorPopupMenu{position:absolute;}#mermaid-svg-h5DsdzQJGxstEDeS .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 \/ 0.4));}#mermaid-svg-h5DsdzQJGxstEDeS .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-h5DsdzQJGxstEDeS .actor-man circle,#mermaid-svg-h5DsdzQJGxstEDeS line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-h5DsdzQJGxstEDeS :root{&#8211;mermaid-font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;}<\/p>\n<p>   encodeBool(handle, key, value)<\/p>\n<p>   kv-&gt;&gt;set((bool)value, key)<\/p>\n<p>   MMBuffer &#043; CodedOutputData \u7f16\u7801\u5230\u4e34\u65f6 buffer<\/p>\n<p>   setDataForKey(move(data), key)<\/p>\n<p>   SCOPED_LOCK(m_lock) &#043; SCOPED_LOCK(m_exclusiveProcessLock)<\/p>\n<p>   checkLoadData() \u2190 \u591a\u8fdb\u7a0b\u4e00\u81f4\u6027\u5165\u53e3<\/p>\n<p>   appendDataWithKey \/ overrideDataWithKey<\/p>\n<p>   ensureMemorySize(size)<\/p>\n<p>   (\u7a7a\u95f4\u4e0d\u8db3) truncate &#043; doFullWriteBack<\/p>\n<p>   m_output-&gt;&gt;writeData() \u5199\u8fdb mmap \u533a<\/p>\n<p>   m_actualSize &#043;&#061; size<\/p>\n<p>   updateCRCDigest() \u2192 writeActualSize() \u5199 .crc<\/p>\n<h4>6.1 Java \u2192 C&#043;&#043; \u7684\u7f16\u89e3\u7801<\/h4>\n<p><span class=\"token comment\">\/\/ MMKV.java:713<\/span><br \/>\n<span class=\"token keyword\">public<\/span> <span class=\"token keyword\">boolean<\/span> <span class=\"token function\">encode<\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">String<\/span> key<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">boolean<\/span> value<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token function\">encodeBool<\/span><span class=\"token punctuation\">(<\/span>nativeHandle<span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">,<\/span> value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ native-bridge.cpp: _encodeBool&#xff08;\u8282\u9009&#xff09;<\/span><br \/>\n<span class=\"token keyword\">static<\/span> jboolean <span class=\"token function\">_encodeBool<\/span><span class=\"token punctuation\">(<\/span>JNIEnv <span class=\"token operator\">*<\/span>env<span class=\"token punctuation\">,<\/span> jobject<span class=\"token punctuation\">,<\/span> jlong handle<span class=\"token punctuation\">,<\/span> jstring jsKey<span class=\"token punctuation\">,<\/span> jboolean value<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> kv <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span>MMKV <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> handle<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> kv<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">set<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">bool<\/span><span class=\"token punctuation\">)<\/span> value<span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:451<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">set<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">bool<\/span> value<span class=\"token punctuation\">,<\/span> MMKVKey_t key<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">uint32_t<\/span> expireDuration<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">isKeyEmpty<\/span><span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    size_t size <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">mmkv_unlikely<\/span><span class=\"token punctuation\">(<\/span>m_enableKeyExpire<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">?<\/span> Fixed32Size <span class=\"token operator\">&#043;<\/span> <span class=\"token function\">pbBoolSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">:<\/span> <span class=\"token function\">pbBoolSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    MMBuffer <span class=\"token function\">data<\/span><span class=\"token punctuation\">(<\/span>size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    CodedOutputData <span class=\"token function\">output<\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">.<\/span><span class=\"token function\">getPtr<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    output<span class=\"token punctuation\">.<\/span><span class=\"token function\">writeBool<\/span><span class=\"token punctuation\">(<\/span>value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">mmkv_unlikely<\/span><span class=\"token punctuation\">(<\/span>m_enableKeyExpire<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> time <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span>expireDuration <span class=\"token operator\">!&#061;<\/span> ExpireNever<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">?<\/span> <span class=\"token function\">getCurrentTimeInSecond<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> expireDuration <span class=\"token operator\">:<\/span> ExpireNever<span class=\"token punctuation\">;<\/span><br \/>\n        output<span class=\"token punctuation\">.<\/span><span class=\"token function\">writeRawLittleEndian32<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">UInt32ToInt32<\/span><span class=\"token punctuation\">(<\/span>time<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :461 \u503c\u540e\u9762\u62fc 4 \u5b57\u8282\u8fc7\u671f\u65f6\u95f4<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token function\">setDataForKey<\/span><span class=\"token punctuation\">(<\/span>std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">move<\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u8981\u70b9&#xff1a;\u503c\u5148\u5728 \u5806\u4e0a\u7684\u4e34\u65f6 MMBuffer \u91cc\u7f16\u7801\u597d&#xff0c;\u518d\u4e00\u6b21\u6027\u5199\u8fdb mmap \u533a\u3002\u4e3a\u4ec0\u4e48\u4e0d\u591a\u5199\u4e00\u6b65\u5230\u4f4d&#xff1f;\u56e0\u4e3a\u9700\u8981\u5148\u77e5\u9053 size \u624d\u80fd ensureMemorySize&#xff0c;\u4e14\u91cd\u6574\u903b\u8f91&#xff08;checkSizeForOverride&#xff09;\u9700\u8981 MMBuffer \u505a\u7b49\u503c\u6bd4\u8f83\u3002mmkv_unlikely \u662f\u5206\u652f\u9884\u6d4b\u63d0\u793a\u5b8f&#xff0c;\u628a\u8fc7\u671f\u903b\u8f91\u4ece\u70ed\u8def\u5f84\u4e0a\u300c\u6324\u51fa\u53bb\u300d\u3002<\/p>\n<h4>6.2 setDataForKey&#xff1a;\u4e09\u5c94\u8def\u53e3<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:581&#xff08;\u975e\u52a0\u5bc6\u5206\u652f&#xff0c;:662 \u8d77&#xff09;<\/span><br \/>\n<span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> itr <span class=\"token operator\">&#061;<\/span> m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">find<\/span><span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>itr <span class=\"token operator\">!&#061;<\/span> m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">end<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token comment\">\/\/ \u2460 compareBeforeSet&#xff1a;\u503c\u6ca1\u53d8\u5c31\u76f4\u63a5\u8fd4\u56de true&#xff0c;\u4e00\u4e2a\u5b57\u8282\u90fd\u4e0d\u5199<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">isCompareBeforeSetEnabled<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> basePtr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">(<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">;<\/span><br \/>\n            MMBuffer oldValueData <span class=\"token operator\">&#061;<\/span> itr<span class=\"token operator\">-&gt;<\/span>second<span class=\"token punctuation\">.<\/span><span class=\"token function\">toMMBuffer<\/span><span class=\"token punctuation\">(<\/span>basePtr<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>oldValueData <span class=\"token operator\">&#061;&#061;<\/span> data<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span>                    <span class=\"token comment\">\/\/ :686 \u2605\u7701\u6389\u4e00\u6b21 append &#043; \u4e00\u6b21 CRC &#043; \u4e00\u6b21 meta \u5199<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token comment\">\/\/ \u2461 \u5168\u5e93\u53ea\u6709\u4e00\u4e2a key \u65f6&#xff0c;\u539f\u5730\u8986\u76d6\u800c\u4e0d\u662f\u8ffd\u52a0<\/span><br \/>\n        <span class=\"token keyword\">bool<\/span> onlyOneKey <span class=\"token operator\">&#061;<\/span> <span class=\"token operator\">!<\/span>m_isInterProcess <span class=\"token operator\">&amp;&amp;<\/span> m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">size<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        KVHolderRet_t ret<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>onlyOneKey<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">overrideDataWithKey<\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">,<\/span> itr<span class=\"token operator\">-&gt;<\/span>second<span class=\"token punctuation\">,<\/span> isDataHolder<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :695<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">appendDataWithKey<\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">,<\/span> itr<span class=\"token operator\">-&gt;<\/span>second<span class=\"token punctuation\">,<\/span> isDataHolder<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>     <span class=\"token comment\">\/\/ :697<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        itr<span class=\"token operator\">-&gt;<\/span>second <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">move<\/span><span class=\"token punctuation\">(<\/span>ret<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token comment\">\/\/ \u2462 \u65b0 key&#xff1a;\u8ffd\u52a0<\/span><br \/>\n        ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">appendDataWithKey<\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">,<\/span> isDataHolder<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">emplace<\/span><span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">,<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">move<\/span><span class=\"token punctuation\">(<\/span>kvHolder<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u5165\u53e3\u7684\u4e09\u4ef6\u5957&#xff08;Core\/MMKV_IO.cpp:585-587&#xff09;&#xff1a;<\/p>\n<p><span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_lock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                    <span class=\"token comment\">\/\/ :585 \u8fdb\u7a0b\u5185\u9012\u5f52\u4e92\u65a5\u9501<\/span><br \/>\n<span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_exclusiveProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>    <span class=\"token comment\">\/\/ :586 \u8de8\u8fdb\u7a0b\u72ec\u5360\u6587\u4ef6\u9501<\/span><br \/>\n<span class=\"token function\">checkLoadData<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                        <span class=\"token comment\">\/\/ :587 \u5148\u540c\u6b65\u5176\u4ed6\u8fdb\u7a0b\u7684\u589e\u91cf<\/span><\/p>\n<p>onlyOneKey \u8fd9\u4e2a\u7279\u4f8b\u503c\u5f97\u5355\u72ec\u8bf4&#xff1a;\u5fae\u4fe1\u91cc\u5927\u91cf MMKV \u5b9e\u4f8b\u53ea\u5b58\u4e00\u4e2a\u8ba1\u6570\u5668\u3002\u5982\u679c\u6bcf\u6b21 &#043;1 \u90fd\u8ffd\u52a0&#xff0c;\u6587\u4ef6\u4f1a\u65e0\u610f\u4e49\u5730\u81a8\u80c0\u5e76\u9891\u7e41\u91cd\u6574\u3002\u5355 key \u573a\u666f\u76f4\u63a5\u4ece\u5934\u8986\u76d6\u5199&#xff0c;\u628a\u300c\u8ffd\u52a0\u578b\u5b58\u50a8\u300d\u53d8\u6210\u300c\u539f\u5730\u66f4\u65b0\u300d&#xff0c;\u4ee3\u4ef7\u662f\u91cd\u6574\u65f6\u4e0d\u9700\u8981 memmove\u3002\u5b83\u540c\u65f6\u53d7 !m_isInterProcess \u7ea6\u675f\u2014\u2014\u591a\u8fdb\u7a0b\u6a21\u5f0f\u7981\u6b62 override&#xff0c;\u56e0\u4e3a\u522b\u7684\u8fdb\u7a0b\u53ef\u80fd\u6b63\u5728\u8bfb\u90a3\u4e2a\u533a\u95f4\u3002<\/p>\n<h4>6.3 \u8ffd\u52a0\u5199\u7684\u6b63\u8eab&#xff1a;doAppendDataWithKey<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:822<\/span><br \/>\nKVHolderRet_t <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">doAppendDataWithKey<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> MMBuffer <span class=\"token operator\">&amp;<\/span>data<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">const<\/span> MMBuffer <span class=\"token operator\">&amp;<\/span>keyData<span class=\"token punctuation\">,<\/span><br \/>\n                                        <span class=\"token keyword\">bool<\/span> isDataHolder<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">uint32_t<\/span> originKeyLength<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> isKeyEncoded <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span>originKeyLength <span class=\"token operator\">&lt;<\/span> keyData<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>     <span class=\"token comment\">\/\/ :823<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> keyLength <span class=\"token operator\">&#061;<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>keyData<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> valueLength <span class=\"token operator\">&#061;<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>isDataHolder<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> valueLength <span class=\"token operator\">&#043;&#061;<\/span> <span class=\"token function\">pbRawVarint32Size<\/span><span class=\"token punctuation\">(<\/span>valueLength<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    size_t size <span class=\"token operator\">&#061;<\/span> isKeyEncoded <span class=\"token operator\">?<\/span> keyLength <span class=\"token operator\">:<\/span> <span class=\"token punctuation\">(<\/span>keyLength <span class=\"token operator\">&#043;<\/span> <span class=\"token function\">pbRawVarint32Size<\/span><span class=\"token punctuation\">(<\/span>keyLength<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :830<\/span><br \/>\n    size <span class=\"token operator\">&#043;&#061;<\/span> valueLength <span class=\"token operator\">&#043;<\/span> <span class=\"token function\">pbRawVarint32Size<\/span><span class=\"token punctuation\">(<\/span>valueLength<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                  <span class=\"token comment\">\/\/ :832<\/span><\/p>\n<p>    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_exclusiveProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>              <span class=\"token comment\">\/\/ :834<\/span><br \/>\n    <span class=\"token keyword\">bool<\/span> hasEnoughSize <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">ensureMemorySize<\/span><span class=\"token punctuation\">(<\/span>size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>      <span class=\"token comment\">\/\/ :836 \u2605\u7a7a\u95f4\u4fdd\u969c<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>hasEnoughSize <span class=\"token operator\">||<\/span> <span class=\"token operator\">!<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token function\">make_pair<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">false<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">KeyValueHolder<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>isKeyEncoded<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> m_output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">writeRawData<\/span><span class=\"token punctuation\">(<\/span>keyData<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>   <span class=\"token comment\">\/\/ :856 \u5df2\u5e26 varint \u5934<\/span><br \/>\n        <span class=\"token keyword\">else<\/span>              <span class=\"token punctuation\">{<\/span> m_output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">writeData<\/span><span class=\"token punctuation\">(<\/span>keyData<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token punctuation\">}<\/span>    <span class=\"token comment\">\/\/ :858<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>isDataHolder<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> m_output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">writeRawVarint32<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">int32_t<\/span><span class=\"token punctuation\">)<\/span> valueLength<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        m_output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">writeData<\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                 <span class=\"token comment\">\/\/ :863<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>std<span class=\"token double-colon punctuation\">::<\/span>exception <span class=\"token operator\">&amp;<\/span>e<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;%s&#034;<\/span><span class=\"token punctuation\">,<\/span> e<span class=\"token punctuation\">.<\/span><span class=\"token function\">what<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token function\">make_pair<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">false<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">KeyValueHolder<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n      <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;append fail&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token function\">make_pair<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">false<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">KeyValueHolder<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">auto<\/span> offset <span class=\"token operator\">&#061;<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>m_actualSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> ptr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> Fixed32Size <span class=\"token operator\">&#043;<\/span> m_actualSize<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_crypter<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> m_crypter<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">encrypt<\/span><span class=\"token punctuation\">(<\/span>ptr<span class=\"token punctuation\">,<\/span> ptr<span class=\"token punctuation\">,<\/span> size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>         <span class=\"token comment\">\/\/ :876 \u539f\u5730\u52a0\u5bc6<\/span><br \/>\n    m_actualSize <span class=\"token operator\">&#043;&#061;<\/span> size<span class=\"token punctuation\">;<\/span>                                          <span class=\"token comment\">\/\/ :879<\/span><br \/>\n    <span class=\"token function\">updateCRCDigest<\/span><span class=\"token punctuation\">(<\/span>ptr<span class=\"token punctuation\">,<\/span> size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                    <span class=\"token comment\">\/\/ :880 \u2605\u589e\u91cf CRC &#043; \u5199 meta<\/span><\/p>\n<p>    <span class=\"token keyword\">return<\/span> <span class=\"token function\">make_pair<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">true<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">KeyValueHolder<\/span><span class=\"token punctuation\">(<\/span>originKeyLength<span class=\"token punctuation\">,<\/span> valueLength<span class=\"token punctuation\">,<\/span> offset<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u6027\u80fd\u89e3\u8bfb&#xff08;\u9762\u8bd5\u53ef\u76f4\u63a5\u80cc&#xff09;&#xff1a;\u4e00\u6b21 encode \u7684\u5b9e\u9645 CPU \u6210\u672c &#061;<\/p>\n<li>\u4e00\u6b21 unordered_map::find&#xff1b;<\/li>\n<li>\u4e24\u6b21 memcpy&#xff08;key \u4e0e value&#xff09;\u5230 mmap \u533a&#xff1b;<\/li>\n<li>\u4e00\u6b21 CRC32 \u589e\u91cf\u8ba1\u7b97&#xff08;aarch64 \u4e0a\u662f\u786c\u4ef6\u6307\u4ee4&#xff09;&#xff1b;<\/li>\n<li>\u4e00\u6b21 memcpy \u5199 4&#043;4 \u5b57\u8282\u7684 meta&#xff08;writeCRCAndActualSizeOnly&#xff0c;Core\/MMKVMetaInfo.hpp:81&#xff09;\u3002<\/li>\n<p>\u6ca1\u6709 write() \u7cfb\u7edf\u8c03\u7528\u3001\u6ca1\u6709 fsync\u3001\u6ca1\u6709 \u5168\u91cf\u5e8f\u5217\u5316\u3001\u6ca1\u6709 \u5185\u6838\u6001\/\u7528\u6237\u6001\u62f7\u8d1d\u3002\u8fd9\u5c31\u662f\u300c\u6beb\u79d2\u7ea7\u751a\u81f3\u5fae\u79d2\u7ea7\u5199\u5165\u300d\u7684\u7531\u6765\u3002<\/p>\n<p>\u4e00\u4e2a\u9690\u85cf\u4f18\u5316\u5728 appendDataWithKey(data, kvHolder, &#8230;)&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:1001&#xff08;key \u5df2\u5b58\u5728\u65f6&#xff0c;\u590d\u7528\u6587\u4ef6\u91cc\u5df2\u7f16\u7801\u597d\u7684 key \u5b57\u8282&#xff09;<\/span><br \/>\n<span class=\"token keyword\">uint32_t<\/span> keyLength <span class=\"token operator\">&#061;<\/span> kvHolder<span class=\"token punctuation\">.<\/span>keySize<span class=\"token punctuation\">;<\/span><br \/>\nsize_t rawKeySize <span class=\"token operator\">&#061;<\/span> keyLength <span class=\"token operator\">&#043;<\/span> <span class=\"token function\">pbRawVarint32Size<\/span><span class=\"token punctuation\">(<\/span>keyLength<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>        <span class=\"token comment\">\/\/ :1006<\/span><br \/>\n<span class=\"token punctuation\">{<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token function\">ensureMemorySize<\/span><span class=\"token punctuation\">(<\/span>size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                                      <span class=\"token comment\">\/\/ :1015 \u2605\u5148\u6269\u5bb9&#xff0c;\u56e0\u4e3a offset \u4f1a\u53d8<\/span><br \/>\n<span class=\"token keyword\">auto<\/span> basePtr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">;<\/span><br \/>\nMMBuffer <span class=\"token function\">keyData<\/span><span class=\"token punctuation\">(<\/span>basePtr <span class=\"token operator\">&#043;<\/span> kvHolder<span class=\"token punctuation\">.<\/span>offset<span class=\"token punctuation\">,<\/span> rawKeySize<span class=\"token punctuation\">,<\/span> MMBufferNoCopy<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :1021<\/span><br \/>\n<span class=\"token keyword\">return<\/span> <span class=\"token function\">doAppendDataWithKey<\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">,<\/span> keyData<span class=\"token punctuation\">,<\/span> isDataHolder<span class=\"token punctuation\">,<\/span> keyLength<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>\u66f4\u65b0\u5df2\u6709 key \u65f6&#xff0c;\u4e0d\u518d\u4ece std::string \u91cd\u65b0\u7f16\u7801 key&#xff0c;\u800c\u662f\u76f4\u63a5\u4ece mmap \u91cc\u6309 offset \u5207\u4e00\u6bb5\u96f6\u62f7\u8d1d\u89c6\u56fe\u590d\u7528&#xff08;isKeyEncoded &#061;&#061; true \u5206\u652f&#xff09;\u3002\u7701\u4e00\u6b21 varint \u7f16\u7801 &#043; \u4e00\u6b21\u62f7\u8d1d\u3002<\/p>\n<h4>6.4 \u66f4\u65b0\u540e\u7684\u300c\u810f\u8bfb\u300d\u6807\u8bb0<\/h4>\n<p>setDataForKey \u7ed3\u5c3e\u4f1a m_hasFullWriteback &#061; false\u3002\u8fd9\u4e2a\u6807\u5fd7\u4f4d\u662f\u7b2c 9 \u7ae0 fullWriteback() \u7684\u77ed\u8def\u5f00\u5173&#xff1a;\u53ea\u8981\u53d1\u751f\u8fc7 append&#xff0c;\u5c31\u8ba4\u4e3a\u6587\u4ef6\u91cc\u5b58\u5728\u65e0\u6548\u65e7\u6570\u636e&#xff0c;\u9700\u8981\u62e9\u673a\u91cd\u6574\u3002<\/p>\n<h4>6.5 \u5220\u9664\u3001\u6e05\u7a7a\u3001\u6539\u540d<\/h4>\n<table>\n<tr>API\u6e90\u7801\u884c\u4e3a<\/tr>\n<tbody>\n<tr>\n<td>removeValueForKey(key)<\/td>\n<td>Core\/MMKV.cpp \u2192 setDataForKey(MMBuffer(), key, true)<\/td>\n<td>\u8ffd\u52a0\u4e00\u6761 valueSize &#061;&#061; 0 \u7684\u5893\u7891&#xff0c;\u5185\u5b58\u5b57\u5178 erase<\/td>\n<\/tr>\n<tr>\n<td>removeValuesForKeys(keys)<\/td>\n<td>\u5faa\u73af\u8c03\u7528&#xff0c;\u4ec5\u5728\u6700\u540e sync<\/td>\n<td>\u6279\u91cf\u5220\u9664<\/td>\n<\/tr>\n<tr>\n<td>clearAll() \/ clearMemoryCache(keepSpace)<\/td>\n<td>Core\/MMKV_IO.cpp:1456<\/td>\n<td>writeActualSize(0,0,nullptr,IncreaseSequence)&#xff1b;keepSpace&#061;false \u65f6 truncate \u56de\u9ed8\u8ba4\u5927\u5c0f<\/td>\n<\/tr>\n<tr>\n<td>reKey(newKey)&#xff08;\u6362\u52a0\u5bc6\u5bc6\u94a5&#xff09;<\/td>\n<td>Core\/MMKV_IO.cpp:1345<\/td>\n<td>\u89c1 11.4<\/td>\n<\/tr>\n<tr>\n<td>trim()<\/td>\n<td>Core\/MMKV_IO.cpp:1413<\/td>\n<td>\u552f\u4e00\u7f29\u5bb9\u5165\u53e3&#xff0c;\u89c1 9.5 \/ 9.6<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>7. \u8bfb\u8def\u5f84\u5168\u94fe\u8def<\/h3>\n<h4>7.1 getBool \u5168\u6587<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:784<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">getBool<\/span><span class=\"token punctuation\">(<\/span>MMKVKey_t key<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> defaultValue<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> <span class=\"token operator\">*<\/span>hasValue<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">isKeyEmpty<\/span><span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token keyword\">return<\/span> defaultValue<span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_lock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                 <span class=\"token comment\">\/\/ :791 \u8fdb\u7a0b\u5185\u4e92\u65a5<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_sharedProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>    <span class=\"token comment\">\/\/ :792 \u2605\u8de8\u8fdb\u7a0b\u5171\u4eab\u9501<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> data <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">getDataForKey<\/span><span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">try<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            CodedInputData <span class=\"token function\">input<\/span><span class=\"token punctuation\">(<\/span>data<span class=\"token punctuation\">.<\/span><span class=\"token function\">getPtr<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> data<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>hasValue <span class=\"token operator\">!&#061;<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token operator\">*<\/span>hasValue <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> input<span class=\"token punctuation\">.<\/span><span class=\"token function\">readBool<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span>std<span class=\"token double-colon punctuation\">::<\/span>exception <span class=\"token operator\">&amp;<\/span>exception<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;%s&#034;<\/span><span class=\"token punctuation\">,<\/span> exception<span class=\"token punctuation\">.<\/span><span class=\"token function\">what<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n          <span class=\"token keyword\">catch<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;decode fail&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>hasValue <span class=\"token operator\">!&#061;<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token operator\">*<\/span>hasValue <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> defaultValue<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:543<\/span><br \/>\nMMBuffer <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">getRawDataForKey<\/span><span class=\"token punctuation\">(<\/span>MMKVKey_t key<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">checkLoadData<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                          <span class=\"token comment\">\/\/ :544 \u2605\u6bcf\u6b21\u8bfb\u90fd\u505a\u4e00\u6b21\u300c\u6709\u6ca1\u6709\u522b\u4eba\u6539\u8fc7\u300d\u7684\u5224\u65ad<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> itr <span class=\"token operator\">&#061;<\/span> m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">find<\/span><span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>itr <span class=\"token operator\">!&#061;<\/span> m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">end<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> basePtr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">(<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> itr<span class=\"token operator\">-&gt;<\/span>second<span class=\"token punctuation\">.<\/span><span class=\"token function\">toMMBuffer<\/span><span class=\"token punctuation\">(<\/span>basePtr<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>               <span class=\"token comment\">\/\/ :558 \u96f6\u62f7\u8d1d\u89c6\u56fe<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    MMBuffer nan<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> nan<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h4>7.2 \u8bfb\u6210\u672c\u5206\u6790<\/h4>\n<p>\u5355\u8fdb\u7a0b\u6a21\u5f0f\u4e0b m_sharedProcessLock-&gt;m_enable &#061;&#061; false&#xff0c;\u9501\u662f\u7a7a\u64cd\u4f5c&#xff0c;\u6240\u4ee5\u4e00\u6b21\u8bfb\u7684\u4ee3\u4ef7\u5c31\u662f&#xff1a;<\/p>\n<li>checkLoadData() \u91cc\u7684 if (!m_isInterProcess) return;&#xff08;Core\/MMKV_IO.cpp:313&#xff09;\u2014\u2014\u4e00\u6b21\u5206\u652f&#xff1b;<\/li>\n<li>\u4e00\u6b21\u54c8\u5e0c\u67e5\u627e&#xff1b;<\/li>\n<li>\u4e00\u6b21\u6307\u9488\u7b97\u672f\u6784\u9020 MMBuffer&#xff08;NoCopy&#xff09;&#xff1b;<\/li>\n<li>CodedInputData::readBool() \u4e4b\u7c7b\u7684 \u5355\u503c\u89e3\u7801\u3002<\/li>\n<p>\u4e0e SharedPreferences \u7684\u6839\u672c\u5dee\u522b&#xff1a;SP \u7684 getXxx \u53ea\u662f\u67e5 ArrayMap&lt;String, Object&gt;&#xff0c;\u770b\u4f3c\u4e5f\u5f88\u5feb&#xff0c;\u4f46 \u5b83\u8981\u6c42\u542f\u52a8\u65f6\u628a\u6574\u4e2a XML \u5168\u91cf\u89e3\u6790\u8fdb\u5185\u5b58&#xff0c;\u9996\u6b21 getInt() \u5728 loadFromDisk \u672a\u5b8c\u6210\u65f6\u4f1a\u963b\u585e&#xff1b;MMKV \u662f \u61d2\u52a0\u8f7d &#043; \u5355\u503c\u89e3\u7801&#xff0c;\u4e14\u52a0\u8f7d\u672c\u8eab\u5c31\u662f\u987a\u5e8f\u626b\u4e00\u904d mmap \u533a\u5efa offset \u8868&#xff0c;\u65e0\u5bf9\u8c61\u5206\u914d&#xff08;\u9664 map \u8282\u70b9&#xff09;\u3002<\/p>\n<h4>7.3 \u8bfb\u7528 shared\u3001\u5199\u7528 exclusive \u7684\u610f\u4e49<\/h4>\n<p><span class=\"token comment\">\/\/ \u8bfb&#xff1a;Core\/MMKV.cpp:792 \u2192 SCOPED_LOCK(m_sharedProcessLock)<\/span><br \/>\n<span class=\"token comment\">\/\/ \u5199&#xff1a;Core\/MMKV_IO.cpp:586 \u2192 SCOPED_LOCK(m_exclusiveProcessLock)<\/span><\/p>\n<p>\u591a\u8fdb\u7a0b\u573a\u666f\u4e0b&#xff0c;\u540c\u4e00\u53f0\u673a\u5668\u4e0a\u7684 N \u4e2a\u8fdb\u7a0b\u53ef\u4ee5\u5e76\u53d1\u8bfb\u540c\u4e00\u4e2a MMKV&#xff08;flock \u7684 LOCK_SH \u53ef\u91cd\u5165\u53e0\u52a0&#xff09;&#xff0c;\u4f46\u4efb\u4f55\u5199\u5165\/\u91cd\u6574\u90fd\u5fc5\u987b LOCK_EX\u3002\u8fd9\u6bd4\u300c\u5168\u5c40\u4e00\u628a\u4e92\u65a5\u9501\u300d\u541e\u5410\u9ad8\u4e00\u4e2a\u91cf\u7ea7&#xff0c;\u540c\u65f6\u9632\u6b62\u4e86\u5728 memmove \u91cd\u6574\u671f\u95f4\u8bfb\u5230\u534a\u4e2a\u5bf9\u8c61\u3002<\/p>\n<h4>7.4 \u61d2\u52a0\u8f7d&#xff1a;loadFromFile \u4e3b\u5e72<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:64<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">loadFromFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">loadMetaInfoAndCheck<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                   <span class=\"token comment\">\/\/ :65 \u8bfb .crc&#xff0c;\u5904\u7406\u7248\u672c\u6b8b\u7559<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_crypter <span class=\"token operator\">&amp;&amp;<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_version <span class=\"token operator\">&gt;&#061;<\/span> MMKVVersionRandomIV<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        m_crypter<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">resetIV<\/span><span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_vector<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_vector<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :69<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">reloadFromFile<\/span><span class=\"token punctuation\">(<\/span>m_expectedCapacity<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>           <span class=\"token comment\">\/\/ :74 \u771f\u6b63 mmap<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_isInterProcess<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> actualFileSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getActualFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>    <span class=\"token comment\">\/\/ :78<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>actualFileSize <span class=\"token operator\">!&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>        <span class=\"token comment\">\/\/ :79 \u522b\u7684\u8fdb\u7a0b\u6269\u8fc7\u5bb9<\/span><br \/>\n            m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">reloadFromFile<\/span><span class=\"token punctuation\">(<\/span>m_expectedCapacity<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;file [%s] not valid&#034;<\/span><span class=\"token punctuation\">,<\/span> m_path<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">bool<\/span> loadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">,<\/span> needFullWriteback <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token function\">checkDataValid<\/span><span class=\"token punctuation\">(<\/span>loadFromFile<span class=\"token punctuation\">,<\/span> needFullWriteback<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>      <span class=\"token comment\">\/\/ :88 \u2605CRC &#043; \u81ea\u6108\u51b3\u7b56<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> ptr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>loadFromFile <span class=\"token operator\">&amp;&amp;<\/span> m_actualSize <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            MMBuffer <span class=\"token function\">inputBuffer<\/span><span class=\"token punctuation\">(<\/span>ptr <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">,<\/span> m_actualSize<span class=\"token punctuation\">,<\/span> MMBufferNoCopy<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :97<\/span><br \/>\n            <span class=\"token function\">clearDictionary<\/span><span class=\"token punctuation\">(<\/span>m_dic<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>needFullWriteback<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token class-name\">MiniPBCoder<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">greedyDecodeMap<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>m_dic<span class=\"token punctuation\">,<\/span> inputBuffer<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>      <span class=\"token comment\">\/\/ :110 \u8d2a\u5fc3\u62a2\u6551<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token class-name\">MiniPBCoder<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">decodeMap<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>m_dic<span class=\"token punctuation\">,<\/span> inputBuffer<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>            <span class=\"token comment\">\/\/ :119 \u6b63\u5e38\u5168\u91cf<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n            m_output <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token function\">CodedOutputData<\/span><span class=\"token punctuation\">(<\/span>ptr <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">,<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            m_output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">seek<\/span><span class=\"token punctuation\">(<\/span>m_actualSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                               <span class=\"token comment\">\/\/ :123 \u2605\u5199\u6307\u9488\u5bf9\u9f50\u5230\u672b\u5c3e<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>needFullWriteback<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">fullWriteback<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                 <span class=\"token comment\">\/\/ :125<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_exclusiveProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            m_output <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token function\">CodedOutputData<\/span><span class=\"token punctuation\">(<\/span>ptr <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">,<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_actualSize <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">,<\/span> IncreaseSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>       <span class=\"token comment\">\/\/ :133 \u5224\u5b9a\u4e0d\u53ef\u4fe1 \u2192 \u4e22\u5f03<\/span><br \/>\n                <span class=\"token function\">sync<\/span><span class=\"token punctuation\">(<\/span>MMKV_SYNC<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">,<\/span> KeepSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    m_needLoadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span>                                          <span class=\"token comment\">\/\/ :143<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u8fd9\u6bb5\u4ee3\u7801\u6d53\u7f29\u4e86 MMKV \u7684\u300c\u542f\u52a8\u5373\u4f53\u68c0\u300d\u6d41\u7a0b&#xff1a;\u8bfb\u8d26\u672c \u2192 \u6620\u5c04\u6587\u4ef6 \u2192 \u6821\u9a8c\u957f\u5ea6\u4e0e CRC \u2192 \u51b3\u5b9a\u300c\u6b63\u5e38\u52a0\u8f7d \/ \u62a2\u6551\u5f0f\u52a0\u8f7d \/ \u6e05\u7a7a\u91cd\u6765\u300d\u2192 \u628a\u5199\u6307\u9488\u6446\u5230\u6709\u6548\u6570\u636e\u672b\u5c3e\u3002<\/p>\n<hr \/>\n<h3>8. \u591a\u8fdb\u7a0b\u4e00\u81f4\u6027\u4e0e\u56db\u5c42\u9501\u6a21\u578b<\/h3>\n<h4>8.1 \u4e00\u81f4\u6027\u534f\u8bae&#xff1a;checkLoadData()<\/h4>\n<p>\u8fd9\u662f MMKV \u591a\u8fdb\u7a0b\u7684 \u5fc3\u810f&#xff0c;\u6bcf\u4e00\u6b21\u8bfb\u3001\u6bcf\u4e00\u6b21\u5199\u4e4b\u524d\u90fd\u4f1a\u6267\u884c&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:305<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">checkLoadData<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_needLoadFromFile<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>                      <span class=\"token comment\">\/\/ \u2460 \u672c\u673a\u9996\u6b21\u4f7f\u7528 \u2192 \u5168\u91cf\u52a0\u8f7d<\/span><br \/>\n        <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_sharedProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        m_needLoadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token function\">loadFromFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_isInterProcess<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span>                                    <span class=\"token comment\">\/\/ \u2461 \u2605\u5355\u8fdb\u7a0b\u76f4\u63a5\u8fd4\u56de&#xff0c;\u96f6\u5f00\u9500<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_metaFile<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_sharedProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>    MMKVMetaInfo metaInfo<span class=\"token punctuation\">;<\/span>                         <span class=\"token comment\">\/\/ \u2462 \u7528\u6808\u4e0a\u7684\u4e34\u65f6\u526f\u672c\u8bfb\u8d26\u672c<\/span><br \/>\n    metaInfo<span class=\"token punctuation\">.<\/span><span class=\"token function\">read<\/span><span class=\"token punctuation\">(<\/span>m_metaFile<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>        <span class=\"token comment\">\/\/ :323<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_sequence <span class=\"token operator\">!&#061;<\/span> metaInfo<span class=\"token punctuation\">.<\/span>m_sequence<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token comment\">\/\/ \u2463 sequence \u53d8\u4e86 &#061; \u522b\u7684\u8fdb\u7a0b\u505a\u8fc7\u300c\u5168\u91cf\u91cd\u6574 \/ clearAll \/ reKey\u300d<\/span><br \/>\n        <span class=\"token function\">MMKVInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;[%s] oldSeq %u, newSeq %u&#034;<\/span><span class=\"token punctuation\">,<\/span> m_mmapID<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_sequence<span class=\"token punctuation\">,<\/span> metaInfo<span class=\"token punctuation\">.<\/span>m_sequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_sharedProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token function\">clearMemoryCache<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token function\">loadFromFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                            <span class=\"token comment\">\/\/ :329 \u53ea\u80fd\u6574\u4f53\u91cd\u8f7d<\/span><br \/>\n        <span class=\"token function\">notifyContentChanged<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_crcDigest <span class=\"token operator\">!&#061;<\/span> metaInfo<span class=\"token punctuation\">.<\/span>m_crcDigest<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token comment\">\/\/ \u2464 crcDigest \u53d8\u4e86 &#061; \u6570\u636e\u533a\u88ab\u8ffd\u52a0\u8fc7<\/span><br \/>\n        <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_sharedProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        size_t fileSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getActualFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">!&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token comment\">\/\/ \u2465 \u6587\u4ef6\u5927\u5c0f\u4e5f\u53d8\u4e86 &#061; \u522b\u7684\u8fdb\u7a0b\u6269\u5bb9\u4e86 \u2192 \u6620\u5c04\u533a\u5df2\u5931\u6548&#xff0c;\u53ea\u80fd\u5168\u91cf\u91cd\u8f7d<\/span><br \/>\n            <span class=\"token function\">MMKVInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;file size has changed [%s] from %zu to %zu&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token function\">clearMemoryCache<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token function\">loadFromFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token function\">partialLoadFromFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                 <span class=\"token comment\">\/\/ :342 \u2605\u589e\u91cf\u540c\u6b65&#xff08;\u6700\u4f18\u8def\u5f84&#xff09;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token function\">notifyContentChanged<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u8fd9\u6bb5\u4ee3\u7801\u56de\u7b54\u4e86\u300c\u5199\u6307\u9488\u540c\u6b65\u300d\u8fd9\u9053\u516b\u80a1\u7684\u771f\u5b9e\u5f62\u6001\u3002 \u6d41\u4f20\u7684\u8bf4\u6cd5\u662f\u300c\u6bcf\u4e2a\u8fdb\u7a0b\u7f13\u5b58\u5199\u6307\u9488&#xff0c;\u5199\u5165\u65f6\u540c\u6b65\u66f4\u65b0 mmap \u5185\u5b58\u4e2d\u7684\u5168\u5c40\u6307\u9488\u300d\u2014\u2014\u4e0d\u5b8c\u5168\u5bf9\u3002\u771f\u5b9e\u673a\u5236\u662f&#xff1a;<\/p>\n<ul>\n<li>\u5199\u6307\u9488\u7684\u300c\u5e7f\u64ad\u4ecb\u8d28\u300d\u4e0d\u662f\u6570\u636e\u6587\u4ef6\u91cc\u7684\u4e00\u4e2a\u5168\u5c40\u53d8\u91cf&#xff0c;\u800c\u662f .crc \u5143\u6587\u4ef6\u91cc\u7684 (m_actualSize, m_crcDigest, m_sequence) \u4e09\u5143\u7ec4&#xff1b;<\/li>\n<li>\u5199\u65b9\u6bcf\u6b21 append \u540e\u901a\u8fc7 updateCRCDigest() \u2192 writeActualSize() \u628a\u65b0\u7684 actualSize\/crcDigest \u843d\u5230 meta \u9875&#xff08;Core\/MMKV.cpp:436\u3001Core\/MMKV_IO.cpp:487&#xff09;&#xff1b;<\/li>\n<li>\u8bfb\u65b9\u4e0d\u9700\u8981\u4efb\u4f55 IPC\/\u901a\u77e5&#xff0c;\u53ea\u8981 memcmp \u81ea\u5df1\u7f13\u5b58\u7684 m_crcDigest \u548c meta \u9875\u91cc\u7684\u503c&#xff08;metaInfo.read() \u5c31\u662f\u4e00\u6b21 memcpy 40 \u5b57\u8282&#xff0c;Core\/MMKVMetaInfo.hpp:88&#xff09;\u3002<\/li>\n<\/ul>\n<p>\u4e09\u79cd\u53d8\u66f4\u7684\u533a\u5206\u903b\u8f91&#xff08;\u8fd9\u662f\u771f\u6b63\u7684\u8bbe\u8ba1\u96be\u70b9&#xff0c;\u4e5f\u662f\u9762\u8bd5\u7684\u52a0\u5206\u70b9&#xff09;&#xff1a;<\/p>\n<table>\n<tr>\u4e8b\u4ef6\u7279\u5f81\u5904\u7406<\/tr>\n<tbody>\n<tr>\n<td>\u522b\u4eba append \u4e86\u65b0\u6570\u636e<\/td>\n<td>sequence \u4e0d\u53d8\u3001crcDigest \u53d8\u3001fileSize \u4e0d\u53d8<\/td>\n<td>partialLoadFromFile() \u589e\u91cf<\/td>\n<\/tr>\n<tr>\n<td>\u522b\u4eba\u505a\u4e86 fullWriteback&#xff08;\u91cd\u6574&#xff09;<\/td>\n<td>sequence \u53d8&#xff08;IncreaseSequence&#xff09;<\/td>\n<td>clearMemoryCache() &#043; loadFromFile()<\/td>\n<\/tr>\n<tr>\n<td>\u522b\u4eba\u6269\u5bb9\u4e86\u6587\u4ef6<\/td>\n<td>crcDigest \u53d8 \u4e14 getFileSize() !&#061; getActualFileSize()<\/td>\n<td>\u5168\u91cf\u91cd\u8f7d&#xff08;\u8001\u6620\u5c04\u533a\u5df2\u8986\u76d6\u4e0d\u4e86\u65b0\u6587\u4ef6&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u4e3a\u4ec0\u4e48\u91cd\u6574\u5fc5\u987b sequence&#043;&#043;&#xff1f;\u56e0\u4e3a\u91cd\u6574\u4e4b\u540e \u6240\u6709 offset \u5168\u53d8\u4e86&#xff0c;\u4f46 crcDigest \u6709\u53ef\u80fd\u6070\u597d\u548c\u65e7\u503c\u76f8\u540c&#xff08;\u6570\u636e\u5185\u5bb9\u4e00\u6837\u53ea\u662f\u4f4d\u7f6e\u53d8\u4e86&#xff09;&#xff0c;\u5355\u9760 digest \u65e0\u6cd5\u611f\u77e5\u3002m_sequence \u5c31\u662f\u4e3a\u6b64\u5b58\u5728\u7684\u300c\u4ee3\u6570&#xff08;generation&#xff09;\u300d\u3002\u6ce8\u91ca\u5199\u5f97\u5f88\u76f4\u767d&#xff1a;uint32_t m_sequence &#061; 0; \/\/ full write-back count&#xff08;Core\/MMKVMetaInfo.hpp:56&#xff09;\u3002<\/p>\n<h4>8.2 \u589e\u91cf\u540c\u6b65&#xff1a;partialLoadFromFile()<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:147<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">partialLoadFromFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    m_metaInfo<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">read<\/span><span class=\"token punctuation\">(<\/span>m_metaFile<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>    size_t oldActualSize <span class=\"token operator\">&#061;<\/span> m_actualSize<span class=\"token punctuation\">;<\/span><br \/>\n    m_actualSize <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">readActualSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                       <span class=\"token comment\">\/\/ :154 \u4ece meta \u62ff\u6743\u5a01\u957f\u5ea6<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> fileSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_actualSize <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_actualSize <span class=\"token operator\">&lt;<\/span> fileSize <span class=\"token operator\">&amp;&amp;<\/span> m_actualSize <span class=\"token operator\">&#043;<\/span> Fixed32Size <span class=\"token operator\">&lt;&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_actualSize <span class=\"token operator\">&gt;<\/span> oldActualSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>            <span class=\"token comment\">\/\/ :161 \u53ea\u5904\u7406\u300c\u589e\u957f\u300d<\/span><br \/>\n                <span class=\"token keyword\">auto<\/span> position <span class=\"token operator\">&#061;<\/span> oldActualSize<span class=\"token punctuation\">;<\/span><br \/>\n                size_t addedSize <span class=\"token operator\">&#061;<\/span> m_actualSize <span class=\"token operator\">&#8211;<\/span> position<span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">auto<\/span> basePtr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token comment\">\/\/ incremental update crc digest<\/span><br \/>\n                m_crcDigest <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token function\">CRC32<\/span><span class=\"token punctuation\">(<\/span>m_crcDigest<span class=\"token punctuation\">,<\/span> basePtr <span class=\"token operator\">&#043;<\/span> position<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span>z_size_t<span class=\"token punctuation\">)<\/span> addedSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :166 \u2605<\/span><br \/>\n                <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_crcDigest <span class=\"token operator\">&#061;&#061;<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_crcDigest<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                    MMBuffer <span class=\"token function\">inputBuffer<\/span><span class=\"token punctuation\">(<\/span>basePtr<span class=\"token punctuation\">,<\/span> m_actualSize<span class=\"token punctuation\">,<\/span> MMBufferNoCopy<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                    <span class=\"token class-name\">MiniPBCoder<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">greedyDecodeMap<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>m_dic<span class=\"token punctuation\">,<\/span> inputBuffer<span class=\"token punctuation\">,<\/span> position<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :175 \u53ea\u89e3 [position, end)<\/span><br \/>\n                    m_output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">seek<\/span><span class=\"token punctuation\">(<\/span>addedSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>             <span class=\"token comment\">\/\/ :177 \u5199\u6307\u9488\u8ddf\u4e0a\u53bb<\/span><br \/>\n                    m_hasFullWriteback <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                    <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                    <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;m_crcDigest[%u] !&#061; m_metaInfo-&gt;m_crcDigest[%u]&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :184<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token comment\">\/\/ something is wrong, do a full load<\/span><br \/>\n    <span class=\"token function\">clearMemoryCache<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">loadFromFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                        <span class=\"token comment\">\/\/ :190 \u2605\u515c\u5e95\u964d\u7ea7<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u589e\u91cf\u540c\u6b65\u7684\u4e09\u6b65\u8d70&#xff1a;<\/p>\n<li>\u589e\u91cf CRC&#xff1a;CRC32(\u65e7digest, \u65b0\u589e\u533a, \u65b0\u589e\u957f\u5ea6) \u2014\u2014 CRC32 \u7684\u6570\u5b66\u6027\u8d28\u5141\u8bb8\u8fd9\u6837\u7eed\u7b97&#xff0c;\u6240\u4ee5\u6821\u9a8c\u6210\u672c\u53ea\u548c \u65b0\u589e\u5b57\u8282\u6570 \u76f8\u5173&#xff0c;\u800c\u4e0d\u662f\u5168\u6587\u4ef6\u3002\u8fd9\u662f MMKV \u591a\u8fdb\u7a0b\u80fd\u9ad8\u9891\u540c\u6b65\u7684\u5173\u952e\u3002<\/li>\n<li>\u589e\u91cf\u89e3\u7801&#xff1a;greedyDecodeMap(dic, buffer, position) \u9760 CodedInputData::seek(position) \u8df3\u8fc7\u65e7\u524d\u7f00&#xff0c;\u53ea\u89e3\u6790\u65b0\u8ffd\u52a0\u7684\u8bb0\u5f55&#xff08;\u89c1 5.6 \u7684 if (position) { m_inputData-&gt;seek(position); }&#xff09;\u3002<\/li>\n<li>\u5199\u6307\u9488\u5bf9\u9f50&#xff1a;m_output-&gt;seek(addedSize)&#xff0c;\u5426\u5219\u672c\u8fdb\u7a0b\u4e0b\u6b21\u5199\u4f1a\u8986\u76d6\u522b\u4eba\u521a\u8ffd\u52a0\u7684\u6570\u636e\u3002\u8fd9\u4e00\u6b65\u5fd8\u4e86\u5c31\u662f\u6570\u636e\u9519\u4e71&#xff0c;\u4e5f\u662f\u5f88\u591a\u81ea\u7814 KV \u5b58\u50a8\u8e29\u8fc7\u7684\u5751\u3002<\/li>\n<p>\u4efb\u4f55\u4e00\u6b65\u4e0d\u6ee1\u8db3&#xff08;\u957f\u5ea6\u4e0d\u5408\u6cd5\u3001CRC \u4e0d\u5339\u914d&#xff09;&#xff0c;\u7acb\u523b\u964d\u7ea7\u4e3a clearMemoryCache() &#043; loadFromFile() \u5168\u91cf\u91cd\u6765\u3002\u300c\u589e\u91cf\u4f18\u5316 &#043; \u5168\u91cf\u515c\u5e95\u300d\u662f MMKV \u6240\u6709\u5feb\u8def\u5f84\u7684\u7edf\u4e00\u8303\u5f0f\u3002<\/p>\n<h4>8.3 \u6587\u4ef6\u9501&#xff1a;flock \u800c\u975e fcntl\/\u4fe1\u53f7\u91cf<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/InterProcessLock.cpp:75<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">int32_t<\/span> <span class=\"token function\">LockType2FlockType<\/span><span class=\"token punctuation\">(<\/span>LockType lockType<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">switch<\/span> <span class=\"token punctuation\">(<\/span>lockType<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">case<\/span> SharedLockType<span class=\"token operator\">:<\/span>    <span class=\"token keyword\">return<\/span> LOCK_SH<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">case<\/span> ExclusiveLockType<span class=\"token operator\">:<\/span> <span class=\"token keyword\">return<\/span> LOCK_EX<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> LOCK_EX<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/InterProcessLock.cpp:85<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">FileLock<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">platformLock<\/span><span class=\"token punctuation\">(<\/span>LockType lockType<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> wait<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> unLockFirstIfNeeded<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> <span class=\"token operator\">*<\/span>tryAgain<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#<\/span><span class=\"token directive keyword\">ifdef<\/span> <span class=\"token expression\">MMKV_ANDROID<\/span><\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_isAshmem<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token function\">ashmemLock<\/span><span class=\"token punctuation\">(<\/span>lockType<span class=\"token punctuation\">,<\/span> wait<span class=\"token punctuation\">,<\/span> unLockFirstIfNeeded<span class=\"token punctuation\">,<\/span> tryAgain<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>   <span class=\"token comment\">\/\/ :87<\/span><br \/>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#<\/span><span class=\"token directive keyword\">endif<\/span><\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> realLockType <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">LockType2FlockType<\/span><span class=\"token punctuation\">(<\/span>lockType<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> cmd <span class=\"token operator\">&#061;<\/span> wait <span class=\"token operator\">?<\/span> realLockType <span class=\"token operator\">:<\/span> <span class=\"token punctuation\">(<\/span>realLockType <span class=\"token operator\">|<\/span> LOCK_NB<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>            <span class=\"token comment\">\/\/ :92 \u975e\u963b\u585e\u52a0 LOCK_NB<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>unLockFirstIfNeeded<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">flock<\/span><span class=\"token punctuation\">(<\/span>m_fd<span class=\"token punctuation\">,<\/span> realLockType <span class=\"token operator\">|<\/span> LOCK_NB<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                   <span class=\"token comment\">\/\/ :95 \u5148\u8bd5\u4e00\u628a<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ret <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token comment\">\/\/ let&#039;s be gentleman: unlock my shared-lock to prevent deadlock<\/span><br \/>\n        ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">flock<\/span><span class=\"token punctuation\">(<\/span>m_fd<span class=\"token punctuation\">,<\/span> LOCK_UN<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                       <span class=\"token comment\">\/\/ :100 \u2605\u4e3b\u52a8\u8ba9\u51fa\u5171\u4eab\u9501<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">auto<\/span> ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">flock<\/span><span class=\"token punctuation\">(<\/span>m_fd<span class=\"token punctuation\">,<\/span> cmd<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                          <span class=\"token comment\">\/\/ :106<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ret <span class=\"token operator\">!&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>tryAgain<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token operator\">*<\/span>tryAgain <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span>errno <span class=\"token operator\">&#061;&#061;<\/span> EWOULDBLOCK<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>             <span class=\"token comment\">\/\/ :109<\/span><br \/>\n        <span class=\"token comment\">\/\/ try recover my shared-lock<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>unLockFirstIfNeeded<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">flock<\/span><span class=\"token punctuation\">(<\/span>m_fd<span class=\"token punctuation\">,<\/span> <span class=\"token function\">LockType2FlockType<\/span><span class=\"token punctuation\">(<\/span>SharedLockType<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>        <span class=\"token comment\">\/\/ :116 \u2605\u5931\u8d25\u518d\u8fd8\u539f<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u4e3a\u4ec0\u4e48\u9009 flock&#xff1f;<\/p>\n<ul>\n<li>flock \u9501\u5728 \u6253\u5f00\u6587\u4ef6\u63cf\u8ff0\u7b26&#xff08;open file description&#xff09; \u4e0a&#xff0c;\u4e0d\u662f fcntl \u90a3\u79cd\u9501\u5728 (\u8fdb\u7a0b, inode) \u4e0a\u3002\u542b\u4e49&#xff1a;\u8fdb\u7a0b\u6b7b\u4ea1\u65f6&#xff0c;\u5185\u6838\u5173\u95ed\u5176\u6240\u6709 fd&#xff0c;\u9501\u81ea\u52a8\u91ca\u653e\u3002MMKV \u56e0\u6b64\u5728\u6ce8\u91ca\u548c\u6587\u6863\u91cc\u6562\u79f0 robust \u2014\u2014 \u4e0d\u4f1a\u56e0\u4e3a\u67d0\u4e2a\u8fdb\u7a0b\u88ab kill -9 \u800c\u7559\u4e0b\u6c38\u4e45\u6b7b\u9501\u3002<\/li>\n<li>fcntl \u8bb0\u5f55\u9501\u5728\u540c\u4e00\u8fdb\u7a0b\u5185\u4e0d\u540c fd \u4e4b\u95f4\u4f1a\u4e92\u76f8\u300c\u610f\u5916\u91ca\u653e\u300d&#xff0c;\u4e14\u4e0e NFS \u8bed\u4e49\u7ea0\u7f20&#xff0c;POSIX \u6709\u540d\u5751\u3002<\/li>\n<li>flock \u5929\u7136\u652f\u6301 LOCK_SH&#xff08;\u591a\u8bfb&#xff09;\/LOCK_EX&#xff08;\u5355\u5199&#xff09;\u8bed\u4e49&#xff0c;\u6b63\u597d\u5339\u914d MMKV \u7684\u8bfb\u5199\u9501\u6a21\u578b\u3002<\/li>\n<\/ul>\n<p>\u552f\u4e00\u7684\u4f8b\u5916\u662f ashmem&#xff1a;Android \u5171\u4eab\u5185\u5b58 fd \u4e0d\u652f\u6301 flock&#xff0c;\u6240\u4ee5\u8d70 fcntl(F_SETLKW\/F_SETLK) \u7684 struct flock \u8bb0\u5f55\u9501&#xff08;Core\/InterProcessLock_Android.cpp:47 \u7684 ashmemLock&#xff09;\u3002\u4e3a\u6b64 Android \u6784\u9020\u51fd\u6570\u8fd8\u8981\u4e13\u95e8\u300c\u5f3a\u5236\u4f7f\u7528 fcntl\u300d\u4ee5\u514d\u548c MemoryFile::reloadFromFile() \u7684 flock \u51b2\u7a81&#xff08;Core\/MMKV_Android.cpp:90-137 \u9644\u8fd1\u6ce8\u91ca&#xff09;\u3002<\/p>\n<h4>8.4 \u53ef\u9012\u5f52 &#043; \u9501\u5347\u7ea7&#xff1a;FileLock \u7684\u300c\u541b\u5b50\u534f\u8bae\u300d<\/h4>\n<p>POSIX flock \u672c\u8eab\u5bf9\u540c\u4e00 fd \u91cd\u590d\u52a0\u9501\u4e0d\u9012\u5f52&#xff08;\u518d\u52a0\u4e00\u628a EX \u4f1a\u81ea\u9501\u6b7b&#xff09;\u3002MMKV \u56e0\u6b64\u5728\u5305\u88c5\u5c42\u505a\u4e86\u5f15\u7528\u8ba1\u6570&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/InterProcessLock.h<\/span><br \/>\n<span class=\"token keyword\">class<\/span> <span class=\"token class-name\">FileLock<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">int<\/span> m_sharedLockCount<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">int<\/span> m_exclusiveLockCount<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>\u89c4\u5219&#xff08;Core\/InterProcessLock.cpp \u7684 doLock&#xff09;&#xff1a;<\/p>\n<ul>\n<li>\u5df2\u6301\u6709 shared&#xff0c;\u518d\u8981 shared \u2192 \u4e0d\u6253\u7834\u5df2\u6709\u9501&#xff0c;\u8ba1\u6570 &#043;&#043;&#xff1b;<\/li>\n<li>\u5df2\u6301\u6709 exclusive&#xff0c;\u518d\u8981 exclusive \u2192 \u8ba1\u6570 &#043;&#043;&#xff08;\u540c\u8fdb\u7a0b\u9012\u5f52&#xff09;&#xff1b;<\/li>\n<li>\u5df2\u6301\u6709 shared&#xff0c;\u5374\u8981 exclusive \u2192 unLockFirstIfNeeded &#061; true&#xff0c;\u5148 LOCK_UN \u8ba9\u51fa\u5171\u4eab\u9501&#xff08;:100 \u201clet\u2019s be gentleman\u201d&#xff09;&#xff0c;\u518d\u8bd5 LOCK_EX | LOCK_NB&#xff1b;\u62ff\u4e0d\u5230\u5c31\u628a\u5171\u4eab\u9501 \u8fd8\u539f&#xff08;:116&#xff09;\u3002<\/li>\n<\/ul>\n<p>unlock \u540c\u7406&#xff1a;\u91ca\u653e\u72ec\u5360\u540e\u5982\u679c m_sharedLockCount &gt; 0&#xff0c;\u4f1a flock(LOCK_SH) \u9000\u56de\u5171\u4eab\u6001&#xff08;Core\/InterProcessLock.cpp:134 \u7684 platformUnLock(bool unlockToSharedLock)&#xff09;\u3002<\/p>\n<p>\u8fd9\u6b63\u662f 4.6 \u4e2d reloadFromFile \u80fd\u505a\u300cshared \u2192 exclusive \u5347\u7ea7\u300d\u7684\u5e95\u5c42\u652f\u6491\u3002<\/p>\n<h4>8.5 \u56db\u5c42\u9501\u5168\u666f<\/h4>\n<table>\n<tr>\u5c42\u6b21\u5bf9\u8c61\u7c92\u5ea6\u4f55\u65f6\u751f\u6548<\/tr>\n<tbody>\n<tr>\n<td>\u2460 \u5168\u5c40\u5b9e\u4f8b\u8868<\/td>\n<td>g_instanceLock&#xff08;Core\/MMKV.cpp:238&#xff09;<\/td>\n<td>SCOPED_LOCK<\/td>\n<td>\u521b\u5efa\/\u67e5\u627e\/\u9500\u6bc1\u5b9e\u4f8b<\/td>\n<\/tr>\n<tr>\n<td>\u2461 \u8fdb\u7a0b\u5185<\/td>\n<td>m_lock&#xff08;ThreadLock&#xff0c;pthread_mutex \u9012\u5f52\u9501&#xff09;<\/td>\n<td>\u6bcf\u4e2a MMKV \u4e00\u628a<\/td>\n<td>\u6240\u6709 set\/get\/trim\/reKey<\/td>\n<\/tr>\n<tr>\n<td>\u2462 \u8de8\u8fdb\u7a0b<\/td>\n<td>m_fileLock &#043; m_sharedProcessLock\/m_exclusiveProcessLock<\/td>\n<td>\u6bcf\u4e2a MMKV \u4e00\u628a&#xff0c;\u52a0\u5728 .crc \u7684 fd \u4e0a<\/td>\n<td>\u4ec5 MULTI_PROCESS_MODE<\/td>\n<\/tr>\n<tr>\n<td>\u2463 \u8fdb\u7a0b\u6a21\u5f0f\u68c0\u67e5<\/td>\n<td>m_fileModeLock&#xff08;Android&#xff0c;\u52a0\u5728 \u6570\u636e\u6587\u4ef6 fd \u4e0a&#xff09;<\/td>\n<td>\u68c0\u6d4b\u7528<\/td>\n<td>\u4ec5 debug \u6784\u5efa<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u3010\u7ea0\u504f\u3011\u2462 \u7684\u9501\u4e3a\u4ec0\u4e48\u52a0\u5728 .crc \u800c\u4e0d\u662f\u6570\u636e\u6587\u4ef6&#xff1f; \u89c1 Core\/MMKV.cpp:93&#xff1a;m_fileLock(new FileLock(m_metaFile-&gt;getFd()))\u3002\u539f\u56e0\u662f\u6570\u636e\u6587\u4ef6\u4f1a\u88ab truncate &#043; munmap\/mmap \u53cd\u590d\u91cd\u5efa\u6620\u5c04&#xff0c;\u800c meta \u6587\u4ef6\u4ece\u5934\u5230\u5c3e\u53ea\u6709\u4e00\u4e2a\u7a33\u5b9a\u7684 fd&#xff1b;\u628a\u9501\u9489\u5728\u300c\u6c38\u4e0d\u91cd\u751f\u7684\u90a3\u4e00\u4e2a fd\u300d\u4e0a&#xff0c;\u9501\u7684\u8bed\u4e49\u624d\u8fde\u7eed\u3002<\/p>\n<p>\u4e5f\u6b63\u56e0\u4e3a\u5982\u6b64&#xff0c;\u7b2c \u2463 \u5c42\u63a2\u6d4b\u9501\u523b\u610f\u7528\u6570\u636e\u6587\u4ef6\u7684 fd&#xff08;Core\/MMKV_Android.cpp \u4e2d m_fileModeLock &#061; new FileLock(m_file-&gt;getFd(), true \/*isAshmem*\/) \u7684\u540c\u7c7b\u8bbe\u8ba1&#xff09;&#xff0c;\u4e24\u628a\u9501\u4e0d\u80fd\u662f\u540c\u4e00\u4e2a fd&#xff0c;\u5426\u5219\u81ea\u76f8\u5e72\u6270\u3002<\/p>\n<h4>8.6 \u8fdb\u7a0b\u6a21\u5f0f\u8bef\u7528\u68c0\u6d4b&#xff08;checkProcessMode&#xff09;<\/h4>\n<p>\u4e00\u4e2a\u975e\u5e38\u73b0\u5b9e\u7684\u7ebf\u4e0a\u95ee\u9898&#xff1a;\u540c\u4e00\u4e2a mmapID&#xff0c;A \u5904\u7528 MULTI_PROCESS_MODE\u3001B \u5904\u7528 SINGLE_PROCESS_MODE \u6253\u5f00&#xff0c;\u6570\u636e\u5c31\u4f1a\u9519\u4e71\u3002MMKV \u7684\u89e3\u6cd5&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_Android.cpp:222<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">checkProcessMode<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_isInterProcess<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_exclusiveProcessModeLock<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            m_exclusiveProcessModeLock <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token function\">InterProcessLock<\/span><span class=\"token punctuation\">(<\/span>m_fileModeLock<span class=\"token punctuation\">,<\/span> ExclusiveLockType<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> tryAgain <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> exclusiveLocked <span class=\"token operator\">&#061;<\/span> m_exclusiveProcessModeLock<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">try_lock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>tryAgain<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :234<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>exclusiveLocked<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                                     <span class=\"token comment\">\/\/ \u80fd\u72ec\u5360 \u2192 \u6ca1\u4eba\u7528<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> shareLocked <span class=\"token operator\">&#061;<\/span> m_sharedProcessModeLock<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">try_lock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                   <span class=\"token comment\">\/\/ :238<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>shareLocked<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> m_exclusiveProcessModeLock<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">try_lock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>tryAgain<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                exclusiveLocked <span class=\"token operator\">&#061;<\/span> m_exclusiveProcessModeLock<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">try_lock<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>tryAgain<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ :246 \u518d\u8bd5\u4e00\u6b21\u6392\u9664 OS \u6296\u52a8<\/span><br \/>\n                <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>exclusiveLocked <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token operator\">!<\/span>tryAgain<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> exclusiveLocked <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>     <span class=\"token comment\">\/\/ \u4ecd\u5f02\u5e38 \u2192 \u653e\u8fc7<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u5224\u5b9a\u903b\u8f91&#xff1a;\u60f3\u72ec\u5360\u5374\u62ff\u4e0d\u5230&#xff0c;\u4f46\u5171\u4eab\u9501\u80fd\u62ff\u5230 \u2192 \u8bf4\u660e \u5df2\u7ecf\u6709\u522b\u4eba\u4ee5 SINGLE_PROCESS_MODE \u6253\u5f00\u4e86\u8fd9\u4e2a\u5b9e\u4f8b&#xff08;\u5355\u8fdb\u7a0b\u5b9e\u4f8b\u4f1a\u6301\u6709\u4e00\u628a shared \u6a21\u5f0f\u9501&#xff09;\u3002\u6b64\u65f6 Java \u5c42 checkProcessMode(handle, mmapID, mode)&#xff08;MMKV.java:601&#xff09;\u629b\u51fa IllegalArgumentException\u3002<\/p>\n<ul>\n<li>\u53ea\u5728 debug \u6784\u5efa \u81ea\u52a8\u5f00\u542f&#xff1a;MMKV.java:199 \u7684 if (isDebugBuild) { enableProcessModeChecker(); }&#xff1b;release \u53ef\u7528 MMKV.enableProcessModeChecker() \u624b\u52a8\u6253\u5f00\u3002<\/li>\n<li>checkedHandleSet&#xff08;MMKV.java:57&#xff09;\u4fdd\u8bc1\u540c\u4e00\u4e2a handle \u53ea\u68c0\u6d4b\u4e00\u6b21&#xff0c;\u907f\u514d\u6027\u80fd\u635f\u8017\u3002<\/li>\n<\/ul>\n<hr \/>\n<h3>9. \u7a7a\u95f4\u7ba1\u7406&#xff1a;\u6269\u5bb9\u3001\u91cd\u6574\u4e0e\u6536\u7f29<\/h3>\n<h4>9.1 \u89e6\u53d1\u70b9&#xff1a;ensureMemorySize<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:402<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">ensureMemorySize<\/span><span class=\"token punctuation\">(<\/span>size_t newSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">MMKVWarning<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;[%s] file not valid&#034;<\/span><span class=\"token punctuation\">,<\/span> m_mmapID<span class=\"token punctuation\">.<\/span><span class=\"token function\">c_str<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>newSize <span class=\"token operator\">&gt;&#061;<\/span> m_output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">spaceLeft<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span>                                  <span class=\"token comment\">\/\/ \u7a7a\u95f4\u4e0d\u591f<\/span><br \/>\n        <span class=\"token operator\">||<\/span> <span class=\"token punctuation\">(<\/span>m_crypter <span class=\"token operator\">?<\/span> m_dicCrypt<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">empty<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">:<\/span> m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">empty<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>          <span class=\"token comment\">\/\/ \u6216\u9996\u6b21\u5199\u5165<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_enableKeyExpire<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">filterExpiredKeys<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                   <span class=\"token comment\">\/\/ :411 \u5148\u6e05\u8fc7\u671f key<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> preparedData <span class=\"token operator\">&#061;<\/span> m_crypter <span class=\"token operator\">?<\/span> <span class=\"token function\">prepareEncode<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>m_dicCrypt<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">:<\/span> <span class=\"token function\">prepareEncode<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>m_dic<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token function\">expandAndWriteBack<\/span><span class=\"token punctuation\">(<\/span>newSize<span class=\"token punctuation\">,<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">move<\/span><span class=\"token punctuation\">(<\/span>preparedData<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                                  m_crypter <span class=\"token operator\">?<\/span> <span class=\"token operator\">!<\/span>m_dicCrypt<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">empty<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">:<\/span> <span class=\"token operator\">!<\/span>m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">empty<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :416<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>prepareEncode&#xff08;Core\/MMKV_IO.cpp:350&#xff09;\u662f\u300c\u53ea\u7b97\u957f\u5ea6&#xff0c;\u4e0d\u505a\u5e8f\u5217\u5316\u300d\u7684\u7ecf\u5178\u4f18\u5316&#xff1a;<\/p>\n<p><span class=\"token keyword\">static<\/span> pair<span class=\"token operator\">&lt;<\/span>MMBuffer<span class=\"token punctuation\">,<\/span> size_t<span class=\"token operator\">&gt;<\/span> <span class=\"token function\">prepareEncode<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> MMKVMap <span class=\"token operator\">&amp;<\/span>dic<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    size_t totalSize <span class=\"token operator\">&#061;<\/span> ItemSizeHolderSize<span class=\"token punctuation\">;<\/span>            <span class=\"token comment\">\/\/ :352 \u7ed9\u5360\u4f4d\u5934\u7559\u51fa\u4f4d\u7f6e<\/span><br \/>\n    <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>itr <span class=\"token operator\">:<\/span> dic<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>kvHolder <span class=\"token operator\">&#061;<\/span> itr<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">;<\/span><br \/>\n        totalSize <span class=\"token operator\">&#043;&#061;<\/span> kvHolder<span class=\"token punctuation\">.<\/span>computedKVSize <span class=\"token operator\">&#043;<\/span> kvHolder<span class=\"token punctuation\">.<\/span>valueSize<span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :355 \u2605holder \u91cc\u5b58\u4e86\u5c3a\u5bf8<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token function\">make_pair<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">MMBuffer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> totalSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>KeyValueHolder.computedKVSize \u5728\u5efa\u7d22\u5f15\u65f6\u5c31\u7b97\u597d\u4e86\u300cvarint(keyLen) &#043; keyLen &#043; varint(valueLen)\u300d&#xff0c;\u6240\u4ee5\u7b97\u603b\u957f \u4e0d\u9700\u8981\u904d\u5386\u771f\u5b9e\u5b57\u8282&#xff0c;\u6574\u4e2a\u91cd\u6574\u7684\u5c3a\u5bf8\u9884\u4f30\u662f\u7eaf O(dic.size()) \u7684\u6574\u6570\u52a0\u6cd5\u3002<\/p>\n<h4>9.2 \u6269\u5bb9\u7b56\u7565&#xff1a;\u7ffb\u500d &#043; \u9884\u7559\u672a\u6765\u7528\u91cf<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:422<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">expandAndWriteBack<\/span><span class=\"token punctuation\">(<\/span>size_t newSize<span class=\"token punctuation\">,<\/span> std<span class=\"token double-colon punctuation\">::<\/span>pair<span class=\"token operator\">&lt;<\/span>mmkv<span class=\"token double-colon punctuation\">::<\/span>MMBuffer<span class=\"token punctuation\">,<\/span> size_t<span class=\"token operator\">&gt;<\/span> preparedData<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> needSync<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> fileSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> sizeOfDic <span class=\"token operator\">&#061;<\/span> preparedData<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">;<\/span><br \/>\n    size_t lenNeeded <span class=\"token operator\">&#061;<\/span> sizeOfDic <span class=\"token operator\">&#043;<\/span> Fixed32Size <span class=\"token operator\">&#043;<\/span> newSize<span class=\"token punctuation\">;<\/span>             <span class=\"token comment\">\/\/ :425<\/span><br \/>\n    size_t nowDicCount <span class=\"token operator\">&#061;<\/span> m_crypter <span class=\"token operator\">?<\/span> m_dicCrypt<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">size<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">:<\/span> m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">size<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    size_t laterDicCount <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token generic-function\"><span class=\"token function\">max<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span> nowDicCount <span class=\"token operator\">&#043;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    size_t avgItemSize <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span>lenNeeded <span class=\"token operator\">&#043;<\/span> laterDicCount <span class=\"token operator\">&#8211;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">\/<\/span> laterDicCount<span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :429 \u5411\u4e0a\u53d6\u6574\u5e73\u5747<\/span><br \/>\n    size_t futureUsage <span class=\"token operator\">&#061;<\/span> avgItemSize <span class=\"token operator\">*<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token generic-function\"><span class=\"token function\">max<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">8<\/span><span class=\"token punctuation\">,<\/span> laterDicCount <span class=\"token operator\">\/<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :430<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>lenNeeded <span class=\"token operator\">&gt;&#061;<\/span> fileSize <span class=\"token operator\">||<\/span> <span class=\"token punctuation\">(<\/span>needSync <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token punctuation\">(<\/span>lenNeeded <span class=\"token operator\">&#043;<\/span> futureUsage<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&gt;&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        size_t oldSize <span class=\"token operator\">&#061;<\/span> fileSize<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">do<\/span> <span class=\"token punctuation\">{<\/span> fileSize <span class=\"token operator\">*&#061;<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">while<\/span> <span class=\"token punctuation\">(<\/span>lenNeeded <span class=\"token operator\">&#043;<\/span> futureUsage <span class=\"token operator\">&gt;&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :435 \u6307\u6570\u6269\u5bb9<\/span><br \/>\n        <span class=\"token function\">MMKVInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;extending [%s] file size from %zu to %zu, incoming size:%zu, future usage:%zu&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ if we can&#039;t extend size, rollback to old state<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">truncate<\/span><span class=\"token punctuation\">(<\/span>fileSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>            <span class=\"token comment\">\/\/ :443 \u2605\u5931\u8d25\u5373\u653e\u5f03&#xff0c;\u4e0d\u52a8\u8001\u6570\u636e<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                        <span class=\"token comment\">\/\/ :448<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token function\">doFullWriteBack<\/span><span class=\"token punctuation\">(<\/span>std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">move<\/span><span class=\"token punctuation\">(<\/span>preparedData<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">,<\/span> needSync<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :453<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u4e24\u5904\u7ec6\u8282\u503c\u5f97\u5728\u9762\u8bd5\u4e2d\u4e3b\u52a8\u70b9\u51fa\u6765&#xff1a;<\/p>\n<li>\u4e0d\u53ea\u662f\u300c\u88c5\u4e0d\u4e0b\u5c31\u7ffb\u500d\u300d&#xff0c;\u8fd8\u4f1a\u989d\u5916\u9884\u7559 futureUsage &#061; avgItemSize * max(8, N\/2)\u3002\u4e5f\u5c31\u662f\u8bf4 MMKV \u4f1a\u9884\u5224\u300c\u672a\u6765\u8fd8\u8981\u5199\u4e00\u534a\u73b0\u6709\u6761\u76ee\u90a3\u4e48\u591a\u6570\u636e\u300d&#xff0c;\u4ece\u800c\u907f\u514d\u521a\u91cd\u6574\u5b8c\u9a6c\u4e0a\u53c8\u6ee1\u3001\u9891\u7e41\u89e6\u53d1\u5168\u91cf\u91cd\u5199\u3002\u8fd9\u662f\u5178\u578b\u7684 \u644a\u8fd8\u5206\u6790&#xff08;amortized&#xff09; \u8bbe\u8ba1\u3002<\/li>\n<li>truncate \u5931\u8d25 \u76f4\u63a5 return false&#xff0c;\u672c\u6b21\u5199\u5165\u6574\u4f53\u5931\u8d25\u5e76\u56de\u6eda \u2014\u2014 \u8001\u6570\u636e\u5b8c\u597d\u3002MemoryFile::truncate \u5185\u90e8\u8fd8\u4f1a\u628a\u6587\u4ef6\u957f\u5ea6 ftruncate \u56de\u539f\u5c3a\u5bf8&#xff08;Core\/MemoryFile.cpp:160&#xff09;\u3002\u300c\u6269\u5bb9\u5931\u8d25\u4e0d\u635f\u574f\u6570\u636e\u300d\u662f\u88ab\u6e90\u7801\u4fdd\u8bc1\u7684&#xff0c;\u4e0d\u662f\u9760\u8fd0\u6c14\u3002<\/li>\n<h4>9.3 \u91cd\u6574\u7684\u7cbe\u9ad3&#xff1a;memmoveDictionary \u2014\u2014 \u4e0d\u91cd\u65b0\u5e8f\u5217\u5316&#xff0c;\u53ea\u642c\u5b57\u8282<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:1102<\/span><br \/>\n<span class=\"token comment\">\/\/ we don&#039;t need to really serialize the dictionary, just reuse what&#039;s already in the file<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token function\">memmoveDictionary<\/span><span class=\"token punctuation\">(<\/span>MMKVMap <span class=\"token operator\">&amp;<\/span>dic<span class=\"token punctuation\">,<\/span> CodedOutputData <span class=\"token operator\">*<\/span>output<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span>ptr<span class=\"token punctuation\">,<\/span><br \/>\n                              AESCrypt <span class=\"token operator\">*<\/span>encrypter<span class=\"token punctuation\">,<\/span> size_t totalSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> originOutputPtr <span class=\"token operator\">&#061;<\/span> output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">curWritePointer<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> writePtr <span class=\"token operator\">&#061;<\/span> originOutputPtr <span class=\"token operator\">&#043;<\/span> ItemSizeHolderSize<span class=\"token punctuation\">;<\/span>          <span class=\"token comment\">\/\/ :1107 \u8df3\u8fc7\u5360\u4f4d\u5934<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>dic<span class=\"token punctuation\">.<\/span><span class=\"token function\">empty<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token comment\">\/\/ sort by offset<\/span><br \/>\n        vector<span class=\"token operator\">&lt;<\/span>KeyValueHolder <span class=\"token operator\">*<\/span><span class=\"token operator\">&gt;<\/span> vec<span class=\"token punctuation\">;<\/span><br \/>\n        vec<span class=\"token punctuation\">.<\/span><span class=\"token function\">reserve<\/span><span class=\"token punctuation\">(<\/span>dic<span class=\"token punctuation\">.<\/span><span class=\"token function\">size<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>itr <span class=\"token operator\">:<\/span> dic<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> vec<span class=\"token punctuation\">.<\/span><span class=\"token function\">push_back<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>itr<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token function\">sort<\/span><span class=\"token punctuation\">(<\/span>vec<span class=\"token punctuation\">.<\/span><span class=\"token function\">begin<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> vec<span class=\"token punctuation\">.<\/span><span class=\"token function\">end<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n             <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>l<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>r<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> l<span class=\"token operator\">-&gt;<\/span>offset <span class=\"token operator\">&lt;<\/span> r<span class=\"token operator\">-&gt;<\/span>offset<span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :1116<\/span><\/p>\n<p>        <span class=\"token comment\">\/\/ merge nearby items to make memmove quicker<\/span><br \/>\n        vector<span class=\"token operator\">&lt;<\/span>pair<span class=\"token operator\">&lt;<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">uint32_t<\/span><span class=\"token operator\">&gt;&gt;<\/span> dataSections<span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ pair(offset, size)<\/span><br \/>\n        dataSections<span class=\"token punctuation\">.<\/span><span class=\"token function\">emplace_back<\/span><span class=\"token punctuation\">(<\/span>vec<span class=\"token punctuation\">.<\/span><span class=\"token function\">front<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token operator\">-&gt;<\/span>offset<span class=\"token punctuation\">,<\/span> vec<span class=\"token punctuation\">.<\/span><span class=\"token function\">front<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token operator\">-&gt;<\/span>computedKVSize <span class=\"token operator\">&#043;<\/span> vec<span class=\"token punctuation\">.<\/span><span class=\"token function\">front<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token operator\">-&gt;<\/span>valueSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span>size_t index <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span> total <span class=\"token operator\">&#061;<\/span> vec<span class=\"token punctuation\">.<\/span><span class=\"token function\">size<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> index <span class=\"token operator\">&lt;<\/span> total<span class=\"token punctuation\">;<\/span> index<span class=\"token operator\">&#043;&#043;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> kvHolder <span class=\"token operator\">&#061;<\/span> vec<span class=\"token punctuation\">[<\/span>index<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>lastSection <span class=\"token operator\">&#061;<\/span> dataSections<span class=\"token punctuation\">.<\/span><span class=\"token function\">back<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>kvHolder<span class=\"token operator\">-&gt;<\/span>offset <span class=\"token operator\">&#061;&#061;<\/span> lastSection<span class=\"token punctuation\">.<\/span>first <span class=\"token operator\">&#043;<\/span> lastSection<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                lastSection<span class=\"token punctuation\">.<\/span>second <span class=\"token operator\">&#043;&#061;<\/span> kvHolder<span class=\"token operator\">-&gt;<\/span>computedKVSize <span class=\"token operator\">&#043;<\/span> kvHolder<span class=\"token operator\">-&gt;<\/span>valueSize<span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :1125 \u76f8\u90bb\u5408\u5e76<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                dataSections<span class=\"token punctuation\">.<\/span><span class=\"token function\">emplace_back<\/span><span class=\"token punctuation\">(<\/span>kvHolder<span class=\"token operator\">-&gt;<\/span>offset<span class=\"token punctuation\">,<\/span> kvHolder<span class=\"token operator\">-&gt;<\/span>computedKVSize <span class=\"token operator\">&#043;<\/span> kvHolder<span class=\"token operator\">-&gt;<\/span>valueSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token comment\">\/\/ do the move<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> basePtr <span class=\"token operator\">&#061;<\/span> ptr <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>section <span class=\"token operator\">:<\/span> dataSections<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token function\">memmove<\/span><span class=\"token punctuation\">(<\/span>writePtr<span class=\"token punctuation\">,<\/span> basePtr <span class=\"token operator\">&#043;<\/span> section<span class=\"token punctuation\">.<\/span>first<span class=\"token punctuation\">,<\/span> section<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :1134 \u2605\u6574\u6bb5\u642c\u8fc1<\/span><br \/>\n            writePtr <span class=\"token operator\">&#043;&#061;<\/span> section<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token comment\">\/\/ update offset<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>encrypter<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> offset <span class=\"token operator\">&#061;<\/span> ItemSizeHolderSize<span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">auto<\/span> kvHolder <span class=\"token operator\">:<\/span> vec<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                kvHolder<span class=\"token operator\">-&gt;<\/span>offset <span class=\"token operator\">&#061;<\/span> offset<span class=\"token punctuation\">;<\/span>                                   <span class=\"token comment\">\/\/ :1141 \u56de\u586b\u65b0 offset<\/span><br \/>\n                offset <span class=\"token operator\">&#043;&#061;<\/span> kvHolder<span class=\"token operator\">-&gt;<\/span>computedKVSize <span class=\"token operator\">&#043;<\/span> kvHolder<span class=\"token operator\">-&gt;<\/span>valueSize<span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">writeUInt32<\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">AESCrypt<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">randomItemSizeHolder<\/span><span class=\"token punctuation\">(<\/span>ItemSizeHolderSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ :1147 \u5199\u968f\u673a\u5360\u4f4d\u5934<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> writtenSize <span class=\"token operator\">&#061;<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>writePtr <span class=\"token operator\">&#8211;<\/span> originOutputPtr<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>encrypter<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> encrypter<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">encrypt<\/span><span class=\"token punctuation\">(<\/span>originOutputPtr<span class=\"token punctuation\">,<\/span> originOutputPtr<span class=\"token punctuation\">,<\/span> writtenSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>  <span class=\"token comment\">\/\/ :1151<\/span><br \/>\n    <span class=\"token function\">assert<\/span><span class=\"token punctuation\">(<\/span>writtenSize <span class=\"token operator\">&#061;&#061;<\/span> totalSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                                      <span class=\"token comment\">\/\/ :1154<\/span><br \/>\n    output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">seek<\/span><span class=\"token punctuation\">(<\/span>writtenSize <span class=\"token operator\">&#8211;<\/span> ItemSizeHolderSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u8fd9\u6bb5\u662f\u5168\u5e93\u6700\u6f02\u4eae\u7684\u4e00\u6bb5\u4ee3\u7801&#xff0c;\u52a1\u5fc5\u7406\u89e3&#xff1a;<\/p>\n<ul>\n<li>\u91cd\u6574 \u4e0d\u8c03\u7528 protobuf \u91cd\u65b0\u7f16\u7801\u3002\u56e0\u4e3a\u6587\u4ef6\u91cc\u6bcf\u6761\u8bb0\u5f55\u672c\u6765\u5c31\u662f\u5b8c\u6574\u3001\u81ea\u6d3d\u7684\u5b57\u8282\u5e8f\u5217&#xff0c;\u53ea\u8981\u6309 offset \u6392\u5e8f\u3001\u628a\u8fd8\u6d3b\u7740\u7684\u8bb0\u5f55 memmove \u5230\u5934\u90e8&#xff0c;\u65e0\u6548\u6570\u636e&#xff08;\u88ab\u8986\u76d6\u7684\u65e7\u503c\u3001\u5893\u7891&#xff09;\u81ea\u7136\u88ab\u8df3\u8fc7\u3002<\/li>\n<li>\u76f8\u90bb\u533a\u95f4\u5408\u5e76&#xff08;:1121-1129&#xff09;&#xff1a;\u628a\u5185\u5b58\u4e2d\u8fde\u7eed\u7684\u591a\u4e2a KV \u5408\u6210\u4e00\u4e2a section&#xff0c;\u4e00\u6b21 memmove \u641e\u5b9a\u3002N \u6761\u8bb0\u5f55\u6700\u574f N \u6b21 move&#xff0c;\u901a\u5e38\u51e0\u6b21\u5c31\u591f\u4e86 \u2014\u2014 \u8fd9\u662f\u4ece O(N) \u6b21\u7cfb\u7edf\u8c03\u7528\u5f0f\u5f00\u9500\u964d\u5230 O(\u6bb5\u6570) \u6b21\u3002<\/li>\n<li>\u6700\u540e assert(writtenSize &#061;&#061; totalSize) \u81ea\u68c0&#xff1a;9.1 \u4e2d prepareEncode \u7684\u7eaf\u7b97\u672f\u9884\u4f30\u5fc5\u987b\u4e0e\u771f\u5b9e\u642c\u8fd0\u7528\u91cf\u5b8c\u5168\u4e00\u81f4\u3002\u8fd9\u662f\u628a\u300c\u4e0d\u5e8f\u5217\u5316\u300d\u4f18\u5316\u95ed\u73af\u9a8c\u8bc1\u7684\u5730\u65b9\u3002<\/li>\n<li>randomItemSizeHolder()&#xff08;\u89c1 11.3&#xff09;\u5199\u4e00\u4e2a\u968f\u673a\u586b\u5145\u5934&#xff0c;\u6df7\u6dc6\u771f\u5b9e\u6570\u636e\u957f\u5ea6\u3002<\/li>\n<\/ul>\n<p>\u52a0\u5bc6\u7248\u672c\u7684 memmoveDictionary&#xff08;Core\/MMKV_IO.cpp:1159&#xff09;\u989d\u5916\u5904\u7406 CFB \u6d41\u72b6\u6001&#xff1a;\u6bcf\u4e2a section \u7528 decrypter-&gt;cloneWithStatus(*get&lt;2&gt;(section)) \u4ece\u8be5 section \u81ea\u5df1\u7684 AESCryptStatus \u6062\u590d\u89e3\u5bc6&#xff0c;\u518d\u987a\u5e8f\u91cd\u52a0\u5bc6\u5e76\u66f4\u65b0\u72b6\u6001&#xff1b;\u82e5 holder \u7c7b\u578b\u4e0d\u662f Offset&#xff08;\u503c\u5185\u8054\u5728\u5b57\u5178\u91cc&#xff09;&#xff0c;\u5219\u5148 MiniPBCoder::encodeDataWithObject() \u628a\u5b83\u771f\u6b63\u843d\u56de\u6587\u4ef6 \u2014\u2014 \u8fd9\u5c31\u662f\u91cd\u6574\u540e offset \u56de\u586b\u88ab\u9650\u5236\u5728 if (!encrypter) \u91cc\u7684\u539f\u56e0\u3002<\/p>\n<h4>9.4 fullWriteback \u4e0e doFullWriteBack<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:1059<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">fullWriteback<\/span><span class=\"token punctuation\">(<\/span>AESCrypt <span class=\"token operator\">*<\/span>newCrypter<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> onlyWhileExpire<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_hasFullWriteback<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>            <span class=\"token comment\">\/\/ :1060 \u2605\u77ed\u8def&#xff1a;\u5df2\u7ecf\u5e72\u51c0\u5c31\u4e0d\u5fc5\u91cd\u6574<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_needLoadFromFile<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>            <span class=\"token comment\">\/\/ :1063<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">mmkv_unlikely<\/span><span class=\"token punctuation\">(<\/span>m_enableKeyExpire<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> expiredCount <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">filterExpiredKeys<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>onlyWhileExpire <span class=\"token operator\">&amp;&amp;<\/span> expiredCount <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>   <span class=\"token comment\">\/\/ :1073<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">auto<\/span> isEmpty <span class=\"token operator\">&#061;<\/span> m_crypter <span class=\"token operator\">?<\/span> m_dicCrypt<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">empty<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">:<\/span> m_dic<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">empty<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>isEmpty<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">clearAll<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>           <span class=\"token comment\">\/\/ :1080 \u7a7a\u8868\u76f4\u63a5\u6e05\u7a7a<\/span><\/p>\n<p>    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_exclusiveProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> preparedData <span class=\"token operator\">&#061;<\/span> m_crypter <span class=\"token operator\">?<\/span> <span class=\"token function\">prepareEncode<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>m_dicCrypt<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">:<\/span> <span class=\"token function\">prepareEncode<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>m_dic<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> sizeOfDic <span class=\"token operator\">&#061;<\/span> preparedData<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>sizeOfDic <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">auto<\/span> fileSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>sizeOfDic <span class=\"token operator\">&#043;<\/span> Fixed32Size <span class=\"token operator\">&lt;&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token function\">doFullWriteBack<\/span><span class=\"token punctuation\">(<\/span>std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">move<\/span><span class=\"token punctuation\">(<\/span>preparedData<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> newCrypter<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :1090<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token function\">assert<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token function\">assert<\/span><span class=\"token punctuation\">(<\/span>newCrypter <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> newSize <span class=\"token operator\">&#061;<\/span> sizeOfDic <span class=\"token operator\">&#043;<\/span> Fixed32Size <span class=\"token operator\">&#8211;<\/span> fileSize<span class=\"token punctuation\">;<\/span>             <span class=\"token comment\">\/\/ :1095<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token function\">expandAndWriteBack<\/span><span class=\"token punctuation\">(<\/span>newSize<span class=\"token punctuation\">,<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">move<\/span><span class=\"token punctuation\">(<\/span>preparedData<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ \u6269\u5bb9\u8def\u5f84\u81ea\u5e26\u5199\u56de<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>doFullWriteBack&#xff08;Core\/MMKV_IO.cpp:1264 \/ :1312&#xff09;\u8d1f\u8d23\u6536\u5c3e&#xff1a;\u91cd\u5efa CodedOutputData \u2192 memmoveDictionary&#xff08;\u6216 fullWriteBackWholeData&#xff09;\u2192 m_actualSize &#061; totalSize \u2192 recalculateCRCDigestWithIV(newIV)&#xff08;\u5185\u90e8 IncreaseSequence&#xff0c;\u89e6\u53d1 sequence&#043;&#043;&#xff09;\u2192 m_hasFullWriteback &#061; true \u2192 sync(MMKV_SYNC)\u3002<\/p>\n<p>\u300c\u4ec0\u4e48\u65f6\u5019\u91cd\u6574\u300d\u7684\u5b8c\u6574\u7b54\u6848&#xff1a;<\/p>\n<ul>\n<li>\u88ab\u52a8&#xff1a;ensureMemorySize \u53d1\u73b0 newSize &gt;&#061; spaceLeft() \u2014\u2014 \u8ffd\u52a0\u524d\u53d1\u73b0\u88c5\u4e0d\u4e0b&#xff1b;<\/li>\n<li>\u4e3b\u52a8&#xff1a;\u4e1a\u52a1\u663e\u5f0f\u8c03\u7528 MMKV.trim() \/ reKey() \/ clearMemoryCache(keepSpace&#061;false) \/ checkDataValid \u5224\u5b9a\u9700\u8981\u62a2\u6551&#xff08;needFullWriteback&#xff09;&#xff1b;<\/li>\n<li>\u4e0d\u4f1a \u6709\u540e\u53f0\u7ebf\u7a0b\u5b9a\u65f6\u91cd\u6574 \u2014\u2014 MMKV \u6ca1\u6709\u4efb\u4f55\u5b9a\u65f6\u5668&#xff0c;\u91cd\u6574\u53ea\u53d1\u751f\u5728\u5199\u8def\u5f84\u4e0a&#xff0c;\u56e0\u6b64 \u4e0d\u4f1a\u5f15\u5165\u968f\u673a\u5ef6\u8fdf\u5c16\u523a\u4ee5\u5916\u7684\u7ebf\u7a0b\u7ade\u4e89&#xff0c;\u53ef\u9884\u6d4b\u6027\u5f3a\u3002<\/li>\n<\/ul>\n<h4>9.5 trim()&#xff1a;\u552f\u4e00\u7684\u7f29\u5bb9\u5165\u53e3<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:1413<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">trim<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_lock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_exclusiveProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">checkLoadData<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_actualSize <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">clearAll<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                       <span class=\"token comment\">\/\/ :1425<\/span><br \/>\n    <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;&#061;<\/span> m_expectedCapacity<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>    <span class=\"token comment\">\/\/ :1427 \u5df2\u7ecf\u8db3\u591f\u5c0f<\/span><\/p>\n<p>    <span class=\"token function\">fullWriteback<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                                     <span class=\"token comment\">\/\/ :1431 \u5148\u91cd\u6574<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> oldSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> fileSize <span class=\"token operator\">&#061;<\/span> oldSize<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">while<\/span> <span class=\"token punctuation\">(<\/span>fileSize <span class=\"token operator\">&gt;<\/span> <span class=\"token punctuation\">(<\/span>m_actualSize <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> fileSize <span class=\"token operator\">\/&#061;<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>   <span class=\"token comment\">\/\/ :1434 \u2605\u4e8c\u5206\u627e\u6700\u5c0f\u53ef\u7528<\/span><br \/>\n    fileSize <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token generic-function\"><span class=\"token function\">max<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>fileSize<span class=\"token punctuation\">,<\/span> m_expectedCapacity<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>oldSize <span class=\"token operator\">&#061;&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">truncate<\/span><span class=\"token punctuation\">(<\/span>fileSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                         <span class=\"token comment\">\/\/ :1445<\/span><br \/>\n    fileSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> ptr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">delete<\/span> m_output<span class=\"token punctuation\">;<\/span><br \/>\n    m_output <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token function\">CodedOutputData<\/span><span class=\"token punctuation\">(<\/span>ptr <span class=\"token operator\">&#043;<\/span> <span class=\"token function\">pbFixed32Size<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> fileSize <span class=\"token operator\">&#8211;<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :1451<\/span><br \/>\n    m_output<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">seek<\/span><span class=\"token punctuation\">(<\/span>m_actualSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h4>\u3010\u7ea0\u504f\u3011\u300cMMKV \u4f1a\u81ea\u52a8\u6536\u7f29\u6587\u4ef6\u3001\u7a7a\u95f4\u81ea\u6108\u300d\u8fd9\u53e5\u8bdd\u8981\u6253\u4e2a\u6298<\/h4>\n<ul>\n<li>\u6269\u5bb9\u662f\u81ea\u52a8\u7684&#xff08;ensureMemorySize \u2192 expandAndWriteBack&#xff09;&#xff1b;<\/li>\n<li>\u91cd\u6574\u662f\u81ea\u52a8\u7684&#xff08;\u540c\u4e0a&#xff0c;doFullWriteBack \u987a\u5e26\u5b8c\u6210&#xff09;&#xff1b;<\/li>\n<li>\u7f29\u5bb9\u53ea\u80fd\u9760\u4e1a\u52a1\u663e\u5f0f\u8c03\u7528 trim()&#xff0c;\u6e90\u7801\u91cc\u6ca1\u6709\u4efb\u4f55\u5730\u65b9\u81ea\u52a8\u8c03 trim()\u3002<\/li>\n<\/ul>\n<p>\u6b63\u786e\u8bf4\u6cd5&#xff1a;\u300cMMKV \u901a\u8fc7\u81ea\u52a8\u91cd\u6574\u628a\u903b\u8f91\u5783\u573e\u56de\u6536\u6389&#xff0c;\u6587\u4ef6\u5927\u5c0f\u5448\u952f\u9f7f\u800c\u975e\u5355\u8c03\u589e\u957f&#xff1b;\u4f46\u8981\u771f\u6b63\u628a\u6587\u4ef6\u7f29\u56de\u53bb&#xff0c;\u9700\u8981\u4e1a\u52a1\u5728\u5408\u9002\u65f6\u673a&#xff08;\u5982\u5207\u540e\u53f0&#xff09;\u8c03 trim()\u3002\u300d<\/p>\n<h4>9.6 \u573a\u666f\u63a8\u6f14&#xff1a;10 \u9875\u7684\u6570\u636e\u5220\u5230\u53ea\u9700 9 \u9875&#xff0c;\u90a3 1 \u9875\u53bb\u54ea\u4e86<\/h4>\n<p>\u8bbe\u9875\u5927\u5c0f DEFAULT_MMAP_SIZE &#061; 4 KB&#xff08;\u8fd0\u884c\u671f\u7531 Core\/MMKV.cpp:165 \u7684 getPageSize() \u8d4b\u503c&#xff0c;Android \u5e38\u89c1 4 KB\u3001Android 15&#043; \/ arm64 \u53ef\u80fd\u662f 16 KB&#xff09;\u3002\u521d\u59cb fileSize &#061; 10 \u00d7 4 KB &#061; 40960&#xff0c;\u5220\u9664\u82e5\u5e72 key \u540e\u6709\u6548\u6570\u636e\u53ea\u9700 9 \u9875\u3002<\/p>\n<p>\u7ed3\u8bba\u5148\u884c&#xff1a;\u90a3 1 \u9875\u65e2\u4e0d\u4f1a\u88ab\u91ca\u653e&#xff0c;\u4e5f\u4e0d\u4f1a\u88ab\u5f52\u8fd8&#xff0c;\u5b83\u4f1a\u53d8\u6210 free space \u88ab\u540e\u7eed append \u539f\u5730\u590d\u7528\u3002\u91cd\u6574\u4e0d\u4f1a\u7f29&#xff0c;\u91cd\u542f\u4e5f\u4e0d\u4f1a\u7f29 \u2014\u2014 \u800c\u4e14\u8fd9\u4e2a\u4f8b\u5b50\u91cc\u8fde trim() \u90fd\u7f29\u4e0d\u52a8\u3002<\/p>\n<h5>\u2460 \u91cd\u6574&#xff08;fullWriteback&#xff09;\u505a\u4e86\u4ec0\u4e48\u3001\u6ca1\u505a\u4ec0\u4e48<\/h5>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:1323-1333  doFullWriteBack<\/span><br \/>\n<span class=\"token keyword\">delete<\/span> m_output<span class=\"token punctuation\">;<\/span><br \/>\nm_output <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token function\">CodedOutputData<\/span><span class=\"token punctuation\">(<\/span>ptr <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">,<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :1324 \u2605\u5bb9\u91cf\u4ecd\u7528 fileSize<\/span><br \/>\n<span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\nm_actualSize <span class=\"token operator\">&#061;<\/span> totalSize<span class=\"token punctuation\">;<\/span>        <span class=\"token comment\">\/\/ :1333 \u2605\u6709\u6548\u6570\u636e\u957f\u5ea6\u7f29\u5230 9 \u9875<\/span><br \/>\n<span class=\"token function\">recalculateCRCDigestWithIV<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\nm_hasFullWriteback <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<ul>\n<li>\u91cd\u6574\u7684\u672c\u8d28\u662f \u628a\u5199\u6307\u9488\u62e8\u56de\u8d77\u70b9 &#043; \u538b\u5b9e\u6709\u6548\u5b57\u8282&#xff1a;m_output \u7684 m_position \u5f52\u96f6&#xff0c;m_actualSize \u4ece\u300c\u63a5\u8fd1 10 \u9875\u300d\u6389\u5230 9 \u9875&#xff1b;<\/li>\n<li>\u4f46 CodedOutputData \u7684\u5bb9\u91cf m_size \u53d6\u7684\u662f m_file-&gt;getFileSize()&#xff0c;\u4ecd\u662f 10 \u9875\u3002\u4e8e\u662f spaceLeft() &#061; m_size &#8211; m_position&#xff08;Core\/CodedOutputData.cpp:97-102&#xff09;\u51ed\u7a7a\u591a\u51fa\u7ea6 1 \u9875&#xff1b;<\/li>\n<li>\u6574\u6761\u91cd\u6574\u94fe\u8def\u91cc\u6ca1\u6709\u4efb\u4f55\u4e00\u5904\u8c03\u7528 truncate() \u6216 munmap()\u3002 \u5168\u4ed3 MMKV \u76ee\u5f55\u91cc grep madvise|MADV_ \u547d\u4e2d\u6570\u4e3a 0 \u2014\u2014 MMKV \u751a\u81f3\u4e0d\u4f1a\u7528 madvise(MADV_DONTNEED) \u628a\u7a7a\u9875\u8fd8\u7ed9\u5185\u6838&#xff1b;<\/li>\n<li>\u6240\u4ee5\u90a3 1 \u9875\u7684\u547d\u8fd0\u662f&#xff1a;\u7559\u5728\u6587\u4ef6\u91cc&#xff0c;\u6210\u4e3a\u5199\u6307\u9488\u524d\u65b9\u5f85\u586b\u5145\u7684\u7a7a\u95f2\u533a&#xff0c;\u4e0b\u6b21 append \u76f4\u63a5 memcpy \u8fdb\u53bb\u7528\u6389&#xff0c;\u4e00\u5206\u94b1\u4e0d\u82b1\u3002\u53ea\u6709\u5f53 spaceLeft() \u4e0d\u591f\u65f6&#xff0c;ensureMemorySize&#xff08;Core\/MMKV_IO.cpp:402-417&#xff09;\u624d\u4f1a\u53bb\u91cd\u6574\u6216\u7ffb\u500d\u6269\u5bb9\u3002<\/li>\n<\/ul>\n<p>\u4e00\u53e5\u8bdd&#xff1a;\u91cd\u6574\u56de\u6536\u7684\u662f\u300c\u903b\u8f91\u5783\u573e\u300d&#xff0c;\u4e0d\u662f\u300c\u7269\u7406\u7a7a\u95f4\u300d\u3002 \u8fd9\u4e5f\u662f totalSize() \u4e0e actualSize() \u4e24\u4e2a API \u5fc5\u987b\u5206\u5f00\u7684\u539f\u56e0 \u2014\u2014 Java \u6ce8\u91ca\u8bf4\u5f97\u5f88\u76f4\u767d&#xff08;Android\/&#8230;\/MMKV.java:1086-1088&#xff09;&#xff1a;\u201ctotalSize() won\u2019t reduce after deleting key-values, call this method (trim()) after lots of deleting if you care about disk usage.\u201d<\/p>\n<h5>\u2461 \u9000\u51fa App \u518d\u91cd\u542f&#xff0c;\u8fd8\u662f 10 \u9875<\/h5>\n<p>\u91cd\u542f\u540e\u8d70\u6784\u9020 \u2192 MemoryFile::reloadFromFile()&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MemoryFile.cpp:226-237<\/span><br \/>\nmmkv<span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span>m_diskFile<span class=\"token punctuation\">.<\/span>m_fd<span class=\"token punctuation\">,<\/span> m_size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>            <span class=\"token comment\">\/\/ :226 \u8bfb\u5230\u771f\u5b9e\u7684 40960<\/span><br \/>\nsize_t expectedSize <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token generic-function\"><span class=\"token function\">max<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>DEFAULT_MMAP_SIZE<span class=\"token punctuation\">,<\/span><br \/>\n                                       <span class=\"token generic-function\"><span class=\"token function\">roundUp<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>expectedCapacity<span class=\"token punctuation\">,<\/span> DEFAULT_MMAP_SIZE<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_size <span class=\"token operator\">&lt;<\/span> expectedSize <span class=\"token operator\">||<\/span> <span class=\"token punctuation\">(<\/span>m_size <span class=\"token operator\">%<\/span> DEFAULT_MMAP_SIZE <span class=\"token operator\">!&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>   <span class=\"token comment\">\/\/ :229<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token function\">truncate<\/span><span class=\"token punctuation\">(<\/span>roundSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                          <span class=\"token comment\">\/\/ \u53ea\u6709\u8fd9\u91cc\u624d\u4f1a\u6539\u5927\u5c0f<\/span><br \/>\n<span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">mmap<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                                <span class=\"token comment\">\/\/ :237 \u2605\u539f\u6837\u6620\u5c04 10 \u9875<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>40960 &lt; 4096&#xff1f;\u5426\u300240960 % 4096 !&#061; 0&#xff1f;\u5426\u3002\u4e24\u4e2a\u6761\u4ef6\u90fd\u4e0d\u6210\u7acb \u2192 \u4e0d\u8fdb truncate \u5206\u652f&#xff0c;\u76f4\u63a5 mmap() \u6574\u4e2a 10 \u9875\u3002 \u968f\u540e loadFromFile() \u53ea\u6309 .crc \u91cc\u7684 m_actualSize&#xff08;9 \u9875&#xff09;\u89e3\u7801&#xff0c;\u7b2c 10 \u9875\u7ee7\u7eed\u5f53\u7a7a\u95f2\u533a\u3002<\/p>\n<p>\u987a\u5e26\u4e00\u4e2a\u771f\u5b9e\u8fb9\u754c&#xff1a;\u5982\u679c\u540c\u4e00\u4efd\u6587\u4ef6\u88ab\u642c\u5230 16 KB \u9875 \u7684\u8bbe\u5907\u4e0a&#xff0c;40960 % 16384 !&#061; 0 \u6210\u7acb \u2192 \u8fdb truncate \u5206\u652f&#xff0c;roundSize &#061; (40960\/16384 &#043; 1) \u00d7 16384 &#061; 49152 \u2014\u2014 \u6587\u4ef6\u88ab\u6491\u5927\u5230 48 KB\u3002\u8fd9\u6761\u8def\u5f84\u53ea\u4f1a\u957f\u4e0d\u4f1a\u77ed&#xff0c;\u662f Android 15&#043; 16 KB page size \u9002\u914d\u4e0b\u4f1a\u9047\u5230\u7684\u73b0\u8c61\u3002<\/p>\n<h5>\u2462 \u66f4\u53cd\u76f4\u89c9\u7684\u4e00\u70b9&#xff1a;\u8fd9\u4e2a\u573a\u666f\u91cc trim() \u4e5f\u4e0d\u4f1a\u7f29<\/h5>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:1431-1441<\/span><br \/>\n<span class=\"token function\">fullWriteback<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                                        <span class=\"token comment\">\/\/ :1431<\/span><br \/>\n<span class=\"token keyword\">auto<\/span> oldSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                   <span class=\"token comment\">\/\/ 40960<\/span><br \/>\n<span class=\"token keyword\">auto<\/span> fileSize <span class=\"token operator\">&#061;<\/span> oldSize<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">while<\/span> <span class=\"token punctuation\">(<\/span>fileSize <span class=\"token operator\">&gt;<\/span> <span class=\"token punctuation\">(<\/span>m_actualSize <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> fileSize <span class=\"token operator\">\/&#061;<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>  <span class=\"token comment\">\/\/ :1434<\/span><br \/>\nfileSize <span class=\"token operator\">&#061;<\/span> std<span class=\"token double-colon punctuation\">::<\/span><span class=\"token generic-function\"><span class=\"token function\">max<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span>size_t<span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>fileSize<span class=\"token punctuation\">,<\/span> m_expectedCapacity<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>oldSize <span class=\"token operator\">&#061;&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">MMKVInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;there&#039;s no need to trim &#8230;&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>   <span class=\"token comment\">\/\/ :1438<\/span><\/p>\n<p>\u7f29\u5bb9\u5224\u636e\u662f \u300c\u6587\u4ef6\u5927\u5c0f\u8981\u8d85\u8fc7\u6709\u6548\u6570\u636e\u7684 2 \u500d\u300d&#xff1a;40960 &gt; (36864 &#043; 4) \u00d7 2 &#061; 73736&#xff1f;\u4e0d\u6210\u7acb \u2192 while \u4e00\u6b21\u90fd\u4e0d\u8fdb \u2192 fileSize &#061;&#061; oldSize \u2192 \u5728 :1438 \u76f4\u63a5 return&#xff0c;\u4e00\u9875\u90fd\u7701\u4e0d\u4e0b\u6765\u3002<\/p>\n<p>\u4ee3\u5165\u51e0\u4e2a\u5177\u4f53\u503c&#xff08;4 KB \u9875&#xff09;&#xff1a;<\/p>\n<table>\n<tr>m_actualSize\u9996\u51cf\u534a\u6761\u4ef6 a &lt; fileSize\/2 &#8211; 4trim() \u7ed3\u679c<\/tr>\n<tbody>\n<tr>\n<td>9 \u9875 &#061; 36864<\/td>\n<td>\u9700 &lt; 20476 \u2192 \u5426<\/td>\n<td>\u4e0d\u7f29&#xff0c;40960 \u539f\u6837<\/td>\n<\/tr>\n<tr>\n<td>5 \u9875 &#061; 20480<\/td>\n<td>\u9700 &lt; 20476 \u2192 \u5dee 4 \u5b57\u8282&#xff0c;\u5426<\/td>\n<td>\u4e0d\u7f29<\/td>\n<\/tr>\n<tr>\n<td>4 \u9875 &#061; 16384<\/td>\n<td>\u6210\u7acb<\/td>\n<td>40960 \u2192 20480&#xff08;5 \u9875&#xff09;&#xff0c;\u518d\u5224 20480 &gt; 32776? \u5426&#xff0c;\u505c<\/td>\n<\/tr>\n<tr>\n<td>1 \u9875 &#061; 4096<\/td>\n<td>\u8fde\u534a\u4e09\u6b21&#xff1a;40960\u219220480\u219210240\u21925120&#xff0c;5120 &gt; 8200? \u5426 \u2192 \u505c<\/td>\n<td>\u7f29\u5230 5120&#xff08;\u4ecd\u7559 1 \u9875\u4f59\u91cf&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u22480.5 \u9875 &#061; 2048<\/td>\n<td>40960\u219220480\u219210240\u21925120\u21922560&#xff0c;max(2560, 4096)<\/td>\n<td>\u7f29\u5230 4096&#xff08;\u88ab m_expectedCapacity \u515c\u4f4f&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>trim() \u7684\u6536\u655b\u70b9\u662f&#xff1a;\u6700\u7ec8 fileSize \u2208 (a&#043;4, (a&#043;4)\u00d72]&#xff0c;\u518d\u4e0e m_expectedCapacity \u53d6\u5927\u3002\u4e5f\u5c31\u662f\u8bf4 MMKV \u7684\u7f29\u5bb9\u7b56\u7565\u5929\u751f\u4fdd\u5b88 \u2014\u2014 \u5b81\u53ef\u7559\u4e00\u500d\u7684\u4f59\u91cf\u907f\u514d\u9891\u7e41\u6269\u5bb9&#xff0c;\u4e5f\u4e0d\u4f1a\u8d34\u7740\u6570\u636e\u957f\u5ea6\u5207\u3002\u60f3\u4e00\u6b65\u780d\u5230\u6700\u5c0f&#xff0c;\u53ea\u6709 clearAll()&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:1468-1491  clearAll(keepSpace &#061; false)<\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>keepSpace<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">truncate<\/span><span class=\"token punctuation\">(<\/span>m_expectedCapacity<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>   <span class=\"token comment\">\/\/ :1473-1474 \u76f4\u63a5\u56de\u5230\u521d\u59cb\u9875\u5927\u5c0f<\/span><br \/>\n<span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> newIV<span class=\"token punctuation\">,<\/span> IncreaseSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>             <span class=\"token comment\">\/\/ :1483 sequence&#043;&#043;&#xff0c;\u5176\u4ed6\u8fdb\u7a0b\u636e\u6b64\u5168\u91cf\u91cd\u8f7d<\/span><br \/>\n<span class=\"token function\">clearMemoryCache<\/span><span class=\"token punctuation\">(<\/span>keepSpace<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                <span class=\"token comment\">\/\/ :1490 \u2192 m_file-&gt;clearMemoryCache() \u2192 munmap &#043; close<\/span><br \/>\n<span class=\"token function\">loadFromFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                             <span class=\"token comment\">\/\/ :1491 \u91cd\u65b0\u6620\u5c04<\/span><\/p>\n<p>clearAllWithKeepingSpace()&#xff08;Java \u4fa7 Android\/&#8230;\/MMKV.java:1083&#xff09;\u8d70 keepSpace &#061; true&#xff1a;\u4e0d truncate\u3001\u4e0d munmap&#xff08;Core\/MMKV.cpp:326-328 \u7684 if (!keepSpace) \u5206\u652f\u8df3\u8fc7 m_file-&gt;clearMemoryCache()&#xff09;&#xff0c;\u4fdd\u7559 10 \u9875\u539f\u5730\u590d\u7528&#xff0c;\u6ce8\u91ca\u91cc\u660e\u8bf4\u8fd9\u662f \u201cfaster implementation\u201d&#xff08;MMKV.java:1080-1082&#xff09;\u3002<\/p>\n<h5>\u2463 \u90a3 1 \u9875\u5230\u5e95\u5728\u6d88\u8017\u4ec0\u4e48\u8d44\u6e90<\/h5>\n<table>\n<tr>\u8d44\u6e90\u662f\u5426\u88ab\u90a3 1 \u9875\u5360\u7528\u6e90\u7801\/OS \u4f9d\u636e<\/tr>\n<tbody>\n<tr>\n<td>\u78c1\u76d8<\/td>\n<td>\u5360&#xff0c;\u800c\u4e14\u662f\u771f\u5b9e\u5757\u5360\u7528<\/td>\n<td>expandAndWriteBack \u2192 MemoryFile::truncate \u4f1a\u8c03 zeroFillFile()&#xff08;Core\/MemoryFile.cpp:155\u3001:349-374&#xff09;&#xff0c;\u7528 write(fd, zeros, 4096) \u771f\u5199\u4e86 0&#xff0c;\u4e0d\u662f\u6587\u4ef6\u7a7a\u6d1e&#xff08;sparse hole&#xff09;&#xff0c;\u4e5f\u6ca1\u7528 FALLOC_FL_PUNCH_HOLE\u3002\u6240\u4ee5 ls -l \/ du \u90fd\u662f 10 \u9875<\/td>\n<\/tr>\n<tr>\n<td>\u865a\u62df\u5730\u5740\u7a7a\u95f4<\/td>\n<td>\u5360 1 \u9875 VMA&#xff0c;\u91cf\u7ea7\u53ef\u5ffd\u7565<\/td>\n<td>mmap() \u4e00\u6b21\u6027\u6620\u5c04\u6574\u4e2a fileSize&#xff08;Core\/MemoryFile.cpp:197&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u7269\u7406\u5185\u5b58 \/ RSS<\/td>\n<td>\u5f71\u54cd\u6781\u5c0f<\/td>\n<td>MAP_SHARED \u6620\u5c04\u7684\u662f page cache&#xff08;\u975e\u533f\u540d\u9875&#xff09;\u3002\u7a7a\u95f2\u9875\u82e5\u672a\u88ab\u5f04\u810f&#xff0c;\u5185\u5b58\u7d27\u5f20\u65f6\u5185\u6838\u53ef\u76f4\u63a5\u56de\u6536&#xff0c;\u65e0\u9700\u56de\u5199&#xff1b;MMKV \u4e5f\u4e0d\u4e3b\u52a8 madvise \u63d0\u524d\u91ca\u653e \u2014\u2014 \u5168\u4ed3 0 \u547d\u4e2d<\/td>\n<\/tr>\n<tr>\n<td>\u5199\u653e\u5927<\/td>\n<td>\u4e0d\u5360<\/td>\n<td>\u7a7a\u95f2\u533a\u5728\u5199\u6307\u9488\u524d\u65b9&#xff0c;append \u76f4\u63a5\u63a8\u8fdb&#xff0c;\u91cd\u6574\u540e\u5934\u4e00\u4e2a\u5199\u5b83\u7684\u8fdb\u7a0b\u4e0d\u9700\u8981\u4efb\u4f55\u9884\u5904\u7406<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u6240\u4ee5\u300cMMKV mmap \u4f1a\u4e0d\u4f1a\u5403\u5185\u5b58\u300d\u7684\u6b63\u89e3\u662f&#xff1a;\u5e38\u9a7b\u7684\u533f\u540d\u5185\u5b58\u53ea\u6709 m_dic&#xff08;key \u2192 12B holder \u7684 unordered_map&#xff09;\u52a0\u89e3\u5bc6\u6a21\u5f0f\u4e0b\u7684\u660e\u6587\u503c&#xff1b;\u6620\u5c04\u533a\u672c\u8eab\u662f\u6587\u4ef6\u9875\u7f13\u5b58&#xff0c;\u7b97 PSS \u4f46\u4e0d\u7b97\u4e0d\u53ef\u56de\u6536\u5185\u5b58&#xff0c;\u800c\u4e14 mmap \u957f\u5ea6\u662f 10 \u9875 \u2260 \u7528\u6389 10 \u9875 RAM\u3002<\/p>\n<h5>\u2464 \u5de5\u7a0b\u5efa\u8bae&#xff08;\u7167\u6e90\u7801\u6765&#xff0c;\u522b\u7167\u611f\u89c9\u6765&#xff09;<\/h5>\n<ul>\n<li>\u5927\u91cf\u5220\u9664\u540e\u4e0d\u8981\u6307\u671b\u81ea\u52a8\u56de\u6536\u7a7a\u95f4&#xff1a;grep -n &#034;trim()&#034; Core \u53ea\u80fd\u627e\u5230\u5b9a\u4e49&#xff0c;\u8fd0\u884c\u671f\u65e0\u4eba\u8c03\u7528&#xff1b;<\/li>\n<li>\u60f3\u56de\u6536 \u2192 \u5728\u5207\u540e\u53f0 \/ \u51b7\u542f\u52a8\u7a7a\u95f2\u65f6\u8c03 trim()&#xff0c;\u5e76\u4e14\u5fc3\u91cc\u6e05\u695a\u5b83\u9700\u8981 actualSize &lt; fileSize \/ 2 \u624d\u751f\u6548&#xff0c;\u7f29\u5b8c\u8fd8\u7559\u4e00\u500d\u4f59\u91cf&#xff1b;<\/li>\n<li>\u6570\u636e\u53ef\u6574\u4f53\u4f5c\u5e9f \u2192 \u7528 clearAll()&#xff08;\u4f1a truncate \u56de\u521d\u59cb\u9875 &#043; munmap \u91cd\u6620\u5c04&#xff0c;\u6709 IO \u6296\u52a8&#xff09;\u800c\u4e0d\u662f\u9010\u6761 removeValueForKey&#xff1b;<\/li>\n<li>\u9884\u77e5\u5bb9\u91cf \u2192 \u7528 mmkvWithID(&#8230;, expectedCapacity)&#xff08;Core\/MMKV.cpp:87 \u7684 m_expectedCapacity&#xff09;\u4e00\u6b21\u7533\u8bf7\u5230\u4f4d&#xff0c;\u907f\u5f00\u53cd\u590d\u7ffb\u500d&#xff1b;\u5b83\u662f trim() \u7684\u4e0b\u9650&#xff08;:1437&#xff09;&#xff0c;\u4e0d\u4f1a\u88ab\u7f29\u6ca1&#xff1b;<\/li>\n<li>\u76d1\u63a7 \u2192 \u770b totalSize() \u800c\u4e0d\u662f actualSize()&#xff0c;\u53ea\u6709\u524d\u8005\u53cd\u6620\u771f\u5b9e\u78c1\u76d8\u5360\u7528\u3002<\/li>\n<\/ul>\n<p>\u4e00\u53e5\u8bdd\u9762\u8bd5\u7248&#xff1a;\u5220\u6570\u636e\u5728 MMKV \u91cc\u53ea\u662f\u300c\u8ffd\u52a0\u4e86\u4e00\u6761 valueSize &#061;&#061; 0 \u7684\u5893\u7891\u300d&#xff0c;\u7a7a\u95f4\u56de\u6536\u9760\u91cd\u6574&#xff0c;\u800c\u91cd\u6574\u53ea\u628a\u5199\u6307\u9488\u62e8\u56de\u8d77\u70b9\u3001\u4e0d\u6539\u6587\u4ef6\u5927\u5c0f&#xff1b;\u7a7a\u51fa\u6765\u7684\u9875\u53d8\u6210 free space \u88ab\u540e\u7eed\u5199\u590d\u7528&#xff0c;\u91cd\u542f\u540e\u7167\u6837\u6620\u5c04\u90a3\u4e48\u591a\u9875\u3002\u8981\u771f\u7f29\u6587\u4ef6\u53ea\u80fd\u624b\u52a8 trim()&#xff0c;\u4e14\u5b83\u7684\u5224\u636e\u662f\u300c\u6709\u6548\u6570\u636e\u4e0d\u8db3\u6587\u4ef6\u4e00\u534a\u300d&#xff0c;\u5929\u751f\u4fdd\u5b88 \u2014\u2014 \u8fd9\u662f totalSize() \u548c actualSize() \u5206\u6210\u4e24\u4e2a API \u7684\u6839\u672c\u539f\u56e0\u3002 &#xff08;\u5893\u7891\u7684\u4ee3\u7801\u6b63\u8eab&#xff1a;Core\/MMKV_IO.cpp:749-760&#xff0c;static MMBuffer nan; &#043; appendDataWithKey(nan, key, &#8230;)&#xff0c;\u540c\u65f6\u7f6e m_hasFullWriteback &#061; false\u3002&#xff09;<\/p>\n<hr \/>\n<h3>10. \u6570\u636e\u5b89\u5168&#xff1a;CRC \u6821\u9a8c\u4e0e\u81ea\u52a8\u81ea\u6108<\/h3>\n<h4>10.1 \u56db\u4e2a CRC \u52a9\u624b\u51fd\u6570<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:405  \u5168\u91cf\u6821\u9a8c&#xff08;\u52a0\u8f7d\u65f6\u7528&#xff09;<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">checkFileCRCValid<\/span><span class=\"token punctuation\">(<\/span>size_t actualSize<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">uint32_t<\/span> crcDigest<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> ptr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ptr<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        m_crcDigest <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token function\">CRC32<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> ptr <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">)<\/span> actualSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_crcDigest <span class=\"token operator\">&#061;&#061;<\/span> crcDigest<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;check crc [%s] fail, crc32:%u, m_crcDigest:%u&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:418  \u91cd\u6574\u540e&#xff1a;\u5168\u91cf\u91cd\u7b97 &#043; sequence&#043;&#043;<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">recalculateCRCDigestWithIV<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>iv<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    m_crcDigest <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    m_crcDigest <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token function\">CRC32<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> ptr <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">)<\/span> m_actualSize<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span>m_actualSize<span class=\"token punctuation\">,<\/span> m_crcDigest<span class=\"token punctuation\">,<\/span> iv<span class=\"token punctuation\">,<\/span> IncreaseSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :423<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:427  \u539f\u5730\u8986\u76d6\u540e&#xff1a;\u5168\u91cf\u91cd\u7b97&#xff0c;\u4f46 sequence \u4e0d\u53d8<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">recalculateCRCDigestOnly<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span>m_actualSize<span class=\"token punctuation\">,<\/span> m_crcDigest<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">,<\/span> KeepSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :432<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:436  \u2605\u70ed\u8def\u5f84&#xff1a;\u589e\u91cf\u7eed\u7b97<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">updateCRCDigest<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span>ptr<span class=\"token punctuation\">,<\/span> size_t length<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ptr <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    m_crcDigest <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token function\">CRC32<\/span><span class=\"token punctuation\">(<\/span>m_crcDigest<span class=\"token punctuation\">,<\/span> ptr<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">)<\/span> length<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :440<\/span><br \/>\n    <span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span>m_actualSize<span class=\"token punctuation\">,<\/span> m_crcDigest<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">,<\/span> KeepSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>     <span class=\"token comment\">\/\/ :442<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u6ce8\u610f updateCRCDigest \u91cc CRC32(m_crcDigest, ptr, length) \u7684\u7b2c\u4e00\u4e2a\u53c2\u6570&#xff1a;CRC32 \u662f\u6eda\u52a8\u54c8\u5e0c&#xff0c;\u628a\u4e0a\u4e00\u6b21\u7684\u8f93\u51fa\u4f5c\u4e3a\u79cd\u5b50\u7ee7\u7eed\u7b97&#xff0c;\u7ed3\u679c\u7b49\u4ef7\u4e8e\u4ece\u5934\u7b97\u6574\u4e2a\u524d\u7f00\u3002\u6240\u4ee5 \u70ed\u8def\u5f84\u7684 CRC \u6210\u672c\u53ea\u4e0e\u672c\u6b21\u65b0\u589e\u5b57\u8282\u6570\u6210\u6b63\u6bd4&#xff0c;\u800c\u4e0d\u662f O(\u6587\u4ef6\u5927\u5c0f)\u3002\u8fd9\u662f\u300c\u6709\u6821\u9a8c\u4f46\u4e0d\u6389\u6027\u80fd\u300d\u7684\u6839\u56e0\u3002<\/p>\n<p>\u53e6\u4e00\u4e2a\u7ec6\u8282&#xff1a;updateCRCDigest \u7528\u7684\u662f KeepSequence&#xff0c;\u5373 \u666e\u901a append \u4e0d\u63a8\u8fdb sequence&#xff1b;\u53ea\u6709\u91cd\u6574\u3001clearAll\u3001reKey \u8fd9\u7c7b\u300coffset \u5168\u53d8\u300d\u7684\u64cd\u4f5c\u624d IncreaseSequence\u3002\u8bed\u4e49\u4e0e 8.1 \u7684\u4e09\u79cd\u72b6\u6001\u4e25\u683c\u5bf9\u5e94\u3002<\/p>\n<h4>10.2 writeActualSize&#xff1a;\u8d26\u672c\u7684\u843d\u7b14\u5904<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:487<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span>size_t size<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">uint32_t<\/span> crcDigest<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>iv<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> increaseSequence<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">oldStyleWriteActualSize<\/span><span class=\"token punctuation\">(<\/span>size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                  <span class=\"token comment\">\/\/ :489 \u2605\u5148\u5199\u6570\u636e\u6587\u4ef6\u5934 4 \u5b57\u8282&#xff08;\u964d\u7ea7\u517c\u5bb9&#xff09;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>m_metaFile<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">bool<\/span> needsFullWrite <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    m_actualSize <span class=\"token operator\">&#061;<\/span> size<span class=\"token punctuation\">;<\/span><br \/>\n    m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_actualSize <span class=\"token operator\">&#061;<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    m_crcDigest <span class=\"token operator\">&#061;<\/span> crcDigest<span class=\"token punctuation\">;<\/span><br \/>\n    m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_crcDigest <span class=\"token operator\">&#061;<\/span> crcDigest<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_version <span class=\"token operator\">&lt;<\/span> MMKVVersionSequence<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_version <span class=\"token operator\">&#061;<\/span> MMKVVersionSequence<span class=\"token punctuation\">;<\/span> needsFullWrite <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">mmkv_unlikely<\/span><span class=\"token punctuation\">(<\/span>iv<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>                        <span class=\"token comment\">\/\/ :505 \u6709\u65b0\u7684\u968f\u673a IV<\/span><br \/>\n        <span class=\"token function\">memcpy<\/span><span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_vector<span class=\"token punctuation\">,<\/span> iv<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_vector<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_version <span class=\"token operator\">&lt;<\/span> MMKVVersionRandomIV<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_version <span class=\"token operator\">&#061;<\/span> MMKVVersionRandomIV<span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        needsFullWrite <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">mmkv_unlikely<\/span><span class=\"token punctuation\">(<\/span>increaseSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>          <span class=\"token comment\">\/\/ :513<\/span><br \/>\n        m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_sequence<span class=\"token operator\">&#043;&#043;<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_lastConfirmedMetaInfo<span class=\"token punctuation\">.<\/span>lastActualSize <span class=\"token operator\">&#061;<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span>size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :515<\/span><br \/>\n        m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_lastConfirmedMetaInfo<span class=\"token punctuation\">.<\/span>lastCRCDigest <span class=\"token operator\">&#061;<\/span> crcDigest<span class=\"token punctuation\">;<\/span>                      <span class=\"token comment\">\/\/ :516<\/span><br \/>\n        <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n        needsFullWrite <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">mmkv_unlikely<\/span><span class=\"token punctuation\">(<\/span>needsFullWrite<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        m_metaInfo<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">write<\/span><span class=\"token punctuation\">(<\/span>m_metaFile<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                        <span class=\"token comment\">\/\/ :536 \u6574\u9875\u5199<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        m_metaInfo<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">writeCRCAndActualSizeOnly<\/span><span class=\"token punctuation\">(<\/span>m_metaFile<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>     <span class=\"token comment\">\/\/ :538 \u2605\u53ea\u6539 8 \u5b57\u8282<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u70ed\u8def\u5f84\u7684\u8d26\u672c\u5199\u5165\u53ea\u6709 8 \u5b57\u8282&#xff08;m_crcDigest &#043; m_actualSize&#xff09;&#xff0c;\u5e76\u4e14 m_lastConfirmedMetaInfo \u53ea\u5728 increaseSequence \u65f6\u624d\u66f4\u65b0 \u2014\u2014 \u542b\u4e49\u662f&#xff1a;\u300c\u4e0a\u4e00\u4e2a\u5df2\u88ab\u786e\u8ba4\u7684\u5b8c\u6574\u72b6\u6001\u300d\u662f\u4e0a\u4e00\u6b21\u91cd\u6574\/\u6e05\u7a7a\u540e\u7684\u5feb\u7167&#xff0c;\u800c\u4e0d\u662f\u6bcf\u4e00\u6b21 append\u3002\u56e0\u6b64\u5d29\u6e83\u65f6\u6700\u591a\u56de\u9000\u5230\u4e0a\u4e00\u6b21\u91cd\u6574&#xff0c;\u4e2d\u95f4\u5df2 append \u7684\u6570\u636e\u4ecd\u7136\u5728\u6587\u4ef6\u91cc\u3001\u5e76\u4e14\u4f1a\u88ab\u7b2c 10.3 \u8282\u7684 CRC \u7cbe\u786e\u5b9a\u4f4d\u5230\u635f\u574f\u70b9\u3002<\/p>\n<h4>10.3 checkDataValid&#xff1a;\u4e09\u7ea7\u81ea\u6108<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:230<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">checkDataValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">bool<\/span> <span class=\"token operator\">&amp;<\/span>loadFromFile<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">bool<\/span> <span class=\"token operator\">&amp;<\/span>needFullWriteback<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> fileSize <span class=\"token operator\">&#061;<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getFileSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> checkLastConfirmedInfo <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token operator\">&amp;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_version <span class=\"token operator\">&gt;&#061;<\/span> MMKVVersionActualSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token comment\">\/\/ \u2460 downgrade &amp; upgrade support<\/span><br \/>\n            <span class=\"token keyword\">uint32_t<\/span> oldStyleActualSize <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token function\">memcpy<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>oldStyleActualSize<span class=\"token punctuation\">,<\/span> m_file<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>        <span class=\"token comment\">\/\/ :237<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>oldStyleActualSize <span class=\"token operator\">!&#061;<\/span> m_actualSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>oldStyleActualSize <span class=\"token operator\">&lt;<\/span> fileSize <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token punctuation\">(<\/span>oldStyleActualSize <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">checkFileCRCValid<\/span><span class=\"token punctuation\">(<\/span>oldStyleActualSize<span class=\"token punctuation\">,<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_crcDigest<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                        <span class=\"token function\">MMKVInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;looks like [%s] been downgrade &amp; upgrade again&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                        loadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                        <span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span>oldStyleActualSize<span class=\"token punctuation\">,<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_crcDigest<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">,<\/span> KeepSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                        <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span>                                                   <span class=\"token comment\">\/\/ :246<\/span><br \/>\n                    <span class=\"token punctuation\">}<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token comment\">\/\/ \u2461 \u56de\u9000\u5230 lastConfirmed<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> lastActualSize <span class=\"token operator\">&#061;<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_lastConfirmedMetaInfo<span class=\"token punctuation\">.<\/span>lastActualSize<span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :253<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>lastActualSize <span class=\"token operator\">&lt;<\/span> fileSize <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token punctuation\">(<\/span>lastActualSize <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">auto<\/span> lastCRCDigest <span class=\"token operator\">&#061;<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_lastConfirmedMetaInfo<span class=\"token punctuation\">.<\/span>lastCRCDigest<span class=\"token punctuation\">;<\/span><br \/>\n                <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">checkFileCRCValid<\/span><span class=\"token punctuation\">(<\/span>lastActualSize<span class=\"token punctuation\">,<\/span> lastCRCDigest<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                    loadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                    <span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span>lastActualSize<span class=\"token punctuation\">,<\/span> lastCRCDigest<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">,<\/span> KeepSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :258<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>    m_actualSize <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">readActualSize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                              <span class=\"token comment\">\/\/ :270<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_actualSize <span class=\"token operator\">&lt;<\/span> fileSize <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token punctuation\">(<\/span>m_actualSize <span class=\"token operator\">&#043;<\/span> Fixed32Size<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;&#061;<\/span> fileSize<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">checkFileCRCValid<\/span><span class=\"token punctuation\">(<\/span>m_actualSize<span class=\"token punctuation\">,<\/span> m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_crcDigest<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            loadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span>                                                  <span class=\"token comment\">\/\/ :274 \u4e00\u5207\u6b63\u5e38<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token function\">checkLastConfirmedInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                             <span class=\"token comment\">\/\/ :276<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>loadFromFile<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token keyword\">auto<\/span> strategic <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">onMMKVCRCCheckFail<\/span><span class=\"token punctuation\">(<\/span>m_mmapID<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                     <span class=\"token comment\">\/\/ :279 \u95ee\u4e1a\u52a1<\/span><br \/>\n                <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>strategic <span class=\"token operator\">&#061;&#061;<\/span> OnErrorRecover<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                    loadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                    needFullWriteback <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span>                                     <span class=\"token comment\">\/\/ :282 \u2605\u8d2a\u5fc3\u6062\u590d<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;check [%s] error: %zu size in total, file size is %zu&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token function\">checkLastConfirmedInfo<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                                  <span class=\"token comment\">\/\/ :290<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>loadFromFile<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> strategic <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">onMMKVFileLengthError<\/span><span class=\"token punctuation\">(<\/span>m_mmapID<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                      <span class=\"token comment\">\/\/ :293<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>strategic <span class=\"token operator\">&#061;&#061;<\/span> OnErrorRecover<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                m_actualSize <span class=\"token operator\">&#061;<\/span> fileSize <span class=\"token operator\">&#8211;<\/span> Fixed32Size<span class=\"token punctuation\">;<\/span>                             <span class=\"token comment\">\/\/ :296 \u522b\u8d8a\u754c\u8bfb<\/span><br \/>\n                loadFromFile <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n                needFullWriteback <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u81ea\u6108\u7684\u5b8c\u6574\u4f18\u5148\u7ea7&#xff08;\u80cc\u4e0b\u6765\u5373\u53ef\u5e94\u4ed8\u8ffd\u95ee&#xff09;&#xff1a;<\/p>\n<li>\u6b63\u5e38\u8def\u5f84&#xff1a;actualSize \u5408\u7406\u4e14 CRC \u5339\u914d \u2192 \u76f4\u63a5\u52a0\u8f7d\u3002<\/li>\n<li>\u964d\u7ea7\/\u5347\u7ea7\u517c\u5bb9&#xff1a;\u7528\u6570\u636e\u6587\u4ef6\u5934 4 \u5b57\u8282\u7684 oldStyleActualSize \u518d\u9a8c\u4e00\u6b21 CRC&#xff0c;\u517c\u5bb9\u300c\u8001\u7248\u672c SDK \u5199\u8fc7\u53c8\u6362\u56de\u65b0\u7248\u672c\u300d\u3002<\/li>\n<li>\u56de\u9000\u5230 lastConfirmed&#xff1a;\u7528 m_lastConfirmedMetaInfo \u7684 (lastActualSize, lastCRCDigest) \u9a8c\u8bc1 \u2192 \u6210\u529f\u5c31 \u628a\u8d26\u672c\u6539\u5199\u4e3a\u8fd9\u4e2a\u5b89\u5168\u70b9&#xff0c;\u7b49\u4e8e\u56de\u6eda\u5230\u4e0a\u6b21\u91cd\u6574\u72b6\u6001\u3002<\/li>\n<li>\u4e1a\u52a1\u51b3\u7b56&#xff1a;MMKVHandler.onMMKVCRCCheckFail \/ onMMKVFileLengthError \u8fd4\u56de\n<ul>\n<li>OnErrorRecover \u2192 loadFromFile&#061;true, needFullWriteback&#061;true&#xff0c;\u8d70 greedyDecodeMap \u5c3d\u53ef\u80fd\u62a2\u6551\u635f\u574f\u70b9\u4e4b\u524d\u7684\u6240\u6709\u8bb0\u5f55&#xff0c;\u7136\u540e\u7acb\u5373 fullWriteback \u628a\u6709\u6548\u6570\u636e\u91cd\u5199\u843d\u76d8&#xff1b;<\/li>\n<li>OnErrorDiscard&#xff08;\u9ed8\u8ba4 :277 \u4e4b\u540e\u4ecd\u4e3a false \u65f6&#xff09; \u2192 \u8d70 loadFromFile \u7684 else \u5206\u652f&#xff0c;writeActualSize(0, 0, nullptr, IncreaseSequence) \u6574\u4e2a\u6587\u4ef6\u4f5c\u5e9f&#xff08;Core\/MMKV_IO.cpp:133&#xff09;\u3002<\/li>\n<\/ul>\n<\/li>\n<p>\u9519\u8bef\u5904\u7406\u5165\u53e3\u7c7b\u578b\u5b9a\u4e49\u5728 Core\/MMKVPredef.h:146&#xff1a;<\/p>\n<p><span class=\"token keyword\">enum<\/span> <span class=\"token class-name\">MMKVRecoverStrategic<\/span> <span class=\"token operator\">:<\/span> <span class=\"token keyword\">int<\/span> <span class=\"token punctuation\">{<\/span> OnErrorDiscard <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> OnErrorRecover<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">typedef<\/span> <span class=\"token function\">MMKVRecoverStrategic<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>ErrorHandler<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> std<span class=\"token double-colon punctuation\">::<\/span>string <span class=\"token operator\">&amp;<\/span>mmapID<span class=\"token punctuation\">,<\/span> MMKVErrorType errorType<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>  <span class=\"token comment\">\/\/ :166<\/span><\/p>\n<h4>10.4 meta \u6587\u4ef6\u81ea\u8eab\u7684\u300c\u534a\u5199\u300d\u68c0\u6d4b<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:205<\/span><br \/>\n<span class=\"token comment\">\/\/ the meta file is in specious status<\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_version <span class=\"token operator\">&gt;&#061;<\/span> MMKVVersionHolder<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">MMKVWarning<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;meta file [%s] in specious state, version %u, flags 0x%llx&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_version <span class=\"token operator\">&#061;<\/span> MMKVVersionActualSize<span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :210 \u56de\u9000\u5230\u300c\u4e0a\u4e00\u4e2a\u5df2\u77e5\u7248\u672c\u300d<\/span><br \/>\n    m_metaInfo<span class=\"token operator\">-&gt;<\/span>m_flags <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span>                          <span class=\"token comment\">\/\/ :211<\/span><br \/>\n    m_metaInfo<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">write<\/span><span class=\"token punctuation\">(<\/span>m_metaFile<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">getMemory<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u7248\u672c\u53f7\u679a\u4e3e&#xff08;Core\/MMKVMetaInfo.hpp:47-50&#xff09;&#xff1a;MMKVVersionNext &#061; 5&#xff0c;MMKVVersionHolder &#061; MMKVVersionNext &#043; 1\u3002<\/p>\n<p>\u8fd9\u662f\u4e00\u62db\u5f88\u5de7\u7684\u300c\u54e8\u5175\u7248\u672c\u300d&#xff1a;\u6b63\u5e38\u5199\u5165\u7684 m_version \u6c38\u8fdc &lt; MMKVVersionHolder\u3002\u5982\u679c\u8bfb\u51fa\u6765\u7684\u7248\u672c\u53f7 \u5927\u4e8e\u7b49\u4e8e \u8fd9\u4e2a\u4e0d\u53ef\u80fd\u503c&#xff0c;\u8bf4\u660e\u8fd9\u5757\u9875\u662f\u6587\u4ef6\u7cfb\u7edf\u4e3a\u65b0\u6587\u4ef6\u586b\u7684 \u5168 0\/\u672a\u521d\u59cb\u5316\u5185\u5bb9\u4e4b\u5916\u7684\u5783\u573e&#xff08;\u6216\u5168 1 \u4e4b\u7c7b\u7684\u5f02\u5e38\u6001&#xff09;&#xff0c;\u5373 meta \u9875\u672c\u8eab\u5904\u4e8e\u300c\u5199\u4e86\u4e00\u534a\u300d\u7684 specious \u72b6\u6001\u3002\u6b64\u65f6\u4e0d\u731c\u3001\u4e0d\u5d29&#xff0c;\u76f4\u63a5\u628a\u7248\u672c\u56de\u9000\u4e3a MMKVVersionActualSize&#xff08;\u201cthe last version we don\u2019t check meta file\u201d&#xff0c;:209 \u6ce8\u91ca&#xff09;&#xff0c;\u6e05\u6389 flags&#xff0c;\u8ba9\u540e\u7eed checkDataValid \u7528\u6570\u636e\u6587\u4ef6 &#043; CRC \u6765\u5224\u65ad\u771f\u76f8\u3002<\/p>\n<hr \/>\n<h3>11. AES-CFB128 \u52a0\u5bc6<\/h3>\n<h4>11.1 \u5c01\u88c5\u4e0e\u5bc6\u94a5<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/aes\/AESCrypt.h:57<\/span><br \/>\n<span class=\"token comment\">\/\/ a AES CFB-128 encrypt-decrypt full-duplex wrapper<\/span><br \/>\n<span class=\"token keyword\">class<\/span> <span class=\"token class-name\">AESCrypt<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n    <span class=\"token keyword\">void<\/span> <span class=\"token function\">getCurStatus<\/span><span class=\"token punctuation\">(<\/span>AESCryptStatus <span class=\"token operator\">&amp;<\/span>status<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                        <span class=\"token comment\">\/\/ :82<\/span><br \/>\n    <span class=\"token keyword\">void<\/span> <span class=\"token function\">statusBeforeDecrypt<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>input<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>output<span class=\"token punctuation\">,<\/span> size_t length<span class=\"token punctuation\">,<\/span><br \/>\n                             AESCryptStatus <span class=\"token operator\">&amp;<\/span>status<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                  <span class=\"token comment\">\/\/ :83<\/span><br \/>\n    AESCrypt <span class=\"token function\">cloneWithStatus<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> AESCryptStatus <span class=\"token operator\">&amp;<\/span>status<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">const<\/span><span class=\"token punctuation\">;<\/span>                      <span class=\"token comment\">\/\/ :85<\/span><br \/>\n    <span class=\"token keyword\">void<\/span> <span class=\"token function\">resetStatus<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> AESCryptStatus <span class=\"token operator\">&amp;<\/span>status<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                    <span class=\"token comment\">\/\/ :88<\/span><br \/>\n    <span class=\"token keyword\">static<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token function\">fillRandomIV<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>vector<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                            <span class=\"token comment\">\/\/ :93<\/span><br \/>\n    <span class=\"token keyword\">static<\/span> <span class=\"token keyword\">uint32_t<\/span> <span class=\"token function\">randomItemSizeHolder<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span> size<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                               <span class=\"token comment\">\/\/ :94<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/aes\/AESCrypt.h:48<\/span><br \/>\n<span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">AESCryptStatus<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">uint8_t<\/span> m_number<span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">uint8_t<\/span> m_vector<span class=\"token punctuation\">[<\/span>AES_KEY_LEN<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ #pragma pack(1)<\/span><\/p>\n<ul>\n<li>\u7b97\u6cd5&#xff1a;AES-128-CFB&#xff08;128bit \u5168\u53cd\u9988&#xff09;&#xff0c;\u5bc6\u94a5 AES_KEY_LEN &#061; 16&#xff08;Core\/MMKVPredef.h:235&#xff09;&#xff0c;\u5b9e\u73b0\u6765\u81ea\u5185\u5d4c\u7684 OpenSSL aes \u6a21\u5757&#xff08;Core\/aes\/openssl\/&#xff09;&#xff0c;aarch64 \u4e0a\u88ab\u66ff\u6362\u4e3a ARMv8 \u786c\u4ef6\u6307\u4ee4&#xff08;\u89c1 2.3&#xff09;\u3002<\/li>\n<li>AESCryptStatus \u662f\u70b9\u775b\u4e4b\u7b14&#xff1a;CFB \u6a21\u5f0f\u5728 128bit \u5168\u53cd\u9988\u4e0b&#xff0c;\u7b2c n \u5757\u7684 keystream \u4f9d\u8d56\u7b2c n-1 \u5757\u5bc6\u6587&#xff0c;\u5929\u751f\u65e0\u6cd5\u968f\u673a\u8bbf\u95ee\u3002\u628a (m_number, m_vector) \u8fd9\u4e24\u4e2a\u300c\u6d41\u4f4d\u7f6e\u72b6\u6001\u300d\u968f\u6bcf\u6761\u5927\u8bb0\u5f55\u4e00\u8d77\u5b58\u8fdb KeyValueHolderCrypt&#xff0c;\u5c31\u7b49\u4e8e\u7ed9\u6bcf\u6761\u8bb0\u5f55\u5b58\u4e86\u4e00\u4e2a \u201c\u968f\u673a\u8bbf\u95ee\u5b58\u6863\u70b9\u201d&#xff0c;\u4ece\u6b64\u53ef\u4ee5\u7528 cloneWithStatus() \u4ece\u4efb\u610f offset \u72ec\u7acb\u89e3\u5bc6&#xff08;Core\/MMKV_IO.cpp:1159 \u7684\u52a0\u5bc6\u7248 memmoveDictionary \u4f9d\u8d56\u6b64\u80fd\u529b&#xff09;\u3002<\/li>\n<li>thread_local AESCryptStatus t_status;&#xff08;Core\/MMKV_IO.cpp:577&#xff09;&#xff1a;\u5199\u7ebf\u7a0b\u5728 append \u524d\u7528 m_crypter-&gt;getCurStatus(t_status)&#xff08;:850&#xff09;\u6293\u62cd\u5f53\u524d\u6d41\u72b6\u6001&#xff0c;\u4f9b holder \u8bb0\u5f55\u5b58\u6863\u70b9\u3002<\/li>\n<\/ul>\n<h4>11.2 \u5bc6\u94a5\u5b58\u5728\u54ea\u91cc<\/h4>\n<p>AESCrypt \u6784\u9020\u65f6 memcpy(m_key, key, &#8230;)&#xff08;Core\/aes\/AESCrypt.cpp:51&#xff09;&#xff0c;m_key \u662f native \u5806\u4e0a\u7684 16 \u5b57\u8282\u6570\u7ec4\u3002Java \u5c42 cryptKey \u5b57\u7b26\u4e32\u5728 JNI \u8c03\u7528\u4e2d\u8f6c\u4e3a std::string&#xff0c;native-bridge.cpp \u91cc\u7528 String2MMKVPath_t &#043; SCOPE_EXIT \u4e4b\u7c7b\u7684\u4f5c\u7528\u57df\u4fdd\u62a4&#xff0c;\u51fd\u6570\u8fd4\u56de\u5373\u6790\u6784\u5e76&#xff08;\u5c3d\u529b&#xff09;\u62b9\u6389\u4e34\u65f6\u4e32\u3002\u6240\u4ee5&#xff1a;<\/p>\n<ul>\n<li>\u5bc6\u94a5 \u4e0d\u8fdb Java \u5806\u3001\u4e0d\u8fdb dex\u3001\u4e0d\u8fdb SharedPreferences&#xff0c;\u53cd\u5c04\u548c Java \u5c42 hook \u62ff\u4e0d\u5230&#xff1b;<\/li>\n<li>\u4f46 native \u5185\u5b58 dump&#xff08;Frida hook AESCrypt \u6784\u9020&#xff09;\u4f9d\u7136\u80fd\u62ff\u5230\u3002MMKV \u7684\u52a0\u5bc6\u5b9a\u4f4d\u662f\u300c\u9632\u541b\u5b50\u4e0d\u9632\u5c0f\u4eba\u300d\u7684 \u9759\u6001\u6570\u636e\u4fdd\u62a4&#xff08;\u9632\u6b62\u6587\u4ef6\u88ab\u76f4\u63a5\u8bfb\u53d6\/\u62f7\u8d1d\u89e3\u6790&#xff09;&#xff0c;\u4e0d\u662f \u5bc6\u94a5\u7ba1\u7406\u4f53\u7cfb\u3002\u751f\u4ea7\u7ea7\u654f\u611f\u6570\u636e\u8bf7\u518d\u5957\u4e00\u5c42\u4fe1\u5c01\u52a0\u5bc6\u3002<\/li>\n<\/ul>\n<h4>11.3 IV \u968f\u673a\u5316\u4e0e\u957f\u5ea6\u4f2a\u88c5<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/aes\/AESCrypt.cpp:109<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">AESCrypt<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">fillRandomIV<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>vector<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">srand<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">unsigned<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token function\">time<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">int<\/span> <span class=\"token operator\">*<\/span>ptr <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">int<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span> vector<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span> i <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span> i <span class=\"token operator\">&lt;<\/span> AES_KEY_LEN <span class=\"token operator\">\/<\/span> <span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">int<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> i<span class=\"token operator\">&#043;&#043;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> ptr<span class=\"token punctuation\">[<\/span>i<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">rand<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>   <span class=\"token comment\">\/\/ :116<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>IV \u5b58\u8fdb meta \u7684 m_vector[16]&#xff08;Core\/MMKVMetaInfo.hpp:57&#xff09;&#xff0c;\u52a0\u8f7d\u65f6 resetIV()&#xff08;Core\/MMKV_IO.cpp:69&#xff09;\u3002\u6bcf\u6b21 fullWriteback \/ clearAll&#xff08;Core\/MMKV_IO.cpp:1479&#xff09;\u90fd\u4f1a\u6362\u4e00\u4e2a\u65b0\u7684\u968f\u673a IV&#xff0c;\u56e0\u6b64\u540c\u4e00\u4efd\u6570\u636e\u4e24\u6b21\u91cd\u6574\u540e\u7684\u5bc6\u6587\u4e0d\u540c&#xff0c;\u524a\u5f31\u300c\u5df2\u77e5\u660e\u6587\/\u56fa\u5b9a\u524d\u7f00\u300d\u7c7b\u5206\u6790\u3002<\/p>\n<p><span class=\"token comment\">\/\/ Core\/aes\/AESCrypt.cpp:33  \u968f\u673a\u5316\u7684 ItemSizeHolder<\/span><br \/>\n<span class=\"token keyword\">uint32_t<\/span> <span class=\"token class-name\">AESCrypt<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">randomItemSizeHolder<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span> size<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">constexpr<\/span> <span class=\"token keyword\">uint32_t<\/span> ItemSizeHolders<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0x80<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0x4000<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0x200000<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0x10000000<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ :34<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> ItemSizeHolderMin <span class=\"token operator\">&#061;<\/span> ItemSizeHolders<span class=\"token punctuation\">[<\/span>size <span class=\"token operator\">&#8211;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> ItemSizeHolderMax <span class=\"token operator\">&#061;<\/span> ItemSizeHolders<span class=\"token punctuation\">[<\/span>size<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#8211;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">srand<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">unsigned<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token function\">time<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">auto<\/span> result <span class=\"token operator\">&#061;<\/span> <span class=\"token generic-function\"><span class=\"token function\">static_cast<\/span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token operator\">&gt;<\/span><\/span><\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">rand<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    result <span class=\"token operator\">&#061;<\/span> result <span class=\"token operator\">%<\/span> <span class=\"token punctuation\">(<\/span>ItemSizeHolderMax <span class=\"token operator\">&#8211;<\/span> ItemSizeHolderMin <span class=\"token operator\">&#043;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    result <span class=\"token operator\">&#043;&#061;<\/span> ItemSizeHolderMin<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> result<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u6587\u4ef6\u5934\u7b2c 5\u20138 \u5b57\u8282\u672c\u6765\u662f\u300c\u5b57\u5178\u5e8f\u5217\u5316\u7ed3\u679c\u7684\u957f\u5ea6\u300d&#xff0c;\u4f1a\u88ab\u653b\u51fb\u8005\u7528\u6765\u63a8\u65ad\u6761\u76ee\u6570\u3002MMKV \u628a\u5b83\u66ff\u6362\u6210 \u540c varint \u5b57\u8282\u6570\u4e0b\u7684\u968f\u673a\u503c&#xff1a;{0, 0x80}\u3001{0x80, 0x4000}\u2026 \u662f\u6309 varint \u7f16\u7801\u4f4d\u6570\u5206\u6bb5\u7684\u533a\u95f4&#xff0c;\u4fdd\u8bc1\u968f\u673a\u503c \u5360\u7528\u7684\u5b57\u8282\u6570\u4e0e\u771f\u5b9e\u503c\u4e00\u81f4&#xff08;size \u53c2\u6570\u5c31\u662f\u6240\u9700\u5b57\u8282\u6570&#xff09;&#xff0c;\u56e0\u6b64\u4e0d\u7834\u574f\u540e\u7eed\u89e3\u6790\u3002\u8bfb\u53d6\u65f6 MiniPBCoder::decodeOneMap \u53ea\u662f m_inputData-&gt;readInt32() \u628a\u5b83 \u5403\u6389\u4e22\u5f03&#xff08;Core\/MiniPBCoder.cpp:511&#xff09;&#xff0c;\u4ece\u4e0d\u53c2\u4e0e\u903b\u8f91 \u2014\u2014 \u6240\u4ee5\u4f2a\u88c5\u65e0\u5bb3\u3002\u8fd9\u662f\u4e00\u4e2a\u300c\u7528\u517c\u5bb9\u6027\u6362\u9690\u79c1\u300d\u7684\u5c0f\u8bbe\u8ba1&#xff0c;\u5f88\u503c\u5f97\u5728\u9762\u8bd5\u4e2d\u8bb2\u3002<\/p>\n<p>\u987a\u5e26\u4e00\u4e2a\u771f\u5b9e\u7684\u5de5\u7a0b\u53d6\u820d&#xff1a;srand(time) &#043; rand() \u5e76\u975e\u5bc6\u7801\u5b66\u5b89\u5168\u968f\u673a\u6e90\u3002\u5b83\u7684\u76ee\u7684\u53ea\u662f\u300c\u6bcf\u6b21\u4e0d\u540c\u300d&#xff0c;IV \u7684\u4f5c\u7528\u5728 CFB \u4e0b\u4e5f\u4e3b\u8981\u662f\u6253\u6563\u5bc6\u6587\u800c\u975e\u8bed\u4e49\u5b89\u5168\u3002\u82e5\u8981\u505a\u4e25\u8c28\u8bc4\u4f30&#xff0c;\u8fd9\u91cc\u5e94\u5f53\u6362\u6210 getrandom\/arc4random\u3002<\/p>\n<h4>11.4 reKey&#xff1a;\u6362\u5bc6\u94a5 &#061; \u4e00\u6b21\u5168\u91cf\u91cd\u6574<\/h4>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:1345&#xff08;\u9aa8\u67b6&#xff09;<\/span><br \/>\n<span class=\"token keyword\">bool<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">reKey<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> string <span class=\"token operator\">&amp;<\/span>cryptKey<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_lock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>m_exclusiveProcessLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">checkLoadData<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span><span class=\"token function\">isFileValid<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">MMKVWarning<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;[%s] file not valid&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>   <span class=\"token comment\">\/\/ :1350<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_crypter<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>cryptKey<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>cryptKey <span class=\"token operator\">&#061;&#061;<\/span> oldKey<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                       <span class=\"token comment\">\/\/ :1358 \u540c\u952e\u76f4\u63a5\u6210\u529f<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> newCrypt <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token function\">AESCrypt<\/span><span class=\"token punctuation\">(<\/span>cryptKey<span class=\"token punctuation\">.<\/span><span class=\"token function\">data<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> cryptKey<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            m_hasFullWriteback <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span>                                    <span class=\"token comment\">\/\/ :1364 \u2605\u5f3a\u5236\u91cd\u6574<\/span><br \/>\n            ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">fullWriteback<\/span><span class=\"token punctuation\">(<\/span>newCrypt<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                 <span class=\"token comment\">\/\/ :1365 \u91cd\u6574\u5373&#034;\u7528\u65b0\u94a5\u91cd\u5199\u5168\u90e8&#034;<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ret<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">delete<\/span> m_crypter<span class=\"token punctuation\">;<\/span> m_crypter <span class=\"token operator\">&#061;<\/span> newCrypt<span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token keyword\">else<\/span>     <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">delete<\/span> newCrypt<span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                                  <span class=\"token comment\">\/\/ :1370 \u5931\u8d25\u5219\u4fdd\u7559\u65e7\u94a5<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">fullWriteback<\/span><span class=\"token punctuation\">(<\/span>InvalidCryptPtr<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                          <span class=\"token comment\">\/\/ :1377 \u89e3\u5bc6\u4e3a\u660e\u6587<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>cryptKey<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token keyword\">auto<\/span> newCrypt <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token function\">AESCrypt<\/span><span class=\"token punctuation\">(<\/span>cryptKey<span class=\"token punctuation\">.<\/span><span class=\"token function\">data<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> cryptKey<span class=\"token punctuation\">.<\/span><span class=\"token function\">length<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">fullWriteback<\/span><span class=\"token punctuation\">(<\/span>newCrypt<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                                 <span class=\"token comment\">\/\/ :1392 \u660e\u6587\u8f6c\u52a0\u5bc6<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ret<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">clearMemoryCache<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span>                                       <span class=\"token comment\">\/\/ :1407 \u2605reKey \u540e\u5b57\u5178\u5931\u6548<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> ret<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>MMKV \u6ca1\u6709\u4e3a\u300c\u6362\u5bc6\u94a5\u300d\u5199\u4efb\u4f55\u4e13\u95e8\u7684\u904d\u5386\u903b\u8f91&#xff0c;\u800c\u662f\u590d\u7528\u91cd\u6574&#xff1a;m_hasFullWriteback &#061; false \u903c fullWriteback \u5e72\u6d3b&#xff0c;doFullWriteBack \u5185\u90e8\u5bf9\u6574\u6bb5\u6570\u636e\u300c\u65e7\u94a5\u89e3\u5bc6 \u2192 \u65b0\u94a5\u52a0\u5bc6 \u2192 \u6362 IV \u2192 \u91cd\u7b97 CRC \u2192 sequence&#043;&#043; \u2192 msync\u300d\u3002\u56e0\u6b64 \u52a0\u5bc6\/\u89e3\u5bc6\/\u6362\u94a5\u4e09\u4ef6\u4e8b\u5171\u7528\u4e00\u6761\u4ee3\u7801\u8def\u5f84&#xff0c;\u51fa\u9519\u9762\u6781\u5c0f\u3002\u6700\u540e clearMemoryCache() \u662f\u56e0\u4e3a holder \u91cc\u5b58\u7684 cryptStatus \u5df2\u7ecf\u5168\u90e8\u4f5c\u5e9f\u3002<\/p>\n<hr \/>\n<h3>12. \u8fdb\u9636\u80fd\u529b&#xff1a;\u8fc7\u671f\u3001compareBeforeSet\u3001\u5185\u5bb9\u901a\u77e5\u3001ashmem<\/h3>\n<h4>12.1 Key \u8fc7\u671f&#xff08;TTL&#xff09;<\/h4>\n<ul>\n<li>\u5f00\u5173&#xff1a;MMKV.enableAutoKeyExpire(expireDurationInSeconds) \u2192 \u843d\u5230 m_enableKeyExpire \u4e0e meta \u7684 m_flags&#xff08;Core\/MMKVMetaInfo.hpp:70 EnableKeyExipre &#061; 1 &lt;&lt; 0&#xff09;&#xff0c;\u4e0b\u6b21 loadMetaInfoAndCheck() \u8bfb\u56de&#xff08;Core\/MMKV_IO.cpp:216&#xff09;\u3002<\/li>\n<li>\u5b58\u50a8&#xff1a;\u5199\u503c\u65f6 \u5728 value \u5c3e\u90e8\u8ffd\u52a0 4 \u5b57\u8282 little-endian \u8fc7\u671f\u65f6\u95f4\u6233&#xff08;Core\/MMKV.cpp:461&#xff09;&#xff0c;\u8bfb\u65f6\u7528 getDataWithoutMTimeForKey() \u5265\u6389\u8fd9 4 \u5b57\u8282&#xff08;Core\/MMKV_IO.cpp:567&#xff09;\u3002<\/li>\n<li>\u6e05\u7406&#xff1a;filterExpiredKeys()&#xff08;Core\/MMKV_IO.cpp:1820&#xff09;\u5728 ensureMemorySize \u4e0e fullWriteback \u524d\u88ab\u52a8\u89e6\u53d1\u3002<\/li>\n<li>\u9650\u5236&#xff1a;enableCompareBeforeSet \u4e0e\u8fc7\u671f \u4e92\u65a5&#xff0c;\u6e90\u7801\u663e\u5f0f\u5173\u95ed\u524d\u8005&#xff1a;<\/li>\n<\/ul>\n<p><span class=\"token comment\">\/\/ Core\/MMKV_IO.cpp:217<\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_enableKeyExpire <span class=\"token operator\">&amp;&amp;<\/span> m_enableCompareBeforeSet<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">MMKVError<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;enableCompareBeforeSet will be invalid when Expiration is on&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    m_enableCompareBeforeSet <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h4>12.2 compareBeforeSet<\/h4>\n<p>\u89c1 6.2 \u7b2c \u2460 \u5206\u652f&#xff1a;\u5f00\u542f\u540e&#xff08;MMKV.enableCompareBeforeSet()&#xff0c;Core\/MMKV_IO.cpp:1903&#xff09;&#xff0c;\u5bf9\u5df2\u5b58\u5728 key \u5148\u505a oldValueData &#061;&#061; data \u7684\u5b57\u8282\u6bd4\u8f83&#xff0c;\u76f8\u540c\u5219 \u76f4\u63a5 return true\u3002\u9002\u5408\u300c\u72b6\u6001\u503c\u9891\u7e41 set \u4f46\u6781\u5c11\u771f\u53d8\u300d\u7684\u573a\u666f&#xff0c;\u80fd\u663e\u8457\u51cf\u5c11\u6587\u4ef6\u81a8\u80c0\u548c CRC \u8ba1\u7b97\u3002\u4ee3\u4ef7&#xff1a;\u6bcf\u6b21 set \u591a\u4e00\u6b21 MMBuffer \u6784\u9020 &#043; memcmp&#xff0c;\u70ed\u8def\u5f84\u53d8\u957f&#xff0c;\u56e0\u6b64\u9ed8\u8ba4\u5173\u95ed\u3002<\/p>\n<h4>12.3 \u8de8\u8fdb\u7a0b\u5185\u5bb9\u53d8\u66f4\u901a\u77e5<\/h4>\n<p><span class=\"token comment\">\/\/ MMKV.java:1616&#xff08;Javadoc \u672c\u8eab\u5c31\u662f\u6700\u6743\u5a01\u7684\u7b54\u6848&#xff09;<\/span><br \/>\n<span class=\"token comment\">\/**<br \/>\n * Register for MMKV inter-process content change notification.<br \/>\n * The notification will trigger only when any method is manually called on the MMKV instance.<br \/>\n * For example {&#064;link #checkContentChangedByOuterProcess()}.<br \/>\n *\/<\/span><br \/>\n<span class=\"token keyword\">public<\/span> <span class=\"token keyword\">static<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token function\">registerContentChangeNotify<\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">MMKVContentChangeNotification<\/span> notify<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>   <span class=\"token comment\">\/\/ :1623<\/span><br \/>\n    gContentChangeNotify <span class=\"token operator\">&#061;<\/span> notify<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">setWantsContentChangeNotify<\/span><span class=\"token punctuation\">(<\/span>gContentChangeNotify <span class=\"token operator\">!&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                            <span class=\"token comment\">\/\/ :1625<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ MMKV.java:1636 \u2014\u2014 native \u56de\u8c03\u8fdb Java \u7684\u843d\u70b9<\/span><br \/>\n<span class=\"token keyword\">private<\/span> <span class=\"token keyword\">static<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token function\">onContentChangedByOuterProcess<\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">String<\/span> mmapID<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>gContentChangeNotify <span class=\"token operator\">!&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        gContentChangeNotify<span class=\"token punctuation\">.<\/span><span class=\"token function\">onContentChangedByOuterProcess<\/span><span class=\"token punctuation\">(<\/span>mmapID<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                      <span class=\"token comment\">\/\/ :1638<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u5b98\u65b9 Javadoc \u90a3\u53e5\u8bdd&#xff08;MMKV.java:1618&#xff09;\u503c\u5f97\u9010\u5b57\u8bfb&#xff1a;\u201ctrigger only when any method is manually called on the MMKV instance\u201d\u3002<\/p>\n<p>\u89e6\u53d1\u70b9\u5728 Core\/MMKV_IO.cpp:330 \/ :344 \u7684 notifyContentChanged()&#xff08;\u5b9e\u73b0\u89c1 Core\/MMKV.cpp:283&#xff09;&#xff1a;\u53ea\u6709 checkLoadData() \u68c0\u6d4b\u5230\u522b\u7684\u8fdb\u7a0b\u6539\u4e86\u6570\u636e&#xff0c;\u624d\u4f1a\u56de\u8c03\u3002<\/p>\n<h4>12.3b checkProcessMode \u4e4b\u5916\u7684\u53e6\u4e00\u4e2a\u624b\u52a8\u5165\u53e3<\/h4>\n<p><span class=\"token comment\">\/\/ MMKV.java:1645&#xff08;\u6ce8\u91ca&#xff09;&#043; :1647<\/span><br \/>\n<span class=\"token comment\">\/** Check inter-process content change manually. *\/<\/span><br \/>\n<span class=\"token keyword\">public<\/span> <span class=\"token keyword\">native<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token function\">checkContentChangedByOuterProcess<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>\u8fd9\u5c31\u662f\u5b98\u65b9\u7ed9\u7684\u300c\u4e3b\u52a8\u62c9\u4e00\u6b21\u4e00\u81f4\u6027\u68c0\u67e5\u300d\u5165\u53e3&#xff0c;native \u5b9e\u73b0\u5185\u90e8\u5373\u8c03\u7528 checkLoadData()&#xff08;Core\/MMKV_IO.cpp:305&#xff09;\u3002\u60f3\u8981\u300c\u4f2a push\u300d&#xff0c;\u5c31\u5b9a\u65f6\u8c03\u5b83 \u2014\u2014 \u6210\u672c\u4ec5\u662f\u4e00\u6b21 40 \u5b57\u8282\u7684 meta memcpy \u6bd4\u8f83\u3002<\/p>\n<p>MMKV.java:1613 \u7684\u6ce8\u91ca\u4e5f\u5370\u8bc1\u4e86\u89e6\u53d1\u65f6\u673a&#xff1a;\/\/ trigger by getXXX() or setXXX() or checkContentChangedByOuterProcess()\u3002<\/p>\n<p>\u5fc5\u987b\u7406\u89e3\u7684\u5173\u952e\u9650\u5236&#xff1a;MMKV \u6ca1\u6709 push \u673a\u5236\u3002notifyContentChanged \u53ea\u4f1a\u5728 \u672c\u8fdb\u7a0b\u81ea\u5df1\u53d1\u751f\u8bfb\u6216\u5199&#xff08;\u4ece\u800c\u8fdb\u5165 checkLoadData&#xff09;\u65f6\u88ab\u89e6\u53d1\u3002\u4e5f\u5c31\u662f\u8bf4&#xff1a;<\/p>\n<p>\u300c\u5176\u4ed6\u8fdb\u7a0b\u6539\u4e86\u6570\u636e&#xff0c;\u672c\u8fdb\u7a0b\u4e0d\u4f1a\u81ea\u52a8\u6536\u5230\u901a\u77e5\u300d\u2014\u2014 \u60f3\u8981\u300c\u5b9e\u65f6\u611f\u77e5\u300d&#xff0c;\u8981\u4e48\u8f6e\u8be2\u8bfb\u4e00\u6b21&#xff08;\u6210\u672c\u6781\u4f4e&#xff09;&#xff0c;\u8981\u4e48\u81ea\u5df1\u5728\u5199\u65b9\u989d\u5916\u5e7f\u64ad&#xff08;ContentObserver\/Broadcast&#xff09;\u3002\u8fd9\u662f\u5f88\u591a\u56e2\u961f\u63a5\u5165 MMKV \u505a\u591a\u8fdb\u7a0b\u914d\u7f6e\u540c\u6b65\u65f6\u7684\u7b2c\u4e00\u4e2a\u5751\u3002<\/p>\n<h4>12.4 ashmem \u6a21\u5f0f\u4e0e MMKVContentProvider<\/h4>\n<h4>\u3010\u7ea0\u504f\u3011MMKVContentProvider \u4e0e\u300c\u591a\u8fdb\u7a0b\u6027\u80fd\u65b9\u6848\u300d\u65e0\u5173<\/h4>\n<p>\u9762\u7ecf\u91cc\u5e38\u8bf4\u300cMMKV \u4e0d\u7528 ContentProvider \u662f\u56e0\u4e3a\u5b83\u6162\u300d&#xff0c;\u7136\u540e\u6709\u4eba\u770b\u5230\u5e93\u91cc\u771f\u6709 MMKVContentProvider.java \u5c31\u56f0\u60d1\u4e86\u3002\u771f\u76f8\u662f&#xff1a;<\/p>\n<ul>\n<li>MMKVContentProvider \u53ea\u670d\u52a1\u4e8e mmkvWithAshmemID() \u8fd9\u4e00\u79cd \u8de8\u5e94\u7528\u5171\u4eab\u5185\u5b58 \u573a\u666f&#xff1a;\u5b83\u7684\u4f5c\u7528\u662f\u5728\u8fdb\u7a0b\/\u5e94\u7528\u4e4b\u95f4 \u4f20\u9012\u4e00\u4e2a ashmem \u7684 fd&#xff08;\u914d\u5408 ParcelableMMKV \u628a fd \u6253\u5305\u8fdb Bundle&#xff09;&#xff0c;\u5b8c\u5168\u4e0d\u53c2\u4e0e\u6570\u636e\u8bfb\u5199\u8def\u5f84\u3002<\/li>\n<li>\u5e38\u89c4\u591a\u8fdb\u7a0b&#xff08;\u540c\u4e00 App \u591a\u8fdb\u7a0b\u5171\u4eab MMKV&#xff09;\u8d70\u7684\u662f mmap \u540c\u4e00\u78c1\u76d8\u6587\u4ef6 &#043; flock &#043; meta \u4e09\u5143\u7ec4&#xff0c;\u8ddf ContentProvider \u4e00\u70b9\u5173\u7cfb\u90fd\u6ca1\u6709\u3002<\/li>\n<\/ul>\n<p>\u6240\u4ee5\u6b63\u786e\u8bf4\u6cd5\u662f&#xff1a;\u300cMMKV \u7684\u591a\u8fdb\u7a0b\u540c\u6b65\u4e0d\u4f9d\u8d56 Binder\/ContentProvider\u300d&#xff0c;\u800c \u4e0d\u662f \u300cMMKV \u91cc\u6ca1\u6709 ContentProvider\u300d\u3002<\/p>\n<p>ashmem \u5728\u6e90\u7801\u91cc\u7684\u7279\u6b8a\u6027&#xff08;Core\/MemoryFile_Android.cpp\u3001Core\/MMKV_Android.cpp&#xff09;&#xff1a;<\/p>\n<ul>\n<li>\u521b\u5efa&#xff1a;\u4f18\u5148 ASharedMemory_create&#xff08;\u901a\u8fc7 dlopen(&#034;libandroid.so&#034;) &#043; dlsym \u52a8\u6001\u53d6&#xff0c;Android O&#043;&#xff09;&#xff0c;\u964d\u7ea7 ashmem_create_region&#xff0c;\u518d\u964d\u7ea7 open(&#034;\/dev\/ashmem&#034;) &#043; ioctl(ASHMEM_SET_NAME\/SET_SIZE)&#xff1b;<\/li>\n<li>\u4e0d\u652f\u6301 ftruncate \u6269\u5bb9&#xff08;MemoryFile::truncate \u76f4\u63a5\u8fd4\u56de false&#xff0c;reloadFromFile \u5f00\u5934 if (m_fileType &#061;&#061; MMFILE_TYPE_ASHMEM) return; \u2014\u2014 Core\/MemoryFile.cpp:209&#xff09;\u2192 \u6240\u4ee5 ashmem \u6a21\u5f0f\u5fc5\u987b \u4e00\u5f00\u59cb\u5c31\u7ed9\u8db3\u5bb9\u91cf&#xff1b;<\/li>\n<li>\u4e0d\u652f\u6301 flock \u2192 FileLock(fd, true \/*isAshmem*\/) \u8d70 fcntl \u8bb0\u5f55\u9501&#xff08;Core\/InterProcessLock_Android.cpp:47&#xff09;&#xff1b;<\/li>\n<li>doCleanMemoryCache(false) \u5bf9 ashmem \u76f4\u63a5\u8df3\u8fc7&#xff08;Core\/MemoryFile.cpp:250&#xff09;&#xff0c;\u907f\u514d\u8bef\u91ca\u653e\u5171\u4eab\u5185\u5b58\u3002<\/li>\n<\/ul>\n<h4>12.5 \u5176\u5b83\u5b9e\u7528\u80fd\u529b\u901f\u67e5<\/h4>\n<table>\n<tr>\u80fd\u529bJava APICore \u5b9e\u73b0<\/tr>\n<tbody>\n<tr>\n<td>\u679a\u4e3e\u5168\u90e8 key<\/td>\n<td>allKeys()<\/td>\n<td>Core\/MMKV.cpp \u2192 \u904d\u5386\u5b57\u5178 key<\/td>\n<\/tr>\n<tr>\n<td>\u7edf\u8ba1\u6761\u6570<\/td>\n<td>count()<\/td>\n<td>m_dic-&gt;size()<\/td>\n<\/tr>\n<tr>\n<td>\u662f\u5426\u542b\u67d0 key<\/td>\n<td>containsKey(key)<\/td>\n<td>find \u5224\u5b58<\/td>\n<\/tr>\n<tr>\n<td>\u5206\u9875\u679a\u4e3e<\/td>\n<td>keys(size_t pageSize, long lastOffset, &#8230;)<\/td>\n<td>\u6309 offset \u5206\u6279&#xff0c;\u907f\u514d\u4e00\u6b21\u6027\u6784\u9020\u5927\u6570\u7ec4<\/td>\n<\/tr>\n<tr>\n<td>\u5907\u4efd<\/td>\n<td>backupMMKVFromID(&#8230;)<\/td>\n<td>MMKV_BACKUP \u6a21\u5f0f &#043; mmkv::copyFile&#xff08;Core\/MMKV_IO.cpp:1537 \u9644\u8fd1&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u539f\u6837\u62f7\u8d1d<\/td>\n<td>MMKV.copyMMKV(fromID, toID)<\/td>\n<td>\u62f7\u8d1d\u6570\u636e\u6587\u4ef6 &#043; .crc<\/td>\n<\/tr>\n<tr>\n<td>\u5220\u5e93<\/td>\n<td>MMKV.removeStorageByID(id)<\/td>\n<td>Core\/MMKV_IO.cpp:1537<\/td>\n<\/tr>\n<tr>\n<td>\u6587\u4ef6\u5065\u5eb7\u68c0\u67e5<\/td>\n<td>MMKV.isFileValid(id)<\/td>\n<td>Core\/MMKV_IO.cpp:1494<\/td>\n<\/tr>\n<tr>\n<td>\u9501<\/td>\n<td>lock()\/unlock()\/tryLock()<\/td>\n<td>Core\/MMKV.cpp:1181\/1185\/1189&#xff08;\u5c31\u662f\u66b4\u9732\u7b2c \u2462 \u5c42\u72ec\u5360\u8fdb\u7a0b\u9501\u7ed9\u4e1a\u52a1\u505a\u590d\u5408\u64cd\u4f5c\u7684\u539f\u5b50\u6027&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>MMKV.lock() \u8bed\u4e49&#xff1a;\u5b83\u62ff\u7684\u662f \u8de8\u8fdb\u7a0b\u72ec\u5360\u6587\u4ef6\u9501&#xff0c;\u4e0d\u662f\u8fdb\u7a0b\u5185\u9501\u3002\u4e1a\u52a1\u7528\u5b83\u6765\u628a\u300c\u8bfb-\u6539-\u5199\u300d\u5305\u6210\u539f\u5b50\u64cd\u4f5c&#xff0c;\u66ff\u4ee3\u5206\u5e03\u5f0f\u9501\u3002\u8fd9\u662f MMKV \u5e38\u88ab\u5ffd\u7565\u4f46\u975e\u5e38\u5b9e\u7528\u7684\u80fd\u529b&#xff08;Core\/MMKV.cpp:1181&#xff09;\u3002<\/p>\n<hr \/>\n<h3>13. \u4e0e SharedPreferences \u7684\u6e90\u7801\u7ea7\u5bf9\u6bd4<\/h3>\n<table>\n<tr>\u7ef4\u5ea6SharedPreferencesMMKV&#xff08;\u6e90\u7801\u4f9d\u636e&#xff09;<\/tr>\n<tbody>\n<tr>\n<td>\u5b58\u50a8\u683c\u5f0f<\/td>\n<td>XML \u5168\u91cf\u6587\u672c<\/td>\n<td>\u8ffd\u52a0\u5f0f protobuf wire-format \u4e8c\u8fdb\u5236&#xff08;MiniPBCoder.cpp:506&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u843d\u76d8\u65b9\u5f0f<\/td>\n<td>write() \u7cfb\u7edf\u8c03\u7528 &#043; \u5168\u91cf\u91cd\u5199<\/td>\n<td>MAP_SHARED mmap &#043; memcpy&#xff08;MemoryFile.cpp:197&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u9996\u6b21\u8bfb<\/td>\n<td>loadFromDisk \u5168\u91cf\u89e3\u6790&#xff0c;\u53ef\u80fd\u963b\u585e<\/td>\n<td>\u61d2\u52a0\u8f7d&#xff0c;\u4e14\u53ea\u5efa offset \u7d22\u5f15&#xff08;MMKV.cpp:120-124 \u6ce8\u91ca\u6389\u6784\u9020\u671f\u52a0\u8f7d&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u8bfb\u5355\u503c<\/td>\n<td>\u67e5 ArrayMap&lt;String, Object&gt;<\/td>\n<td>unordered_map \u5f02\u6784\u67e5\u627e &#043; \u96f6\u62f7\u8d1d\u89c6\u56fe&#xff08;KeyValueHolder.h:41&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u5199\u5355\u503c<\/td>\n<td>\u6539\u5185\u5b58 &#043; \u6807\u8bb0 dirty&#xff0c;\u6700\u7ec8\u5168\u91cf\u5e8f\u5217\u5316<\/td>\n<td>\u53ea\u8ffd\u52a0\u4e00\u6761\u8bb0\u5f55 &#043; 8 \u5b57\u8282 meta&#xff08;MMKV_IO.cpp:822\u3001MMKVMetaInfo.hpp:81&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u5220\u9664<\/td>\n<td>\u5168\u91cf\u91cd\u5199<\/td>\n<td>\u8ffd\u52a0 valueSize&#061;&#061;0 \u5893\u7891&#xff08;MiniPBCoder.cpp:523&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u5783\u573e\u56de\u6536<\/td>\n<td>\u65e0&#xff08;\u6bcf\u6b21\u90fd\u662f\u5168\u91cf&#xff09;<\/td>\n<td>\u81ea\u52a8\u91cd\u6574 memmoveDictionary&#xff08;MMKV_IO.cpp:1104&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u7a7a\u95f4\u5f52\u8fd8<\/td>\n<td>\u5929\u7136<\/td>\n<td>\u9700\u4e1a\u52a1\u8c03 trim()&#xff08;MMKV_IO.cpp:1413&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>ANR<\/td>\n<td>commit \u540c\u6b65&#xff1b;apply \u53d7 QueuedWork.waitToFinish() \u7275\u8fde<\/td>\n<td>\u65e0\u7cfb\u7edf\u8c03\u7528\u3001\u65e0\u7b49\u5f85\u961f\u5217&#xff08;\u89c1 Q2&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u591a\u8fdb\u7a0b<\/td>\n<td>MODE_MULTI_PROCESS \u5df2\u5e9f\u5f03\u4e14\u4e0d\u53ef\u9760<\/td>\n<td>flock &#043; meta \u4e09\u5143\u7ec4&#xff08;MMKV_IO.cpp:305&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u6389\u7535\/\u635f\u574f<\/td>\n<td>\u65e0\u6821\u9a8c&#xff0c;XML \u534a\u5199\u5373\u5168\u5e9f<\/td>\n<td>CRC32 &#043; lastConfirmed \u56de\u6eda &#043; \u8d2a\u5fc3\u6062\u590d&#xff08;MMKV_IO.cpp:230&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u52a0\u5bc6<\/td>\n<td>\u65e0<\/td>\n<td>AES-128-CFB&#xff0c;\u5bc6\u94a5\u4ec5\u5b58 native&#xff08;AESCrypt.h:57&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u5355\u6587\u4ef6\u5927\u5c0f<\/td>\n<td>\u65e0\u4e0a\u9650&#xff0c;\u6027\u80fd\u7ebf\u6027\u52a3\u5316<\/td>\n<td>\u9875\u7c92\u5ea6\u6307\u6570\u6269\u5bb9&#xff08;MMKV_IO.cpp:435&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>TTL<\/td>\n<td>\u65e0<\/td>\n<td>\u503c\u5c3e 4 \u5b57\u8282\u65f6\u95f4\u6233 &#043; filterExpiredKeys&#xff08;MMKV.cpp:461&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u4f9d\u8d56<\/td>\n<td>\u7cfb\u7edf\u5185\u7f6e<\/td>\n<td>\u9700 native so&#xff08;\u4f53\u79ef\u6210\u672c ~1MB \u5168 ABI&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u6027\u80fd\u5dee\u5f02\u7684\u6839\u6e90\u7528\u4e00\u53e5\u8bdd\u6982\u62ec&#xff1a;SP \u7684\u590d\u6742\u5ea6\u662f O(\u6574\u4e2a map)&#xff08;\u6bcf\u6b21\u843d\u76d8\u90fd\u8981\u5168\u91cf\u5e8f\u5217\u5316&#xff09;&#xff0c;MMKV \u7684\u590d\u6742\u5ea6\u662f O(\u5355\u6761\u8bb0\u5f55)\u3002\u5f53\u6570\u636e\u91cf\u5c0f\u7684\u65f6\u5019\u5dee\u522b\u4e0d\u660e\u663e&#xff0c;\u5f53 SharedPreferences \u91cc\u6709\u51e0\u5343\u4e2a key \u65f6&#xff0c;SP \u7684\u6bcf\u6b21 apply \u90fd\u8981\u91cd\u5199\u6574\u4e2a XML \u2014\u2014 \u8fd9\u5c31\u662f\u300c\u7528\u7740\u7528\u7740\u8d8a\u6765\u8d8a\u5361\u300d\u7684\u6570\u5b66\u539f\u56e0\u3002<\/p>\n<hr \/>\n<h3>14. \u9762\u8bd5\u9898\u6e90\u7801\u7ea7\u7cbe\u8bb2&#xff08;Q1\u2013Q8 &#043; \u8bef\u533a\u6e05\u5355&#xff09;<\/h3>\n<h4>Q1&#xff1a;MMKV \u4e3a\u4ec0\u4e48\u6bd4 SharedPreferences \u5feb&#xff1f;<\/h4>\n<p>\u7b54\u9898\u6846\u67b6&#xff1a;\u4e09\u5c42\u5404\u6709\u4e00\u4e2a\u6e90\u7801\u652f\u70b9&#xff0c;\u6700\u540e\u518d\u8865\u4e00\u5c42\u300c\u5f88\u591a\u4eba\u6f0f\u6389\u7684\u7b2c\u56db\u5c42\u300d\u3002<\/p>\n<li>\n<p>IO \u5c42&#xff1a;mmap \u6d88\u9664 write \u7cfb\u7edf\u8c03\u7528 Core\/MemoryFile.cpp:197&#xff1a;::mmap(m_ptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)\u3002\u5199\u5165 &#061; \u7528\u6237\u6001\u76f4\u63a5 memcpy \u5230\u5185\u6838\u6258\u7ba1\u7684 page cache \u9875&#xff0c;\u6ca1\u6709 write() \u7684\u7cfb\u7edf\u8c03\u7528\u5207\u6362\u3001\u6ca1\u6709\u7528\u6237\u6001\u5230\u5185\u6838\u6001\u7684\u90a3\u4e00\u6b21\u6570\u636e\u62f7\u8d1d\u3002\u843d\u76d8\u4ea4\u7ed9\u5185\u6838\u5f02\u6b65 writeback\u3002<\/p>\n<\/li>\n<li>\n<p>\u5e8f\u5217\u5316\u5c42&#xff1a;protobuf wire-format \u800c\u975e XML Core\/MiniPBCoder.cpp:506 \u7684\u7f16\u89e3\u7801\u5c31\u662f varint32 len &#043; bytes \u7684\u5e73\u94fa\u3002\u6ca1\u6709\u6807\u7b7e\u540d\u3001\u6ca1\u6709\u8f6c\u4e49\u3001\u6ca1\u6709 DOM\u3002Core\/CodedInputData.cpp:182 \u7684 readRawVarint32 \u662f\u624b\u5199\u7684\u79fb\u4f4d\u89e3\u7801\u3002<\/p>\n<\/li>\n<li>\n<p>\u5199\u5165\u7b56\u7565&#xff1a;\u589e\u91cf\u8ffd\u52a0\u800c\u975e\u5168\u91cf\u91cd\u5199&#xff08;\u590d\u6742\u5ea6\u5c42\u9762&#xff09; Core\/MMKV_IO.cpp:822 doAppendDataWithKey&#xff1a;\u5199\u6307\u9488\u5bf9 (m_output) \u4e0a memcpy \u4e00\u6761\u8bb0\u5f55&#xff0c;m_actualSize &#043;&#061; size&#xff0c;updateCRCDigest(ptr, size)\u3002\u5355\u6b21\u5199\u6210\u672c O(\u672c\u6b21\u8bb0\u5f55\u5927\u5c0f)&#xff0c;\u4e0e\u5df2\u6709\u6570\u636e\u91cf\u65e0\u5173\u3002 \u5bf9\u7167 SP&#xff1a;\u5355\u6b21\u5199\u6210\u672c O(\u5168\u90e8\u6570\u636e)\u3002<\/p>\n<\/li>\n<li>\n<p>\u5f88\u591a\u4eba\u6f0f\u6389\u7684\u7b2c\u56db\u5c42&#xff1a;\u7d22\u5f15\u5e38\u9a7b &#043; \u96f6\u62f7\u8d1d\u8bfb m_dic \u662f key \u2192 KeyValueHolder{keySize, valueSize, offset}&#xff08;Core\/KeyValueHolder.h:32&#xff09;&#xff0c;\u8bfb\u503c\u5c31\u662f MMBuffer(basePtr &#043; offset &#043; computedKVSize, valueSize, MMBufferNoCopy) \u2014\u2014 \u4e00\u6b21\u6307\u9488\u7b97\u672f&#xff0c;\u4e00\u6b21\u6784\u9020&#xff0c;\u4e0d\u62f7\u8d1d\u4e0d new\u3002SP \u7684\u5feb\u662f\u56e0\u4e3a\u5b83\u5728\u5185\u5b58\u91cc\u5b58\u4e86\u89e3\u6790\u597d\u7684\u5bf9\u8c61&#xff0c;MMKV \u7684\u5feb\u662f\u300c\u6570\u636e\u672c\u6765\u5c31\u5728\u5185\u5b58\u91cc&#xff0c;\u800c\u4e14\u4e0d\u9700\u8981\u89e3\u6790\u300d\u3002<\/p>\n<\/li>\n<li>\n<p>\u9526\u4e0a\u6dfb\u82b1&#xff1a;\u786c\u4ef6\u6307\u4ee4 Core\/MMKV.cpp:184 CRC32 &#061; mmkv::armv8_crc32&#xff1b;:172 \u8d77\u628a AES \u6362\u6210 ARMv8 \u6307\u4ee4\u3002\u6821\u9a8c\u548c\u52a0\u5bc6\u8fd9\u4e24\u4ef6\u300c\u989d\u5916\u6210\u672c\u300d\u88ab CPU \u6307\u4ee4\u6d88\u5316\u6389\u4e86\u3002<\/p>\n<\/li>\n<p>\u52a0\u5206\u70b9&#xff1a;MMKV \u5feb\u4e0d\u662f\u6ca1\u6709\u4ee3\u4ef7\u7684\u3002\u4ee3\u4ef7\u6709\u4e09&#xff1a;(a) \u8ffd\u52a0\u5f0f\u5199\u5165\u4f7f\u6587\u4ef6\u4ea7\u751f\u5783\u573e&#xff0c;\u9700\u8981\u91cd\u6574\u673a\u5236&#xff1b;(b) \u7d22\u5f15\u9700\u5e38\u9a7b\u5185\u5b58&#xff0c;m_dic \u4e0e\u6570\u636e\u662f\u4e24\u4efd\u7ed3\u6784&#xff1b;\u00a9 \u843d\u76d8\u7531\u5185\u6838\u638c\u63a7&#xff0c;\u56e0\u6b64\u300c\u5df2\u8fd4\u56de true\u300d\u2260\u300c\u5df2\u6301\u4e45\u5316\u5230\u95ea\u5b58\u300d&#xff0c;\u6389\u7535\u573a\u666f\u4e0d\u5982\u663e\u5f0f fsync\u3002<\/p>\n<h4>Q2&#xff1a;MMKV \u5982\u4f55\u89e3\u51b3 SharedPreferences \u7684 ANR \u95ee\u9898&#xff1f;<\/h4>\n<p>\u5148\u628a SP \u7684 ANR \u673a\u7406\u8bb2\u51c6&#xff08;\u8fd9\u91cc\u6700\u80fd\u533a\u5206\u80cc\u4e66\u548c\u771f\u61c2&#xff09;&#xff1a;<\/p>\n<ul>\n<li>commit()&#xff1a;QueuedWork.queue(awaitCommit&#061;true) \u2192 \u5f53\u524d\u7ebf\u7a0b\u540c\u6b65\u5199 XML&#xff1b;<\/li>\n<li>apply()&#xff1a;startWriteToDisk() \u5728 FileOutputStream.write() \u4e4b\u524d\u628a MemoryCommit \u5165\u961f sDiskWriteTasks&#xff0c;\u5199\u76d8\u5728 CachedThreadPoolExecutor \u5f02\u6b65\u6267\u884c&#xff1b;<\/li>\n<li>\u771f\u6b63\u7684\u5751&#xff1a;Activity.onStop() \/ Service.onStart() \u91cc QueuedWork.waitToFinish() \u2014\u2014 \u5b83 while (!sDiskWriteTasks.isEmpty()) { FutureTask f &#061; sDiskWriteTasks.take(); f.run(); }&#xff0c;\u540c\u6b65\u7b49\u5f85\u6240\u6709\u5f85\u5199\u7684 XML \u843d\u76d8\u3002\u4f4e\u7aef\u673a &#043; \u5927\u6570\u636e &#043; \u9891\u7e41\u5207\u540e\u53f0\u65f6&#xff0c;\u4e3b\u7ebf\u7a0b\u5c31\u5361\u6b7b\u5728\u8fd9\u91cc \u2192 ANR\u3002<\/li>\n<li>\u6240\u4ee5\u300capply \u662f\u5f02\u6b65\u7684\u6240\u4ee5\u4e0d\u4f1a ANR\u300d\u662f\u9519\u7684&#xff1a;apply \u628a\u6210\u672c\u5ef6\u540e\u5230\u4e86\u751f\u547d\u5468\u671f\u56de\u8c03\u4e0a\u3002<\/li>\n<\/ul>\n<p>MMKV \u4fa7\u4e3a\u4ec0\u4e48\u7ed3\u6784\u4e0a\u4e0d\u53ef\u80fd\u51fa\u73b0\u8fd9\u4e2a\u95ee\u9898&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:436  \u552f\u4e00\u7684&#034;\u843d\u76d8\u51c6\u5907&#034;\u52a8\u4f5c<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">updateCRCDigest<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">const<\/span> <span class=\"token keyword\">uint8_t<\/span> <span class=\"token operator\">*<\/span>ptr<span class=\"token punctuation\">,<\/span> size_t length<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    m_crcDigest <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token function\">CRC32<\/span><span class=\"token punctuation\">(<\/span>m_crcDigest<span class=\"token punctuation\">,<\/span> ptr<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">uint32_t<\/span><span class=\"token punctuation\">)<\/span> length<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">writeActualSize<\/span><span class=\"token punctuation\">(<\/span>m_actualSize<span class=\"token punctuation\">,<\/span> m_crcDigest<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">,<\/span> KeepSequence<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ \u2192 memcpy 8 \u5b57\u8282\u5230 mmap \u533a<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<li>\u6ca1\u6709\u300c\u5f85\u5199\u961f\u5217\u300d\u8fd9\u79cd\u4e1c\u897f\u3002encode() \u8fd4\u56de\u65f6&#xff0c;\u5b57\u8282\u5df2\u7ecf\u5728 mmap \u533a\u91cc\u4e86&#xff0c;\u6ca1\u6709\u4efb\u4f55\u4e1c\u897f\u7559\u7ed9\u540e\u53f0\u53bb\u505a&#xff0c;\u56e0\u6b64 \u4e0d\u5b58\u5728\u53ef\u4ee5\u88ab waitToFinish() \u7b49\u5f85\u7684 future&#xff1b;<\/li>\n<li>\u4e3b\u7ebf\u7a0b\u4e0d\u89e6\u53d1 write()\/fsync()&#xff0c;\u810f\u9875\u56de\u5199\u7531\u5185\u6838 writeback \u7ebf\u7a0b\u8d1f\u8d23&#xff0c;\u4e0e\u5e94\u7528\u7ebf\u7a0b\u5b8c\u5168\u89e3\u8026&#xff1b;<\/li>\n<li>MMKV \u91cc\u6ca1\u6709 onStop \u94a9\u5b50&#xff0c;\u4e5f\u4e0d\u53c2\u4e0e\u7ec4\u4ef6\u751f\u547d\u5468\u671f&#xff0c;\u56e0\u6b64\u4e0d\u4f1a\u6709\u300c\u751f\u547d\u5468\u671f\u5207\u6362\u65f6\u96c6\u4e2d flush\u300d\u7684\u6a21\u5f0f\u3002<\/li>\n<li>Android 8.1&#043; \u5df2\u7ecf\u6539\u7528 QueuedWork.beginDefer\/finishDefer &#043; \u751f\u547d\u5468\u671f\u611f\u77e5\u7f13\u89e3 SP \u7684\u8fd9\u4e2a\u95ee\u9898&#xff0c;\u4f46\u8fd9\u5c5e\u4e8e\u300c\u6253\u8865\u4e01\u300d&#xff1b;MMKV \u662f\u4ece\u6570\u636e\u7ed3\u6784\u4e0a\u6d88\u9664\u3002<\/li>\n<p>\u9700\u8981\u8001\u5b9e\u8bf4\u660e\u7684\u8fb9\u754c&#xff1a;mmap \u6d88\u9664\u7684\u662f\u300c\u540c\u6b65 IO \u7b49\u5f85\u300d&#xff0c;\u4f46\u6ca1\u6d88\u9664\u9875\u9519\u8bef\u3002\u9996\u6b21\u8bbf\u95ee\u672a fault-in \u7684\u6620\u5c04\u9875\u4f1a\u89e6\u53d1 minor fault&#xff1b;\u5982\u679c\u5185\u6838\u5df2\u628a\u8fd9\u4e9b\u5e72\u51c0\u9875\u56de\u6536&#xff0c;\u8bbf\u95ee\u65f6\u4f1a\u53d8\u6210 major fault&#xff08;\u9700\u8bfb\u76d8&#xff09;&#xff0c;\u6b64\u65f6\u4f9d\u7136\u53ef\u80fd\u5361\u4f4f\u4e3b\u7ebf\u7a0b \u2014\u2014 \u53ea\u662f\u6982\u7387\u4e0e\u65f6\u957f\u8fdc\u4f4e\u4e8e SP \u7684\u5168\u91cf XML \u91cd\u5199\u3002\u53e6\u5916 MemoryFile::truncate \u5185\u7684 zeroFillFile \u4e0e ftruncate \u662f \u771f\u7cfb\u7edf\u8c03\u7528&#xff0c;\u53d1\u751f\u5728\u5199\u8def\u5f84\u7684\u6269\u5bb9\u77ac\u95f4&#xff0c;\u5c5e\u4e8e MMKV \u552f\u4e00\u53ef\u89c1\u7684 IO \u5c16\u523a&#xff08;Core\/MMKV_IO.cpp:443&#xff09;\u3002<\/p>\n<h4>Q3&#xff1a;MMKV \u7684\u591a\u8fdb\u7a0b\u662f\u600e\u4e48\u5b9e\u73b0\u7684&#xff1f;\u4e3a\u4ec0\u4e48\u4e0d\u7528 ContentProvider&#xff1f;<\/h4>\n<p>\u7b54&#xff08;\u56db\u5c42\u9012\u8fdb&#xff09;&#xff1a;<\/p>\n<li>\u5171\u4eab\u8f7d\u4f53&#xff1a;\u6240\u6709\u8fdb\u7a0b mmap \u540c\u4e00\u4e2a\u78c1\u76d8\u6587\u4ef6&#xff08;Core\/MMKV.cpp:88&#xff0c;\u8def\u5f84\u7531 mappedKVPathWithID \u51b3\u5b9a&#xff09;\u3002\u56e0\u4e3a\u7528\u7684\u662f MAP_SHARED&#xff0c;\u5404\u8fdb\u7a0b\u770b\u5230\u7684\u662f\u540c\u4e00\u6279 page cache \u7269\u7406\u9875 \u2014\u2014 \u6570\u636e\u53ef\u89c1\u6027\u7531\u5185\u6838\u767d\u9001&#xff0c;\u4e0d\u9700\u8981\u4efb\u4f55 IPC\u3002<\/li>\n<li>\u4e92\u65a5&#xff1a;Core\/MMKV.cpp:93 m_fileLock(new FileLock(m_metaFile-&gt;getFd()))&#xff0c;\u8bfb\u5199\u5206\u522b\u7528 LOCK_SH\/LOCK_EX&#xff08;Core\/InterProcessLock.cpp:85-126&#xff09;\u3002\u9501\u52a0\u5728 .crc \u6587\u4ef6\u7684 fd \u4e0a&#xff0c;\u56e0\u4e3a\u90a3\u4e2a fd \u5168\u7a0b\u7a33\u5b9a&#xff0c;\u800c\u6570\u636e\u6587\u4ef6\u4f1a\u88ab\u53cd\u590d munmap\/mmap\u3002<\/li>\n<li>\u4e00\u81f4\u6027\u534f\u8bae&#xff08;\u6838\u5fc3&#xff09;&#xff1a;Core\/MMKV_IO.cpp:305 \u7684 checkLoadData()&#xff0c;\u5728 \u6bcf\u6b21\u8bfb\u5199\u5165\u53e3 \u6bd4\u5bf9 meta \u91cc\u7684 (m_sequence, m_crcDigest, actualSize\/fileSize) \u4e09\u5143\u7ec4&#xff0c;\u533a\u5206\u4e09\u79cd\u53d8\u66f4&#xff1a;\n<ul>\n<li>crcDigest \u53d8 &#043; \u6587\u4ef6\u5927\u5c0f\u4e0d\u53d8 \u2192 partialLoadFromFile() \u589e\u91cf CRC &#043; \u53ea\u89e3\u65b0\u589e\u6bb5 &#043; \u5199\u6307\u9488\u8ddf\u8fdb&#xff08;Core\/MMKV_IO.cpp:166-177&#xff09;&#xff1b;<\/li>\n<li>crcDigest \u53d8 &#043; \u6587\u4ef6\u5927\u5c0f\u53d8 \u2192 \u5168\u91cf\u91cd\u8f7d&#xff1b;<\/li>\n<li>sequence \u53d8 \u2192 \u522b\u7684\u8fdb\u7a0b\u505a\u4e86 fullWriteback&#xff0c;\u6240\u6709 offset \u5931\u6548&#xff0c;\u5fc5\u987b\u5168\u91cf\u91cd\u8f7d\u3002<\/li>\n<\/ul>\n<\/li>\n<li>\u4e3a\u4ec0\u4e48\u4e0d\u7528 ContentProvider&#xff1a;ContentProvider \u662f C\/S \u67b6\u6784&#xff0c;\u8bfb\u5199\u8981\u7ecf\u8fc7 Binder \u4e00\u6b21\u540c\u6b65\u4e8b\u52a1 &#043; Provider \u8fdb\u7a0b\u5fc5\u987b\u6d3b\u7740&#xff08;\u51b7\u542f\u52a8\u62c9\u8d77 &#061; \u6570\u767e ms&#xff09;\u3002MMKV \u4e00\u6b21 encode \u53ea\u662f\u4e24\u6b21 memcpy&#xff0c;\u8d70 Binder \u7684\u8bdd\u5149\u4e0a\u4e0b\u6587\u5207\u6362\u5c31\u6162\u4e24\u4e2a\u6570\u91cf\u7ea7\u3002\u800c\u4e14 ContentProvider \u65e0\u6cd5\u63d0\u4f9b\u300c\u591a\u4e2a\u8fdb\u7a0b\u76f4\u63a5\u770b\u5230\u540c\u4e00\u5757\u5185\u5b58\u300d\u7684\u80fd\u529b&#xff0c;\u4ecd\u7136\u8981\u4e00\u6b21\u6570\u636e\u642c\u8fd0\u3002<\/li>\n<li>flock \u7684 robust \u6027&#xff1a;flock \u9501\u5728 open file description \u4e0a&#xff0c;\u8fdb\u7a0b\u88ab kill -9 \u65f6\u5185\u6838\u5173 fd \u81ea\u52a8\u653e\u9501&#xff0c;\u4e0d\u4f1a\u7559\u4e0b\u6c38\u4e45\u6b7b\u9501&#xff08;fcntl \u8bb0\u5f55\u9501\u5728\u8fdb\u7a0b\/\u7ebf\u7a0b\u4e0e fd \u5173\u7cfb\u4e0a\u8bed\u4e49\u66f4\u590d\u6742&#xff0c;\u5bb9\u6613\u8bef\u91ca\u653e&#xff09;\u3002\u552f\u4e00\u4f8b\u5916\u662f ashmem&#xff0c;\u9000\u5316\u6210 fcntl&#xff08;Core\/InterProcessLock_Android.cpp:47&#xff09;\u3002<\/li>\n<h4>\u3010\u7ea0\u504f\u3011\u4e09\u4e2a\u5fc5\u987b\u6f84\u6e05\u7684\u70b9<\/h4>\n<li>\u300c\u5199\u6307\u9488\u540c\u6b65\u66f4\u65b0\u5230 mmap \u5185\u5b58\u4e2d\u7684\u5168\u5c40\u6307\u9488\u300d\u4e0d\u51c6\u786e\u3002 \u5168\u5c40\u53ef\u89c1\u7684\u300c\u5199\u6307\u9488\u300d\u5176\u5b9e\u5728 .crc \u5143\u6587\u4ef6\u7684 m_actualSize \u5b57\u6bb5&#xff0c;\u4e0d\u662f\u6570\u636e\u6587\u4ef6\u91cc\u7684\u4e00\u4e2a\u53d8\u91cf\u3002\u6570\u636e\u6587\u4ef6\u5934\u90a3 4 \u5b57\u8282 actualSize \u53ea\u662f\u964d\u7ea7\u517c\u5bb9&#xff08;Core\/MMKV_IO.cpp:473 oldStyleWriteActualSize&#xff09;&#xff0c;\u6743\u5a01\u503c\u5728 meta\u3002<\/li>\n<li>\u5e93\u91cc\u786e\u5b9e\u6709 MMKVContentProvider.java&#xff0c;\u4f46\u5b83\u4e0e\u591a\u8fdb\u7a0b\u540c\u6b65\u65e0\u5173\u3002 \u5b83\u53ea\u4e3a mmkvWithAshmemID() \u7684 \u8de8\u5e94\u7528\u5171\u4eab \u4f20\u4e00\u4e2a ashmem fd&#xff08;\u914d ParcelableMMKV&#xff0c;MMKV.java:545-546&#xff09;\u3002\u8bf4\u300cMMKV \u4e0d\u7528 ContentProvider\u300d\u65f6\u8981\u9650\u5b9a\u8303\u56f4&#xff1a;\u6570\u636e\u540c\u6b65\u8def\u5f84\u4e0d\u7528\u3002<\/li>\n<li>\u300c\u591a\u8fdb\u7a0b\u6a21\u5f0f\u4e0b\u652f\u6301 override \u539f\u5730\u8986\u76d6\u300d\u662f\u9519\u7684\u3002 Core\/MMKV_IO.cpp:691 \u5199\u6b7b\u4e86 bool onlyOneKey &#061; !m_isInterProcess &amp;&amp; m_dic-&gt;size() &#061;&#061; 1;&#xff0c;\u591a\u8fdb\u7a0b\u4e00\u5f8b\u8d70 append\u3002<\/li>\n<p>\u52a0\u5206\u70b9&#xff1a;MMKV \u7684\u591a\u8fdb\u7a0b\u4e0d\u662f\u300c\u5b9e\u65f6\u300d\u7684\u3002 \u4e00\u81f4\u6027\u53ea\u5728\u672c\u8fdb\u7a0b\u4e3b\u52a8\u8c03 checkLoadData() \u65f6\u5237\u65b0&#xff0c;notifyContentChanged&#xff08;Core\/MMKV.cpp:283&#xff09;\u4e5f\u53ea\u5728\u8bfb\u5199\u8def\u5f84\u4e0a\u89e6\u53d1\u3002\u5b98\u65b9 Javadoc \u8bf4\u5f97\u5f88\u6e05\u695a&#xff08;MMKV.java:1618&#xff09;\u3002\u8981\u505a\u300c\u914d\u7f6e\u53d8\u66f4\u5373\u65f6\u751f\u6548\u300d&#xff0c;\u5f97\u81ea\u5df1\u8f6e\u8be2 checkContentChangedByOuterProcess()&#xff08;MMKV.java:1647&#xff09;\u6216\u53e6\u52a0\u5e7f\u64ad\u3002<\/p>\n<h4>Q4&#xff1a;mmap \u4f1a\u4e0d\u4f1a\u5bfc\u81f4\u5185\u5b58\u6cc4\u6f0f&#xff1f;MMKV \u600e\u4e48\u7ba1\u7406\u5b9e\u4f8b\u5185\u5b58&#xff1f;<\/h4>\n<p>\u5148\u7834\u9898&#xff1a;mmap \u672c\u8eab\u4e0d\u4f1a\u300c\u6cc4\u6f0f\u300d&#xff0c;\u4f46\u4f1a \u957f\u671f\u5360\u7528\u865a\u62df\u5730\u5740\u7a7a\u95f4 \u5e76\u8ba9\u5bf9\u5e94\u7269\u7406\u9875\u7559\u5728 page cache \u4e2d&#xff0c;\u6240\u4ee5\u300cMMKV \u5b9e\u4f8b\u5f00\u5f97\u8d8a\u591a&#xff0c;\u5360\u7528\u8d8a\u5927\u300d\u662f\u4e8b\u5b9e\u3002\u771f\u6b63\u7684\u95ee\u9898\u662f&#xff1a;\u8fd9\u4e9b\u6620\u5c04\u4ec0\u4e48\u65f6\u5019\u88ab\u91ca\u653e&#xff1f;<\/p>\n<p>\u6e90\u7801\u4e8b\u5b9e&#xff08;v1.3.16&#xff09;&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:60<\/span><br \/>\nunordered_map<span class=\"token operator\">&lt;<\/span>string<span class=\"token punctuation\">,<\/span> MMKV <span class=\"token operator\">*<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token operator\">*<\/span>g_instanceDic<span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:257  \u521b\u5efa\u5373\u6c38\u4e45\u7f13\u5b58<\/span><br \/>\n<span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>g_instanceDic<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">[<\/span>mmapKey<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> kv<span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKV.cpp:262  \u552f\u4e00\u7684\u6279\u91cf\u91ca\u653e\u5165\u53e3<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MMKV<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">onExit<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">SCOPED_LOCK<\/span><span class=\"token punctuation\">(<\/span>g_instanceLock<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">auto<\/span> <span class=\"token operator\">&amp;<\/span>pair <span class=\"token operator\">:<\/span> <span class=\"token operator\">*<\/span>g_instanceDic<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        pair<span class=\"token punctuation\">.<\/span>second<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">sync<\/span><span class=\"token punctuation\">(<\/span>MMKV_SYNC<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        pair<span class=\"token punctuation\">.<\/span>second<span class=\"token operator\">-&gt;<\/span><span class=\"token function\">clearMemoryCache<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">delete<\/span> pair<span class=\"token punctuation\">.<\/span>second<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">delete<\/span> g_instanceDic<span class=\"token punctuation\">;<\/span><br \/>\n    g_instanceDic <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Core\/MemoryFile.cpp:248<\/span><br \/>\n<span class=\"token keyword\">void<\/span> <span class=\"token class-name\">MemoryFile<\/span><span class=\"token double-colon punctuation\">::<\/span><span class=\"token function\">doCleanMemoryCache<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">bool<\/span> forceClean<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>m_ptr <span class=\"token operator\">&amp;&amp;<\/span> m_ptr <span class=\"token operator\">!&#061;<\/span> MAP_FAILED<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">munmap<\/span><span class=\"token punctuation\">(<\/span>m_ptr<span class=\"token punctuation\">,<\/span> m_size<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">!&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    m_ptr <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">nullptr<\/span><span class=\"token punctuation\">;<\/span>   <span class=\"token comment\">\/\/ \u968f\u540e File::close()\u3001m_size &#061; 0<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h4>\u3010\u7ea0\u504f\u3011\u300cMMKV \u5bf9\u5b9e\u4f8b\u91c7\u7528 LRU \u7f13\u5b58\u6dd8\u6c70\u300d\u2014\u2014 \u6e90\u7801\u4e2d\u4e0d\u5b58\u5728<\/h4>\n<p>v1.3.16 \u6ca1\u6709\u4efb\u4f55 LRU&#xff1a;\u5bb9\u5668\u662f\u88f8 unordered_map&#xff0c;\u65e0\u8bbf\u95ee\u8ba1\u6570\u3001\u65e0\u6dd8\u6c70\u961f\u5217\u3002\u91ca\u653e\u6620\u5c04\u7684\u65f6\u673a\u53ea\u6709\u4e09\u4e2a&#xff1a;<\/p>\n<li>MMKV.onExit()&#xff08;Core\/MMKV.cpp:262&#xff0c;\u5bf9\u5e94 Java MMKV.java:317 \u7684 public static native void onExit()&#xff09;\u2014\u2014 \u901a\u5e38 App \u9000\u51fa\u65f6\u8c03\u4e00\u6b21&#xff1b;<\/li>\n<li>MMKV.clearMemoryCache(mmapID) \/ \u5b9e\u4f8b\u7248&#xff08;Core\/MMKV.cpp:302&#xff09;\u2014\u2014 \u4e1a\u52a1\u663e\u5f0f\u8c03\u7528&#xff1b;<\/li>\n<li>MemoryFile::truncate() \u5185\u90e8\u7684\u4e34\u65f6 munmap&#xff08;Core\/MemoryFile.cpp:173&#xff09;\u2014\u2014 \u4e3a\u91cd\u65b0\u6620\u5c04&#xff0c;\u4e0d\u662f\u91ca\u653e\u3002<\/li>\n<p>\u90a3 MMKV \u4e3a\u4ec0\u4e48\u6562\u4e0d\u505a\u6dd8\u6c70&#xff1f; \u56e0\u4e3a MAP_SHARED \u7684\u6587\u4ef6\u6620\u5c04\u9875\u5c5e\u4e8e page cache&#xff08;file-backed clean\/dirty page&#xff09;&#xff1a;\u5185\u5b58\u7d27\u5f20\u65f6\u5185\u6838\u53ef\u4ee5\u76f4\u63a5\u4e22\u5f03\u5e72\u51c0\u9875&#xff08;\u4e0b\u6b21\u8bbf\u95ee\u518d\u8bfb\u56de&#xff09;&#xff0c;\u4e0d\u9700\u8981 MMKV \u81ea\u5df1\u7ba1\u3002\u4e5f\u5c31\u662f\u8bf4 mmap \u7684 RSS \u662f&#034;\u53ef\u56de\u6536&#034;\u7684&#xff0c;\u4e0e Java \u5806\u91cc\u7684\u5f3a\u5f15\u7528\u5bf9\u8c61\u5b8c\u5168\u4e0d\u662f\u4e00\u4e2a\u6027\u8d28\u3002<\/p>\n<p>\u6b63\u786e\u7684\u98ce\u9669\u8868\u8ff0&#xff1a;MMKV \u7684\u5e38\u9a7b\u6210\u672c\u4e3b\u8981\u662f \u2460 m_dic \u8fd9\u5f20 \u771f\u00b7\u8fdb\u7a0b\u5185\u5185\u5b58 \u7684\u54c8\u5e0c\u8868&#xff08;\u6bcf\u6761 12 \u5b57\u8282 holder &#043; string key &#043; \u6876\u5f00\u9500&#xff09;&#xff0c;\u2461 \u6bcf\u4e2a\u5b9e\u4f8b\u4e00\u5bf9 fd\u3002\u5b9e\u4f8b\u6570\u5931\u63a7\u65f6&#xff0c;\u2460\u624d\u662f\u4e3b\u8981\u5185\u5b58\u538b\u529b\u6e90\u3002\u56e0\u6b64\u89c4\u7ea6\u662f&#xff1a;mmapID \u5fc5\u987b\u6709\u9650\u53ef\u679a\u4e3e&#xff0c;\u7edd\u4e0d\u8981\u7528\u7528\u6237 ID \/ \u65e5\u671f\u4e4b\u7c7b\u65e0\u754c\u5b57\u7b26\u4e32\u5f53 mmapID\u3002<\/p>\n<p>Context \u6cc4\u6f0f&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ MMKV.java:91<\/span><br \/>\n<span class=\"token keyword\">public<\/span> <span class=\"token keyword\">static<\/span> <span class=\"token class-name\">String<\/span> <span class=\"token function\">initialize<\/span><span class=\"token punctuation\">(<\/span><span class=\"token annotation punctuation\">&#064;NonNull<\/span> <span class=\"token class-name\">Context<\/span> context<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token class-name\">String<\/span> rootDir <span class=\"token operator\">&#061;<\/span> context<span class=\"token punctuation\">.<\/span><span class=\"token function\">getFilesDir<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">getPath<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#043;<\/span> <span class=\"token string\">&#034;\/mmkv&#034;<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h4>\u3010\u7ea0\u504f\u3011\u300cMMKV \u901a\u8fc7\u5f31\u5f15\u7528\u5173\u8054 Context\u300d\u2014\u2014 \u4e0d\u5b58\u5728<\/h4>\n<p>MMKV.java \u91cc\u6ca1\u6709 WeakReference&lt;Context&gt;\u3002initialize \u53ea \u540c\u6b65\u8bfb\u53d6 getFilesDir() \/ getCacheDir() \u4e24\u4e2a\u5b57\u7b26\u4e32\u5c31\u518d\u65e0\u5173\u7cfb&#xff1b;MMKV \u5b9e\u4f8b\u672c\u8eab \u4e0d\u6301\u6709 Context \u5b57\u6bb5\u3002\u6240\u4ee5 MMKV \u4e0d\u6cc4\u6f0f Activity \u7684\u539f\u56e0\u662f\u300c\u538b\u6839\u4e0d\u5f15\u7528\u300d&#xff0c;\u800c\u4e0d\u662f\u300c\u5f31\u5f15\u7528\u300d\u3002<\/p>\n<p>\u552f\u4e00\u8981\u7559\u610f\u7684\u662f \u4f60\u81ea\u5df1\u7684 MMKVHandler \/ MMKVContentChangeNotification \u5b9e\u73b0&#xff1a;MMKV.java:1614 \u7684 gContentChangeNotify \u662f \u9759\u6001\u5f3a\u5f15\u7528&#xff0c;\u5982\u679c\u4f60\u5728\u91cc\u9762\u6301\u6709 Activity&#xff0c;\u90a3\u5c31\u7531\u4f60\u8d1f\u8d23\u6cc4\u6f0f \u2014\u2014 \u8fd9\u662f\u771f\u5b9e\u7684\u8e29\u5751\u70b9\u3002<\/p>\n<p>\u5176\u4ed6\u8d44\u6e90&#xff1a; MMKV Parcelable \u7684 mCreators&#xff08;MMKV.java:907&#xff09;\u662f\u9759\u6001 HashMap&lt;String, Parcelable.Creator&lt;?&gt;&gt;&#xff0c;\u7f13\u5b58\u53cd\u5c04\u5f97\u5230\u7684 CREATOR&#xff0c;\u5c5e\u6709\u754c\u7f13\u5b58&#xff08;key \u662f\u7c7b\u540d&#xff09;&#xff0c;\u4f46\u4e25\u683c\u8bf4\u5b83\u6ca1\u6709\u4e0a\u9650&#xff1b;checkedHandleSet&#xff08;MMKV.java:57&#xff09;\u540c\u7406&#xff0c;\u5143\u7d20\u6570\u91cf\u7b49\u4e8e\u5b9e\u4f8b\u6570&#xff0c;onExit \u624d\u6e05\u3002<\/p>\n<h4>Q5&#xff1a;MMKV \u7684\u6570\u636e\u5b89\u5168\u6027\u5982\u4f55\u4fdd\u8bc1&#xff1f;<\/h4>\n<p>\u7b54\u9898\u7ed3\u6784&#xff1a;\u5199\u5165\u539f\u5b50\u6027 \u2192 \u68c0\u6d4b \u2192 \u6062\u590d \u2192 \u52a0\u5bc6&#xff0c;\u56db\u5c42&#xff0c;\u9010\u5c42\u7ed9\u6e90\u7801\u3002<\/p>\n<p>\u2460 \u5199\u5165\u7684\u300c\u539f\u5b50\u6027\u300d\u6765\u81ea\u9875\u5bf9\u9f50 &#043; \u53cc\u6587\u4ef6\u5206\u79bb<\/p>\n<p><span class=\"token comment\">\/\/ Core\/MMKVMetaInfo.hpp:94<\/span><br \/>\n<span class=\"token keyword\">static_assert<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span>MMKVMetaInfo<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;&#061;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token number\">4<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">1024<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;MMKVMetaInfo lager than one pagesize&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>\u8d26\u672c&#xff08;\u957f\u5ea6\u3001CRC\u3001IV\u3001sequence&#xff09;\u5355\u72ec\u653e .crc \u6587\u4ef6&#xff0c;\u4e14\u6574\u4e2a\u7ed3\u6784 \u2264 1 \u9875\u3002\u6570\u636e\u6587\u4ef6\u7684\u8ffd\u52a0\u53ea\u589e\u52a0 actualSize&#xff0c;\u53ea\u8981\u8d26\u672c\u6ca1\u5199\u6210\u529f&#xff0c;\u591a\u51fa\u6765\u7684\u5b57\u8282\u5c31\u81ea\u52a8\u4e0d\u88ab\u627f\u8ba4\u3002\u8fd9\u662f MMKV \u6297\u300c\u5199\u4e00\u534a\u5d29\u6e83\u300d\u7684\u6839\u672c\u8bbe\u8ba1&#xff1a;\u628a&#034;\u63d0\u4ea4\u70b9&#034;\u6536\u655b\u5230\u4e00\u9875\u4ee5\u5185\u7684\u5bf9\u9f50\u5199\u3002<\/p>\n<p>\u2461 \u68c0\u6d4b&#xff1a;CRC32<\/p>\n<p>Core\/MMKV.cpp:405 \u5168\u91cf\u6821\u9a8c\u3001:436 \u589e\u91cf\u7eed\u7b97\u3002\u6821\u9a8c\u8303\u56f4\u662f ptr &#043; Fixed32Size \u8d77\u3001\u957f\u5ea6 actualSize \u7684\u6570\u636e\u533a&#xff0c;\u5373 \u6240\u6709 KV \u8bb0\u5f55\u7684\u5b57\u8282\u6d41\u3002\u540c\u65f6 Core\/MMKV_IO.cpp:272 \u8fd8\u68c0\u67e5 actualSize &lt; fileSize&#xff08;\u957f\u5ea6\u5408\u7406\u6027&#xff09;\u4e0e Core\/MMKV_IO.cpp:205 \u7684 meta \u7248\u672c\u54e8\u5175\u3002<\/p>\n<p>\u2462 \u6062\u590d&#xff1a;\u4e09\u7ea7\u964d\u7ea7 &#043; \u8d2a\u5fc3\u89e3\u7801 &#043; \u4e1a\u52a1\u51b3\u7b56<\/p>\n<table>\n<tr>\u7ea7\u522b\u4f4d\u7f6e\u624b\u6bb5<\/tr>\n<tbody>\n<tr>\n<td>L1<\/td>\n<td>MMKV_IO.cpp:273<\/td>\n<td>\u6b63\u5e38 CRC \u5339\u914d<\/td>\n<\/tr>\n<tr>\n<td>L2<\/td>\n<td>MMKV_IO.cpp:237-246<\/td>\n<td>\u964d\u7ea7\/\u5347\u7ea7\u517c\u5bb9&#xff1a;\u7528\u6587\u4ef6\u5934 oldStyleActualSize \u91cd\u9a8c<\/td>\n<\/tr>\n<tr>\n<td>L3<\/td>\n<td>MMKV_IO.cpp:253-258<\/td>\n<td>\u56de\u9000\u5230 m_lastConfirmedMetaInfo&#xff08;\u4e0a\u6b21\u91cd\u6574\/\u6e05\u7a7a\u7684\u5feb\u7167&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>L4<\/td>\n<td>MMKV_IO.cpp:279\/293<\/td>\n<td>\u95ee MMKVHandler&#xff0c;OnErrorRecover \u2192 needFullWriteback &#061; true<\/td>\n<\/tr>\n<tr>\n<td>L5<\/td>\n<td>MMKV_IO.cpp:110<\/td>\n<td>greedyDecodeMap&#xff1a;\u53ea\u62a2\u6551\u635f\u574f\u70b9\u4e4b\u524d\u80fd\u89e3\u6790\u7684\u8bb0\u5f55&#xff0c;\u968f\u540e\u7acb\u5373 fullWriteback \u56fa\u5316<\/td>\n<\/tr>\n<tr>\n<td>L6<\/td>\n<td>MMKV_IO.cpp:133<\/td>\n<td>OnErrorDiscard \u2192 writeActualSize(0,0,&#8230;) \u6574\u4e2a\u6587\u4ef6\u4f5c\u5e9f&#xff0c;\u4e1a\u52a1\u53ef\u91cd\u6765<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>greedy vs \u975e greedy \u7684\u5b9e\u73b0\u5dee\u5f02\u5728 Core\/MiniPBCoder.cpp:530-548&#xff1a;\u975e\u8d2a\u5fc3\u5148\u5199 tmpDic \u518d dic.swap(tmpDic)&#xff08;\u5168\u6709\u6216\u5168\u65e0&#xff09;&#xff1b;\u8d2a\u5fc3\u76f4\u63a5\u5199\u76ee\u6807\u5b57\u5178&#xff08;\u5c3d\u529b\u800c\u4e3a&#xff09;\u3002<\/p>\n<p>\u2463 \u52a0\u5bc6&#xff1a;AES-128-CFB &#043; \u968f\u673a IV &#043; \u957f\u5ea6\u4f2a\u88c5<\/p>\n<p>\u89c1\u7b2c 11 \u7ae0\u3002\u5bc6\u94a5\u53ea\u5728 native \u5806&#xff08;AESCrypt.cpp:51 memcpy(m_key, &#8230;)&#xff09;&#xff0c;\u6bcf\u6b21\u91cd\u6574\u6362 IV&#xff08;MMKV_IO.cpp:1479&#xff09;&#xff0c;\u6587\u4ef6\u5934\u957f\u5ea6\u5b57\u6bb5\u968f\u673a\u5316&#xff08;AESCrypt.cpp:33&#xff09;\u3002<\/p>\n<h4>\u3010\u7ea0\u504f\u3011\u300c\u5199\u65f6\u590d\u5236&#xff1a;\u4fee\u6539\u65f6\u521b\u5efa\u65b0\u5185\u5b58\u9875&#xff0c;\u907f\u514d\u5199\u5165\u5d29\u6e83\u635f\u574f\u539f\u6709\u6570\u636e\u300d\u2014\u2014 \u4e0d\u6210\u7acb<\/h4>\n<li>MemoryFile.cpp:197 \u7528\u7684\u662f MAP_SHARED&#xff0c;COW \u5bf9\u5e94\u7684\u662f MAP_PRIVATE\u3002\u7528 MAP_PRIVATE \u7684\u8bdd\u5199\u5165\u6839\u672c\u4e0d\u843d\u76d8&#xff0c;\u591a\u8fdb\u7a0b\u4e5f\u4e0d\u5171\u4eab \u2014\u2014 \u4e0e MMKV \u7684\u7acb\u8eab\u4e4b\u672c\u76f4\u63a5\u77db\u76fe\u3002<\/li>\n<li>\u5168\u5e93\u6ca1\u6709\u4efb\u4f55\u300c\u4e3a\u4fee\u6539\u800c\u5206\u914d\u65b0\u9875\/\u65b0\u6587\u4ef6\u300d\u7684\u903b\u8f91\u3002\u5199\u5165\u5c31\u662f\u5f80 m_output \u5f53\u524d\u4f4d\u7f6e memcpy\u3002<\/li>\n<li>\u771f\u5b9e\u7684\u6297\u5d29\u6e83\u673a\u5236\u662f&#xff1a;\u2460\u8d26\u672c\u9875\u539f\u5b50\u5199 &#043; \u2461CRC \u6821\u9a8c &#043; \u2462lastConfirmed \u56de\u6eda\u70b9 &#043; \u2463\u8d2a\u5fc3\u89e3\u7801\u3002\u5b83\u5141\u8bb8\u300c\u6700\u540e\u51e0\u6761\u8bb0\u5f55\u53ef\u80fd\u4e22\u300d&#xff0c;\u4f46\u4fdd\u8bc1\u300c\u4e0d\u4f1a\u8bfb\u5230\u5783\u573e\u3001\u4e0d\u4f1a\u6574\u4f53\u635f\u574f\u300d\u3002<\/li>\n<p>\u552f\u4e00\u6cbe\u8fb9\u300c\u590d\u5236\u300d\u7684\u5730\u65b9\u662f mmkv::copyFile()&#xff08;Core\/MemoryFile.cpp&#xff09;\u7528 mkstemp \u4e34\u65f6\u6587\u4ef6 &#043; tryAtomicRename \u505a \u539f\u5b50\u66ff\u6362&#xff0c;\u4f46\u90a3\u670d\u52a1\u4e8e backupTo() \u7b49\u6587\u4ef6\u7ea7\u64cd\u4f5c&#xff0c;\u4e0d\u662f\u5e38\u89c4\u5199\u8def\u5f84\u3002<\/p>\n<p>\u5fc5\u987b\u8865\u5145\u7684\u8bda\u5b9e\u8fb9\u754c&#xff08;\u8bf4\u51fa\u6765\u624d\u663e\u4e13\u4e1a&#xff09;&#xff1a;<\/p>\n<ul>\n<li>mmap \u4e0d\u4fdd\u8bc1\u6389\u7535\u5b89\u5168\u3002encode() \u8fd4\u56de true \u53ea\u4fdd\u8bc1\u300c\u5199\u8fdb\u4e86 page cache\u300d\u3002\u771f\u6389\u7535\u65f6\u672a\u56de\u5199\u7684\u810f\u9875\u4f1a\u4e22\u3002\u8981\u66f4\u5f3a\u4fdd\u8bc1\u5fc5\u987b MMKV.sync(MMKV_SYNC)&#xff08;Core\/MMKV.cpp:1169 \u2192 msync(MS_SYNC)&#xff09;&#xff0c;\u6216\u5728\u5173\u952e\u5199\u4e4b\u540e\u8c03\u5b83\u3002<\/li>\n<li>\u56e0\u6b64\u300c\u6570\u636e\u96f6\u4e22\u5931\u300d\u7684\u6b63\u786e\u8bf4\u6cd5\u662f&#xff1a;\u8fdb\u7a0b\u5d29\u6e83\u4e0d\u4e22&#xff08;\u5185\u6838\u4ecd\u6301\u6709\u810f\u9875\u5e76\u7ee7\u7eed\u56de\u5199&#xff09;&#xff0c;\u6781\u7aef\u6389\u7535\u53ef\u80fd\u6709\u79d2\u7ea7\u7a97\u53e3\u5185\u7684\u4e22\u5931&#xff0c;\u4e14 CRC \u673a\u5236\u4fdd\u8bc1 \u4e22\u7684\u662f\u4e00\u81f4\u6027\u53ef\u68c0\u6d4b\u7684\u5c3e\u90e8&#xff0c;\u800c\u4e0d\u662f\u6574\u5e93\u635f\u574f\u3002<\/li>\n<\/ul>\n<h4>Q6&#xff1a;MMKV \u7684\u6587\u4ef6\u4f1a\u65e0\u9650\u589e\u957f\u5417&#xff1f;<\/h4>\n<p>\u4e0d\u4f1a&#xff0c;\u4f46\u8981\u5206\u6e05\u4e09\u4ef6\u4e8b&#xff1a;\u5783\u573e\u56de\u6536 \u2260 \u7a7a\u95f4\u5f52\u8fd8\u3002<\/p>\n<p>\u6587\u4ef6\u5927\u5c0f\u66f2\u7ebf&#xff08;\u540c\u4e00\u5b9e\u4f8b&#xff0c;\u9ad8\u9891\u66f4\u65b0 100 \u4e2a key&#xff09;&#xff1a;<\/p>\n<p>size<br \/>\n \u2502            \u2571\u2572          \u2571\u2572<br \/>\n \u2502        \u2571\u2572 \u2571  \u2572      \u2571\u2572 \u2571  \u2572        \u2190 \u7ffb\u500d\u6269\u5bb9<br \/>\n \u2502    \u2571\u2572 \u2571  \u2572__  \u2572__\u2571\u2572\u2571   \u2572__  \u2572__<br \/>\n \u2502  \u2571  \u2572__                    \u2572__<br \/>\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\u2500\u2500\u2500\u2192 time<br \/>\n   append \u586b\u5145   \u91cd\u6574(memmove)   \u6269\u5bb9<\/p>\n<li>\u5783\u573e\u7684\u4ea7\u751f&#xff1a;\u6bcf\u6b21\u66f4\u65b0\/\u5220\u9664\u90fd\u8ffd\u52a0\u4e00\u6761\u8bb0\u5f55&#xff08;Core\/MMKV_IO.cpp:822&#xff09;&#xff0c;\u65e7\u8bb0\u5f55\u7559\u5728\u539f\u5730&#xff1b;m_hasFullWriteback \u88ab\u7f6e false&#xff08;:~756 \u9644\u8fd1&#xff0c;\u51fd\u6570\u5c3e\u90e8&#xff09;\u3002<\/li>\n<li>\u89e6\u53d1\u56de\u6536&#xff1a;ensureMemorySize() \u53d1\u73b0 newSize &gt;&#061; m_output-&gt;spaceLeft()&#xff08;Core\/MMKV_IO.cpp:408&#xff09;\u2192 prepareEncode &#043; expandAndWriteBack \u2192 doFullWriteBack \u2192 memmoveDictionary&#xff08;Core\/MMKV_IO.cpp:1104&#xff09;\u6309 offset \u6392\u5e8f\u3001\u5408\u5e76\u76f8\u90bb\u6bb5\u3001memmove \u5230\u5934\u90e8&#xff0c;\u53ea\u642c\u6709\u6548\u6570\u636e\u3002<\/li>\n<li>\u4e0d\u91cd\u65b0\u5e8f\u5217\u5316\u7684\u5173\u952e&#xff1a;prepareEncode&#xff08;Core\/MMKV_IO.cpp:350&#xff09;\u7528 holder \u91cc\u7684 computedKVSize \u7eaf\u7b97\u672f\u7b97\u51fa totalSize&#xff0c;assert(writtenSize &#061;&#061; totalSize)&#xff08;:1154&#xff09;\u81ea\u8bc1\u3002\u91cd\u6574\u7684 CPU \u6210\u672c\u662f memmove \u800c\u4e0d\u662f encode\u3002<\/li>\n<li>\u6269\u5bb9\u5224\u636e\u5e26\u300c\u672a\u6765\u9884\u7559\u300d&#xff1a;futureUsage &#061; avgItemSize * max(8, laterDicCount\/2)&#xff0c;do { fileSize *&#061; 2; } while (lenNeeded &#043; futureUsage &gt;&#061; fileSize)&#xff08;Core\/MMKV_IO.cpp:430-437&#xff09;\u3002\u6240\u4ee5\u589e\u957f\u662f \u6307\u6570\u644a\u8fd8 \u7684&#xff0c;\u4e0d\u4f1a\u6bcf\u5199\u51e0\u6761\u5c31 ftruncate \u4e00\u6b21\u3002<\/li>\n<li>\u4e0a\u9650&#xff1a;MMKV \u5355\u6587\u4ef6\u9ed8\u8ba4\u521d\u59cb DEFAULT_MMAP_SIZE&#xff08;&#061; 1 \u9875&#xff0c;4KB&#xff09;&#xff0c;\u53ef\u7ecf mmkvWithID(&#8230;, expectedCapacity)&#xff08;MMKV.java:379&#xff09;\u9884\u5206\u914d\u907f\u5f00\u9996\u8f6e\u591a\u6b21\u6269\u5bb9\u3002<\/li>\n<li>\u7f29\u5bb9\u9700\u663e\u5f0f\u8c03\u7528&#xff1a;trim()&#xff08;Core\/MMKV_IO.cpp:1413&#xff09;fullWriteback() \u4e4b\u540e while (fileSize &gt; (m_actualSize &#043; Fixed32Size) * 2) fileSize \/&#061; 2&#xff0c;\u518d truncate\u3002<\/li>\n<p>\u4e00\u53e5\u8bdd\u7b54&#xff1a;\u903b\u8f91\u7a7a\u95f4\u4f1a\u81ea\u52a8\u56de\u6536&#xff08;\u91cd\u6574&#xff09;&#xff0c;\u78c1\u76d8\u5360\u7528\u4f1a\u81ea\u52a8\u644a\u8fd8\u589e\u957f\u4f46\u4e0d\u4f1a\u81ea\u52a8\u7f29\u56de&#xff1b;\u8981\u5f52\u8fd8\u78c1\u76d8\u5fc5\u987b\u8c03 trim()\u3002<\/p>\n<p>\u987a\u5e26\u7ea0\u6b63\u4e00\u4e2a\u8bf4\u6cd5&#xff1a;\u300c\u4ec5\u5728\u7a7a\u95f4\u8fbe\u5230\u9608\u503c\u65f6\u624d\u89e6\u53d1\u91cd\u6574\u300d\u7684&#034;\u9608\u503c&#034;\u5177\u4f53\u5c31\u662f newSize &gt;&#061; spaceLeft()&#xff08;MMKV_IO.cpp:408&#xff09;&#xff0c;\u662f&#034;\u5f53\u524d\u5269\u4f59\u53ef\u8ffd\u52a0\u7a7a\u95f4\u4e0d\u8db3&#034;&#xff0c;\u800c\u4e0d\u662f&#034;\u6587\u4ef6\u8d85\u8fc7\u67d0\u4e2a\u5927\u5c0f&#034;\u3002\u53e6\u5916 clearAll()&#xff08;:1457&#xff09;\u91cc keepSpace&#061;false \u65f6\u4f1a truncate(m_expectedCapacity)&#xff0c;\u8fd9\u662f\u53e6\u4e00\u4e2a\u628a\u7a7a\u95f4\u8fd8\u56de\u53bb\u7684\u8def\u5f84\u3002<\/p>\n<h4>Q7&#xff1a;MMKV \u652f\u6301\u54ea\u4e9b\u6570\u636e\u7c7b\u578b&#xff1f;\u5982\u4f55\u5b58\u81ea\u5b9a\u4e49\u5bf9\u8c61&#xff1f;\u5b58 Serializable \u884c\u4e0d\u884c&#xff1f;<\/h4>\n<p>Java \u5c42 encode\/decode \u5bb6\u65cf&#xff08;MMKV.java:713 \u8d77&#xff09;&#xff1a;<\/p>\n<table>\n<tr>\u7c7b\u578bencodedecode<\/tr>\n<tbody>\n<tr>\n<td>boolean\/int\/long\/float\/double<\/td>\n<td>encode(key, v)&#xff08;:713\/735\/756\/777\/798&#xff09;<\/td>\n<td>decodeBool\/Int\/Long\/Float\/Double<\/td>\n<\/tr>\n<tr>\n<td>String<\/td>\n<td>encode(key, String)&#xff08;:819&#xff09;<\/td>\n<td>decodeString<\/td>\n<\/tr>\n<tr>\n<td>byte[]<\/td>\n<td>encode(key, byte[])<\/td>\n<td>decodeBytes<\/td>\n<\/tr>\n<tr>\n<td>Set&lt;String&gt;<\/td>\n<td>encode(key, Set&lt;String&gt;)&#xff08;:841&#xff09;<\/td>\n<td>decodeStringSet&#xff08;:855&#xff0c;\u53ef\u4f20 Class&lt;? extends Set&gt; \u6307\u5b9a\u5b9e\u73b0&#xff0c;\u5982 TreeSet&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>Parcelable<\/td>\n<td>encode(key, Parcelable)&#xff08;:917\u3001:930&#xff09;<\/td>\n<td>decodeParcelable(key, Class)&#xff08;:940&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u6bcf\u4e2a\u7c7b\u578b\u90fd\u6709\u5e26 expireDurationInSecond \u7684\u91cd\u8f7d&#xff0c;\u5bf9\u5e94 native \u7684 _2 \u540e\u7f00&#xff08;\u5982 encodeBool_2&#xff0c;MMKV.java:723&#xff09;\u3002<\/p>\n<p>Parcelable \u7684\u771f\u5b9e\u5b9e\u73b0&#xff1a;<\/p>\n<p><span class=\"token comment\">\/\/ MMKV.java:909<\/span><br \/>\n<span class=\"token keyword\">private<\/span> <span class=\"token keyword\">byte<\/span><span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token function\">getParcelableByte<\/span><span class=\"token punctuation\">(<\/span><span class=\"token annotation punctuation\">&#064;NonNull<\/span> <span class=\"token class-name\">Parcelable<\/span> value<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token class-name\">Parcel<\/span> parcel <span class=\"token operator\">&#061;<\/span> <span class=\"token class-name\">Parcel<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">obtain<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    value<span class=\"token punctuation\">.<\/span><span class=\"token function\">writeToParcel<\/span><span class=\"token punctuation\">(<\/span>parcel<span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">byte<\/span><span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span> bytes <span class=\"token operator\">&#061;<\/span> parcel<span class=\"token punctuation\">.<\/span><span class=\"token function\">marshall<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    parcel<span class=\"token punctuation\">.<\/span><span class=\"token function\">recycle<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> bytes<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h4>\u3010\u7ea0\u504f\u3011\u300cMMKV \u5185\u90e8\u901a\u8fc7 protobuf \u5b8c\u6210 Parcelable \u5e8f\u5217\u5316\u300d\u2014\u2014 \u8bf4\u6cd5\u9519\u8bef<\/h4>\n<p>Parcelable \u5bf9\u8c61 \u7531 Android Parcel \u5e8f\u5217\u5316\u6210 byte[]&#xff0c;MMKV \u53ea\u662f\u628a\u8fd9\u5768 byte[] \u5f53\u6210\u4e00\u4e2a\u666e\u901a\u7684 bytes value \u5b58\u8fdb\u53bb\u3002protobuf \u7684\u89d2\u8272\u662f \u7ed9 MMKV \u81ea\u5df1\u7684\u8bb0\u5f55\u6d41\u505a\u957f\u5ea6\u524d\u7f00\u7f16\u7801&#xff08;key\/value \u7684 varint \u5934&#xff09;&#xff0c;\u5b83 \u4e0d\u8ba4\u8bc6 \u4f60\u7684\u4e1a\u52a1\u5bf9\u8c61\u7ed3\u6784&#xff0c;\u4e5f\u4e0d\u505a\u5bf9\u8c61\u6620\u5c04\u3002<\/p>\n<p>\u6362\u53e5\u8bdd\u8bf4&#xff1a;MMKV \u7684 \u201cprotobuf\u201d \u662f \u5bb9\u5668\u5c42\u7684\u7f16\u7801\u683c\u5f0f&#xff0c;\u4e0d\u662f \u4e1a\u52a1\u5bf9\u8c61\u7684\u5e8f\u5217\u5316\u6846\u67b6\u3002<\/p>\n<p>decodeParcelable \u7684\u53cd\u5c04\u7f13\u5b58&#xff08;MMKV.java:940-964&#xff09;&#xff1a;\u901a\u8fc7 tClass.getField(&#034;CREATOR&#034;) \u62ff Parcelable.Creator&#xff0c;\u7f13\u5b58\u5728\u9759\u6001 mCreators&#xff08;MMKV.java:907&#xff09;\u91cc&#xff0c;\u907f\u514d\u6bcf\u6b21 getClass().getField()\u3002<\/p>\n<p>Serializable&#xff1f; MMKV \u6ca1\u6709 \u63d0\u4f9b Serializable \u7684 encode\/decode \u91cd\u8f7d\u3002\u8981\u5b58 Serializable \u53ea\u80fd\u81ea\u5df1\u8f6c byte[]&#xff08;ObjectOutputStream&#xff09;\u3002\u800c\u4e14\u5f3a\u70c8\u5efa\u8bae \u522b\u8fd9\u4e48\u5e72&#xff1a;Java \u5e8f\u5217\u5316\u683c\u5f0f\u4e0e serialVersionUID\/\u7c7b\u7ed3\u6784\u5f3a\u8026\u5408&#xff0c;\u4e00\u65e6\u6df7\u6dc6\u6216\u6539\u7c7b\u5c31\u89e3\u4e0d\u51fa\u6765\u3002\u5de5\u7a0b\u4e0a\u66f4\u7a33\u7684\u505a\u6cd5\u662f&#xff1a;\u4e1a\u52a1\u5bf9\u8c61 \u2192 JSON\/Parcelable \u7684 byte[] \u2192 encode(key, bytes)&#xff0c;\u8ba9\u5b58\u50a8\u5c42\u4e0e\u7c7b\u7ed3\u6784\u89e3\u8026\u3002<\/p>\n<p>\u7c7b\u578b\u4e0d\u5339\u914d\u4f1a\u600e\u6837&#xff1f; getBool \u62ff\u5230\u4e00\u4e2a string \u7684\u5b57\u8282\u65f6&#xff0c;CodedInputData::readBool() \u4f1a\u629b\u5f02\u5e38&#xff0c;\u88ab Core\/MMKV.cpp:801 \u7684 catch \u6355\u83b7\u5e76\u8fd4\u56de defaultValue\u3002MMKV \u4e0d\u4f1a\u56e0\u4e3a\u7c7b\u578b\u9519\u7528\u800c\u5d29\u6e83&#xff0c;\u4f46\u4f1a\u9759\u9ed8\u8fd4\u56de\u9ed8\u8ba4\u503c \u2014\u2014 \u8fd9\u662f\u6392\u67e5\u300c\u503c\u83ab\u540d\u53d8\u6210\u9ed8\u8ba4\u503c\u300d\u65f6\u7684\u4e00\u4e2a\u5e38\u89c1\u771f\u56e0\u3002<\/p>\n<h4>Q8&#xff1a;\u5982\u4f55\u4ece SharedPreferences \u8fc1\u79fb\u5230 MMKV&#xff1f;<\/h4>\n<p><span class=\"token comment\">\/\/ Android\/MMKV\/mmkv\/src\/main\/java\/com\/tencent\/mmkv\/MMKV.java:1166<\/span><br \/>\n<span class=\"token keyword\">public<\/span> <span class=\"token keyword\">int<\/span> <span class=\"token function\">importFromSharedPreferences<\/span><span class=\"token punctuation\">(<\/span><span class=\"token annotation punctuation\">&#064;NonNull<\/span> <span class=\"token class-name\">SharedPreferences<\/span> preferences<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token class-name\">Map<\/span><span class=\"token generics\"><span class=\"token punctuation\">&lt;<\/span><span class=\"token class-name\">String<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token operator\">?<\/span><span class=\"token punctuation\">&gt;<\/span><\/span> kvs <span class=\"token operator\">&#061;<\/span> preferences<span class=\"token punctuation\">.<\/span><span class=\"token function\">getAll<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>kvs <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token keyword\">null<\/span> <span class=\"token operator\">||<\/span> kvs<span class=\"token punctuation\">.<\/span><span class=\"token function\">size<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">return<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token class-name\">Map<span class=\"token punctuation\">.<\/span>Entry<\/span><span class=\"token generics\"><span class=\"token punctuation\">&lt;<\/span><span class=\"token class-name\">String<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token operator\">?<\/span><span class=\"token punctuation\">&gt;<\/span><\/span> entry <span class=\"token operator\">:<\/span> kvs<span class=\"token punctuation\">.<\/span><span class=\"token function\">entrySet<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token class-name\">String<\/span> key <span class=\"token operator\">&#061;<\/span> entry<span class=\"token punctuation\">.<\/span><span class=\"token function\">getKey<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token class-name\">Object<\/span> value <span class=\"token operator\">&#061;<\/span> entry<span class=\"token punctuation\">.<\/span><span class=\"token function\">getValue<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>key <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token keyword\">null<\/span> <span class=\"token operator\">||<\/span> value <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token keyword\">null<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token keyword\">continue<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>value <span class=\"token keyword\">instanceof<\/span> <span class=\"token class-name\">Boolean<\/span><span class=\"token punctuation\">)<\/span>      <span class=\"token punctuation\">{<\/span> <span class=\"token function\">encodeBool<\/span><span class=\"token punctuation\">(<\/span>nativeHandle<span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">boolean<\/span><span class=\"token punctuation\">)<\/span> value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>value <span class=\"token keyword\">instanceof<\/span> <span class=\"token class-name\">Integer<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">encodeInt<\/span><span class=\"token punctuation\">(<\/span>nativeHandle<span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">int<\/span><span class=\"token punctuation\">)<\/span> value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>value <span class=\"token keyword\">instanceof<\/span> <span class=\"token class-name\">Long<\/span><span class=\"token punctuation\">)<\/span>    <span class=\"token punctuation\">{<\/span> <span class=\"token function\">encodeLong<\/span><span class=\"token punctuation\">(<\/span>nativeHandle<span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">long<\/span><span class=\"token punctuation\">)<\/span> value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>value <span class=\"token keyword\">instanceof<\/span> <span class=\"token class-name\">Float<\/span><span class=\"token punctuation\">)<\/span>   <span class=\"token punctuation\">{<\/span> <span class=\"token function\">encodeFloat<\/span><span class=\"token punctuation\">(<\/span>nativeHandle<span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">float<\/span><span class=\"token punctuation\">)<\/span> value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>value <span class=\"token keyword\">instanceof<\/span> <span class=\"token class-name\">Double<\/span><span class=\"token punctuation\">)<\/span>  <span class=\"token punctuation\">{<\/span> <span class=\"token function\">encodeDouble<\/span><span class=\"token punctuation\">(<\/span>nativeHandle<span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">double<\/span><span class=\"token punctuation\">)<\/span> value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>value <span class=\"token keyword\">instanceof<\/span> <span class=\"token class-name\">String<\/span><span class=\"token punctuation\">)<\/span>  <span class=\"token punctuation\">{<\/span> <span class=\"token function\">encodeString<\/span><span class=\"token punctuation\">(<\/span>nativeHandle<span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token class-name\">String<\/span><span class=\"token punctuation\">)<\/span> value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">else<\/span> <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>value <span class=\"token keyword\">instanceof<\/span> <span class=\"token class-name\">Set<\/span><span class=\"token punctuation\">)<\/span>     <span class=\"token punctuation\">{<\/span> <span class=\"token function\">encode<\/span><span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token class-name\">Set<\/span><span class=\"token generics\"><span class=\"token punctuation\">&lt;<\/span><span class=\"token class-name\">String<\/span><span class=\"token punctuation\">&gt;<\/span><\/span><span class=\"token punctuation\">)<\/span> value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">else<\/span> <span class=\"token punctuation\">{<\/span> <span class=\"token function\">simpleLog<\/span><span class=\"token punctuation\">(<\/span><span class=\"token class-name\">MMKVLogLevel<span class=\"token punctuation\">.<\/span>LevelError<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;unknown type: &#034;<\/span> <span class=\"token operator\">&#043;<\/span> value<span class=\"token punctuation\">.<\/span><span class=\"token function\">getClass<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> kvs<span class=\"token punctuation\">.<\/span><span class=\"token function\">size<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h4>\u3010\u7ea0\u504f\u3011&#034;\u4e00\u884c\u4ee3\u7801\u5373\u53ef\u5b8c\u6210\u8fc1\u79fb&#034;\u662f\u8425\u9500\u8bdd\u672f&#xff0c;\u4e0d\u662f\u5b9e\u73b0\u539f\u7406<\/h4>\n<p>\u6e90\u7801\u8bf4\u660e\u5b83\u662f getAll() &#043; \u9010\u6761 encodeXxx \u7684\u8fd0\u884c\u65f6\u642c\u8fd0&#xff0c;\u56e0\u6b64&#xff1a;<\/p>\n<li>\u4f9d\u8d56 SP \u5df2\u7ecf\u628a XML \u89e3\u6790\u5b8c&#xff1a;getAll() \u8981\u6c42 SP \u52a0\u8f7d\u5b8c\u6bd5&#xff0c;\u5426\u5219\u8fd4\u56de\u7a7a map \u2192 \u9759\u9ed8\u8fc1\u79fb 0 \u6761\u3002\u6b63\u786e\u505a\u6cd5\u662f\u5148 sp.getAll() \u89e6\u53d1\u52a0\u8f7d\u6216\u786e\u4fdd SP \u5df2\u5b8c\u6210 loadFromDisk\u3002<\/li>\n<li>\u53ea\u652f\u6301 7 \u79cd\u7c7b\u578b&#xff08;Set \u8d70 instanceof Set&#xff09;\u3002SP \u91cc\u7406\u8bba\u4e0a\u4e5f\u53ea\u6709\u8fd9\u51e0\u79cd&#xff0c;\u4f46 unknown type \u53ea\u5199\u65e5\u5fd7\u3001\u4e0d\u62a5\u9519&#xff0c;\u8fd4\u56de\u503c\u4ecd\u662f kvs.size() \u2014\u2014 \u8fd4\u56de\u503c\u4e0d\u80fd\u4f5c\u4e3a&#034;\u6210\u529f\u8fc1\u79fb N \u6761&#034;\u7684\u8bc1\u636e&#xff0c;\u8fd9\u662f\u4e2a\u771f\u5b9e\u7684\u5751\u3002<\/li>\n<li>\u6bcf\u6761\u72ec\u7acb encode&#xff0c;\u4f1a\u89e6\u53d1 N \u6b21 meta \u5199\u3002\u51e0\u767e\u6761\u65e0\u6240\u8c13&#xff0c;\u4e0a\u4e07\u6761\u5efa\u8bae\u8fc1\u79fb\u5b8c trim() \u6216\u76f4\u63a5 MMKV.clearAll() \u524d\u4e00\u6b21\u6027\u505a\u5b8c\u3002<\/li>\n<li>\u4e0d\u662f\u5e42\u7b49\u7684&#xff1a;\u8c03\u4e24\u6b21\u4f1a\u642c\u4e24\u6b21&#xff08;\u5185\u5bb9\u76f8\u540c&#xff0c;\u914d\u5408 compareBeforeSet \u53ef\u7701 IO&#xff0c;\u4f46\u9ed8\u8ba4\u5173\u95ed&#xff09;\u3002<\/li>\n<li>\u539f SP \u6587\u4ef6\u4e0d\u4f1a\u88ab\u5220\u9664&#xff0c;\u4e5f\u4e0d\u4f1a\u81ea\u52a8\u63a5\u7ba1\u540e\u7eed\u5199\u5165\u3002\u771f\u6b63\u7684\u8fc1\u79fb\u65b9\u6848\u8fd8\u5f97\u914d\u5408\u300c\u8bfb\u5199\u4ee3\u7406\u5207\u6362 &#043; \u4e00\u6b21\u6027\u6807\u8bb0\u4f4d\u300d\u3002<\/li>\n<p>\u5de5\u7a0b\u4e0a\u63a8\u8350\u7684\u6807\u51c6\u8fc1\u79fb\u4e09\u6bb5\u5f0f&#xff1a;<\/p>\n<p><span class=\"token class-name\">MMKV<\/span> kv <span class=\"token operator\">&#061;<\/span> <span class=\"token constant\">MMKV<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">mmkvWithID<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;app_prefs_shared_process&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token constant\">MMKV<\/span><span class=\"token punctuation\">.<\/span><span class=\"token constant\">MULTI_PROCESS_MODE<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token class-name\">File<\/span> spFile <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">new<\/span> <span class=\"token class-name\">File<\/span><span class=\"token punctuation\">(<\/span>context<span class=\"token punctuation\">.<\/span><span class=\"token function\">getDataDir<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;shared_prefs\/old_name.xml&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>spFile<span class=\"token punctuation\">.<\/span><span class=\"token function\">exists<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token operator\">!<\/span>kv<span class=\"token punctuation\">.<\/span><span class=\"token function\">getBoolean<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;__migrated__&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token class-name\">SharedPreferences<\/span> old <span class=\"token operator\">&#061;<\/span> context<span class=\"token punctuation\">.<\/span><span class=\"token function\">getSharedPreferences<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;old_name&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">Context<\/span><span class=\"token punctuation\">.<\/span><span class=\"token constant\">MODE_PRIVATE<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">int<\/span> count <span class=\"token operator\">&#061;<\/span> kv<span class=\"token punctuation\">.<\/span><span class=\"token function\">importFromSharedPreferences<\/span><span class=\"token punctuation\">(<\/span>old<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    kv<span class=\"token punctuation\">.<\/span><span class=\"token function\">encode<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;__migrated__&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token boolean\">true<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    spFile<span class=\"token punctuation\">.<\/span><span class=\"token function\">delete<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>                 <span class=\"token comment\">\/\/ \u6216\u6539\u540d\u7559\u6863&#xff0c;\u9632\u6b62\u56de\u6eda\u65f6\u8bef\u5224<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>\u53e6\u4e00\u4e2a\u66f4\u5f7b\u5e95\u7684\u9009\u9879&#xff1a;MMKV \u5b9e\u73b0\u4e86 SharedPreferences \u4e0e SharedPreferences.Editor \u4e24\u4e2a\u63a5\u53e3&#xff08;MMKV.java:52&#xff09;&#xff0c;\u6240\u4ee5\u53ef\u4ee5\u5199\u4e00\u4e2a SharedPreferences \u95e8\u9762\u76f4\u63a5\u66ff\u6362 getSharedPreferences() \u7684\u8fd4\u56de\u503c&#xff08;\u5b98\u65b9\u63d0\u4f9b MMKVCompat&#xff09;&#xff0c;\u8ba9\u5b58\u91cf\u4ee3\u7801 \u4e0d\u6539\u4e00\u884c \u5c31\u6362\u6389\u5b9e\u73b0\u3002\u8fd9\u624d\u662f\u771f\u6b63\u7684&#034;\u4f4e\u6210\u672c\u8fc1\u79fb&#034;\u3002<\/p>\n<h4>\u9ad8\u9891\u8bef\u533a\u6e05\u5355&#xff08;\u4e00\u5f20\u8868\u5e26\u8fc7&#xff0c;\u9762\u8bd5\u65f6\u4e3b\u52a8\u7ea0\u504f\u5f88\u52a0\u5206&#xff09;<\/h4>\n<table>\n<tr>\u6d41\u4f20\u8bf4\u6cd5\u6e90\u7801\u4e8b\u5b9e\u4f9d\u636e<\/tr>\n<tbody>\n<tr>\n<td>\u5b9e\u4f8b\u7528 LRU \u7f13\u5b58\u6dd8\u6c70<\/td>\n<td>\u88f8 unordered_map&#xff0c;\u6c38\u4e45\u7f13\u5b58&#xff0c;\u53ea\u6709 onExit\/clearMemoryCache \u4f1a munmap<\/td>\n<td>MMKV.cpp:60\/257\/262\/302<\/td>\n<\/tr>\n<tr>\n<td>\u4fee\u6539\u65f6\u5199\u65f6\u590d\u5236&#xff08;\u521b\u5efa\u65b0\u5185\u5b58\u9875&#xff09;<\/td>\n<td>MAP_SHARED&#xff0c;\u539f\u5730 memcpy&#xff0c;\u65e0 COW<\/td>\n<td>MemoryFile.cpp:197<\/td>\n<\/tr>\n<tr>\n<td>\u5f31\u5f15\u7528\u5173\u8054 Context<\/td>\n<td>\u4e0d\u6301\u6709 Context&#xff0c;\u4e5f\u6ca1\u6709 WeakReference<\/td>\n<td>MMKV.java:91<\/td>\n<\/tr>\n<tr>\n<td>\u5168\u5c40\u5199\u6307\u9488\u653e\u5728 mmap \u5185\u5b58\u91cc<\/td>\n<td>\u6743\u5a01\u957f\u5ea6\/CRC \u5728 .crc \u5143\u6587\u4ef6&#xff1b;\u6570\u636e\u6587\u4ef6\u5934 4 \u5b57\u8282\u53ea\u4e3a\u964d\u7ea7\u517c\u5bb9<\/td>\n<td>MMKV_IO.cpp:473\/487<\/td>\n<\/tr>\n<tr>\n<td>\u591a\u8fdb\u7a0b\u7528 ContentProvider \u505a\u540c\u6b65<\/td>\n<td>ContentProvider \u53ea\u4f20 ashmem fd&#xff1b;\u540c\u6b65\u9760 flock &#043; meta<\/td>\n<td>MMKVContentProvider.java\u3001MMKV_IO.cpp:305<\/td>\n<\/tr>\n<tr>\n<td>\u591a\u8fdb\u7a0b\u4e5f\u80fd\u539f\u5730\u8986\u76d6<\/td>\n<td>onlyOneKey \u663e\u5f0f\u6392\u9664 m_isInterProcess<\/td>\n<td>MMKV_IO.cpp:691<\/td>\n<\/tr>\n<tr>\n<td>\u6587\u4ef6\u4f1a\u81ea\u52a8\u6536\u7f29<\/td>\n<td>\u7f29\u5bb9\u53ea\u80fd\u9760\u4e1a\u52a1\u8c03 trim()<\/td>\n<td>MMKV_IO.cpp:1413<\/td>\n<\/tr>\n<tr>\n<td>\u4e00\u884c\u4ee3\u7801\u65e0\u635f\u8fc1\u79fb SP<\/td>\n<td>\u8fd0\u884c\u65f6\u9010\u6761\u642c\u8fd0&#xff0c;\u5f02\u5e38\u53ea\u6253\u65e5\u5fd7\u3001\u8fd4\u56de\u503c\u4e0d\u4ee3\u8868\u6210\u529f<\/td>\n<td>MMKV.java:1166<\/td>\n<\/tr>\n<tr>\n<td>CRC \u5931\u8d25\u81ea\u52a8\u56de\u6eda\u5230\u4e0a\u6b21\u5b8c\u6574\u72b6\u6001<\/td>\n<td>\u5148\u8bd5 lastConfirmed \u56de\u6eda&#xff1b;\u5931\u8d25\u8fd8\u8981\u95ee\u4e1a\u52a1 OnErrorRecover\/Discard<\/td>\n<td>MMKV_IO.cpp:253\/279<\/td>\n<\/tr>\n<tr>\n<td>MMKV \u5b8c\u5168\u4e0d\u4f1a ANR<\/td>\n<td>\u7ed3\u6784\u4e0a\u65e0\u7b49\u5f85\u961f\u5217&#xff0c;\u4f46\u6269\u5bb9\u7684 ftruncate\/zeroFill \u662f\u771f\u7cfb\u7edf\u8c03\u7528<\/td>\n<td>MMKV_IO.cpp:443\u3001MemoryFile.cpp<\/td>\n<\/tr>\n<tr>\n<td>\u52a0\u5bc6\u5bc6\u94a5\u5f88\u5b89\u5168<\/td>\n<td>\u53ea\u5728 native \u5806&#xff0c;\u53ef\u88ab Frida hook AESCrypt \u6784\u9020\u53d6&#xff1b;\u5c5e\u9759\u6001\u6570\u636e\u4fdd\u62a4&#xff0c;\u975e KMS<\/td>\n<td>AESCrypt.cpp:51<\/td>\n<\/tr>\n<tr>\n<td>protobuf \u5e8f\u5217\u5316\u4e1a\u52a1\u5bf9\u8c61<\/td>\n<td>\u53ea\u7f16\u7801\u5bb9\u5668\u957f\u5ea6\u524d\u7f00&#xff1b;Parcelable \u8d70 Parcel.marshall()<\/td>\n<td>MMKV.java:909\u3001MiniPBCoder.cpp:506<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>\u9644\u5f55 A&#xff1a;\u5173\u952e\u6e90\u7801\u7d22\u5f15\u8868<\/h3>\n<p>\u8def\u5f84\u5747\u76f8\u5bf9\u4e8e C:\\\\Users\\\\Administrator.DESKTOP-VOB36RN\\\\Downloads\\\\Android Project\\\\mmkv\u6e90\u7801\u5206\u6790\\\\&#xff0c;\u884c\u53f7\u4e3a v1.3.16 \u7684 1-based \u771f\u5b9e\u884c\u53f7\u3002<\/p>\n<table>\n<tr>\u4e3b\u9898\u4f4d\u7f6e\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>\u7248\u672c\u5b8f<\/td>\n<td>Core\/MMKVPredef.h:37<\/td>\n<td>MMKV_VERSION &#061; &#034;v1.3.16&#034;<\/td>\n<\/tr>\n<tr>\n<td>\u5b57\u5178\u7c7b\u578b<\/td>\n<td>Core\/MMKVPredef.h:228<\/td>\n<td>MMKVMap&#xff08;\u5f02\u6784\u67e5\u627e&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u9519\u8bef\u6062\u590d\u7b56\u7565<\/td>\n<td>Core\/MMKVPredef.h:146\/166<\/td>\n<td>MMKVRecoverStrategic \/ ErrorHandler<\/td>\n<\/tr>\n<tr>\n<td>Java \u7c7b\u58f0\u660e<\/td>\n<td>Android\/&#8230;\/MMKV.java:52<\/td>\n<td>implements SharedPreferences, Editor<\/td>\n<\/tr>\n<tr>\n<td>Java \u521d\u59cb\u5316<\/td>\n<td>Android\/&#8230;\/MMKV.java:91 \/ 192 \/ 216<\/td>\n<td>\u5165\u53e3 \/ \u5168\u53c2 \/ \u52a0\u8f7d so<\/td>\n<\/tr>\n<tr>\n<td>debug \u5f00\u8fdb\u7a0b\u6a21\u5f0f\u68c0\u67e5<\/td>\n<td>Android\/&#8230;\/MMKV.java:199<\/td>\n<td>enableProcessModeChecker()<\/td>\n<\/tr>\n<tr>\n<td>mmkvWithID \u5bb6\u65cf<\/td>\n<td>Android\/&#8230;\/MMKV.java:344\u2013500<\/td>\n<td>\u5404\u91cd\u8f7d<\/td>\n<\/tr>\n<tr>\n<td>\u8fdb\u7a0b\u6a21\u5f0f\u6821\u9a8c<\/td>\n<td>Android\/&#8230;\/MMKV.java:601<\/td>\n<td>checkProcessMode &#043; checkedHandleSet<\/td>\n<\/tr>\n<tr>\n<td>encode \u8d77\u70b9<\/td>\n<td>Android\/&#8230;\/MMKV.java:713<\/td>\n<td>boolean&#xff1b;819 String&#xff1b;841 Set&#xff1b;917 Parcelable<\/td>\n<\/tr>\n<tr>\n<td>Parcelable \u2192 bytes<\/td>\n<td>Android\/&#8230;\/MMKV.java:909<\/td>\n<td>Parcel.marshall()<\/td>\n<\/tr>\n<tr>\n<td>SP \u8fc1\u79fb<\/td>\n<td>Android\/&#8230;\/MMKV.java:1166<\/td>\n<td>importFromSharedPreferences<\/td>\n<\/tr>\n<tr>\n<td>\u53d8\u66f4\u901a\u77e5<\/td>\n<td>Android\/&#8230;\/MMKV.java:1623 \/ 1636 \/ 1647<\/td>\n<td>\u6ce8\u518c \/ native \u56de\u8c03 \/ \u624b\u52a8\u68c0\u67e5<\/td>\n<\/tr>\n<tr>\n<td>native \u58f0\u660e\u5757<\/td>\n<td>Android\/&#8230;\/MMKV.java:1642\u20131751<\/td>\n<td>private static native<\/td>\n<\/tr>\n<tr>\n<td>JNI \u6ce8\u518c<\/td>\n<td>Android\/&#8230;\/cpp\/native-bridge.cpp:59 \/ 69 \/ 1101 \/ 1158<\/td>\n<td>JNI_OnLoad \/ \u7c7b\u540d \/ \u65b9\u6cd5\u8868<\/td>\n<\/tr>\n<tr>\n<td>native \u521d\u59cb\u5316<\/td>\n<td>Android\/&#8230;\/cpp\/native-bridge.cpp:143<\/td>\n<td>jniInitialize_2<\/td>\n<\/tr>\n<tr>\n<td>\u6784\u9020\u51fd\u6570<\/td>\n<td>Core\/MMKV.cpp:81<\/td>\n<td>\u53cc\u6587\u4ef6 &#043; \u9501 &#043; \u61d2\u52a0\u8f7d\u6ce8\u91ca<\/td>\n<\/tr>\n<tr>\n<td>\u9501 enable \u5f00\u5173<\/td>\n<td>Core\/MMKV.cpp:117<\/td>\n<td>\u5355\u8fdb\u7a0b\u65f6\u6587\u4ef6\u9501\u7a7a\u64cd\u4f5c<\/td>\n<\/tr>\n<tr>\n<td>\u5168\u5c40\u521d\u59cb\u5316<\/td>\n<td>Core\/MMKV.cpp:160<\/td>\n<td>page size\u3001ARMv8 AES\/CRC32<\/td>\n<\/tr>\n<tr>\n<td>initializeMMKV<\/td>\n<td>Core\/MMKV.cpp:200<\/td>\n<td>ThreadOnce &#043; mkPath<\/td>\n<\/tr>\n<tr>\n<td>\u5b9e\u4f8b\u5b57\u5178<\/td>\n<td>Core\/MMKV.cpp:60 \/ 233 \/ 257<\/td>\n<td>g_instanceDic<\/td>\n<\/tr>\n<tr>\n<td>onExit<\/td>\n<td>Core\/MMKV.cpp:262<\/td>\n<td>sync &#043; clearMemoryCache &#043; delete<\/td>\n<\/tr>\n<tr>\n<td>clearMemoryCache<\/td>\n<td>Core\/MMKV.cpp:302<\/td>\n<td>\u4e3b\u52a8 munmap<\/td>\n<\/tr>\n<tr>\n<td>CRC \u52a9\u624b<\/td>\n<td>Core\/MMKV.cpp:405 \/ 418 \/ 427 \/ 436<\/td>\n<td>\u5168\u91cf \/ \u91cd\u6574 \/ \u8986\u76d6 \/ \u589e\u91cf<\/td>\n<\/tr>\n<tr>\n<td>set(bool,\u2026)<\/td>\n<td>Core\/MMKV.cpp:451<\/td>\n<td>\u8fc7\u671f\u65f6\u95f4\u6233\u62fc\u63a5<\/td>\n<\/tr>\n<tr>\n<td>getBool<\/td>\n<td>Core\/MMKV.cpp:784<\/td>\n<td>shared \u9501 &#043; \u96f6\u62f7\u8d1d<\/td>\n<\/tr>\n<tr>\n<td>sync<\/td>\n<td>Core\/MMKV.cpp:1169<\/td>\n<td>\u53cc\u6587\u4ef6 msync<\/td>\n<\/tr>\n<tr>\n<td>lock\/unlock\/try_lock<\/td>\n<td>Core\/MMKV.cpp:1181\/1185\/1189<\/td>\n<td>\u66b4\u9732\u8de8\u8fdb\u7a0b\u72ec\u5360\u9501<\/td>\n<\/tr>\n<tr>\n<td>loadFromFile<\/td>\n<td>Core\/MMKV_IO.cpp:64<\/td>\n<td>\u542f\u52a8\u4f53\u68c0\u4e3b\u5e72<\/td>\n<\/tr>\n<tr>\n<td>partialLoadFromFile<\/td>\n<td>Core\/MMKV_IO.cpp:147<\/td>\n<td>\u589e\u91cf\u540c\u6b65&#xff08;3 \u6b65\u8d70&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>loadMetaInfoAndCheck<\/td>\n<td>Core\/MMKV_IO.cpp:194<\/td>\n<td>meta \u7248\u672c\u54e8\u5175<\/td>\n<\/tr>\n<tr>\n<td>checkDataValid<\/td>\n<td>Core\/MMKV_IO.cpp:230<\/td>\n<td>\u4e09\u7ea7\u81ea\u6108<\/td>\n<\/tr>\n<tr>\n<td>checkLoadData<\/td>\n<td>Core\/MMKV_IO.cpp:305<\/td>\n<td>\u2605\u591a\u8fdb\u7a0b\u4e00\u81f4\u6027\u5fc3\u810f<\/td>\n<\/tr>\n<tr>\n<td>ItemSizeHolderSize<\/td>\n<td>Core\/MMKV_IO.cpp:348<\/td>\n<td>&#061; 4<\/td>\n<\/tr>\n<tr>\n<td>prepareEncode<\/td>\n<td>Core\/MMKV_IO.cpp:350<\/td>\n<td>\u53ea\u7b97\u957f\u5ea6\u4e0d\u5e8f\u5217\u5316<\/td>\n<\/tr>\n<tr>\n<td>ensureMemorySize<\/td>\n<td>Core\/MMKV_IO.cpp:402<\/td>\n<td>\u91cd\u6574\u89e6\u53d1\u70b9<\/td>\n<\/tr>\n<tr>\n<td>expandAndWriteBack<\/td>\n<td>Core\/MMKV_IO.cpp:422<\/td>\n<td>\u7ffb\u500d &#043; \u672a\u6765\u9884\u7559<\/td>\n<\/tr>\n<tr>\n<td>readActualSize \/ oldStyleWriteActualSize<\/td>\n<td>Core\/MMKV_IO.cpp:455 \/ 473<\/td>\n<td>\u957f\u5ea6\u8bfb\u5199<\/td>\n<\/tr>\n<tr>\n<td>writeActualSize<\/td>\n<td>Core\/MMKV_IO.cpp:487<\/td>\n<td>\u2605\u8d26\u672c\u843d\u7b14<\/td>\n<\/tr>\n<tr>\n<td>getRawDataForKey<\/td>\n<td>Core\/MMKV_IO.cpp:543<\/td>\n<td>\u96f6\u62f7\u8d1d\u89c6\u56fe<\/td>\n<\/tr>\n<tr>\n<td>t_status<\/td>\n<td>Core\/MMKV_IO.cpp:577<\/td>\n<td>thread_local CFB \u72b6\u6001<\/td>\n<\/tr>\n<tr>\n<td>setDataForKey<\/td>\n<td>Core\/MMKV_IO.cpp:581<\/td>\n<td>\u2605\u4e09\u5c94\u8def\u53e3<\/td>\n<\/tr>\n<tr>\n<td>doAppendDataWithKey<\/td>\n<td>Core\/MMKV_IO.cpp:822<\/td>\n<td>\u2605\u8ffd\u52a0\u6b63\u8eab<\/td>\n<\/tr>\n<tr>\n<td>doOverrideDataWithKey<\/td>\n<td>Core\/MMKV_IO.cpp:884<\/td>\n<td>\u539f\u5730\u8986\u76d6<\/td>\n<\/tr>\n<tr>\n<td>checkSizeForOverride<\/td>\n<td>Core\/MMKV_IO.cpp:966<\/td>\n<td>\u8986\u76d6\u524d\u7f6e\u68c0\u67e5<\/td>\n<\/tr>\n<tr>\n<td>appendDataWithKey(kvHolder)<\/td>\n<td>Core\/MMKV_IO.cpp:1001<\/td>\n<td>\u2605\u590d\u7528\u5df2\u7f16\u7801 key<\/td>\n<\/tr>\n<tr>\n<td>fullWriteback<\/td>\n<td>Core\/MMKV_IO.cpp:1059<\/td>\n<td>\u91cd\u6574\u5165\u53e3 &#043; \u77ed\u8def<\/td>\n<\/tr>\n<tr>\n<td>memmoveDictionary<\/td>\n<td>Core\/MMKV_IO.cpp:1104<\/td>\n<td>\u2605\u91cd\u6574\u7cbe\u9ad3&#xff08;\u660e\u6587&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>memmoveDictionary(crypt)<\/td>\n<td>Core\/MMKV_IO.cpp:1159<\/td>\n<td>CFB \u5b58\u6863\u70b9\u7248<\/td>\n<\/tr>\n<tr>\n<td>doFullWriteBack<\/td>\n<td>Core\/MMKV_IO.cpp:1264 \/ 1312<\/td>\n<td>\u6536\u5c3e &#043; CRC &#043; sync<\/td>\n<\/tr>\n<tr>\n<td>reKey<\/td>\n<td>Core\/MMKV_IO.cpp:1345<\/td>\n<td>\u6362\u5bc6\u94a5&#061;\u4e00\u6b21\u91cd\u6574<\/td>\n<\/tr>\n<tr>\n<td>trim<\/td>\n<td>Core\/MMKV_IO.cpp:1413<\/td>\n<td>\u552f\u4e00\u7f29\u5bb9<\/td>\n<\/tr>\n<tr>\n<td>clearAll<\/td>\n<td>Core\/MMKV_IO.cpp:1457<\/td>\n<td>\u6362 IV &#043; truncate<\/td>\n<\/tr>\n<tr>\n<td>isFileValid<\/td>\n<td>Core\/MMKV_IO.cpp:1494<\/td>\n<td>\u5065\u5eb7\u68c0\u67e5<\/td>\n<\/tr>\n<tr>\n<td>removeStorage<\/td>\n<td>Core\/MMKV_IO.cpp:1537<\/td>\n<td>\u5220\u5e93<\/td>\n<\/tr>\n<tr>\n<td>filterExpiredKeys<\/td>\n<td>Core\/MMKV_IO.cpp:1820<\/td>\n<td>TTL \u6e05\u7406<\/td>\n<\/tr>\n<tr>\n<td>enableCompareBeforeSet<\/td>\n<td>Core\/MMKV_IO.cpp:1903<\/td>\n<td>\u5f00\u5173<\/td>\n<\/tr>\n<tr>\n<td>mmap() \u672c\u4f53<\/td>\n<td>Core\/MemoryFile.cpp:195<\/td>\n<td>\u2605MAP_SHARED<\/td>\n<\/tr>\n<tr>\n<td>msync()<\/td>\n<td>Core\/MemoryFile.cpp:184<\/td>\n<td>MS_SYNC\/MS_ASYNC<\/td>\n<\/tr>\n<tr>\n<td>truncate() \u56de\u6eda<\/td>\n<td>Core\/MemoryFile.cpp:160<\/td>\n<td>\u5931\u8d25\u8fd8\u539f\u957f\u5ea6<\/td>\n<\/tr>\n<tr>\n<td>reloadFromFile()<\/td>\n<td>Core\/MemoryFile.cpp:207<\/td>\n<td>\u9501\u5347\u7ea7 &#043; \u91cd\u6620\u5c04<\/td>\n<\/tr>\n<tr>\n<td>doCleanMemoryCache()<\/td>\n<td>Core\/MemoryFile.cpp:248<\/td>\n<td>munmap &#043; close<\/td>\n<\/tr>\n<tr>\n<td>FileLock::platformLock<\/td>\n<td>Core\/InterProcessLock.cpp:85<\/td>\n<td>\u2605flock &#043; \u541b\u5b50\u534f\u8bae<\/td>\n<\/tr>\n<tr>\n<td>platformUnLock<\/td>\n<td>Core\/InterProcessLock.cpp:128<\/td>\n<td>\u9000\u56de shared \u9501<\/td>\n<\/tr>\n<tr>\n<td>ashmemLock<\/td>\n<td>Core\/InterProcessLock_Android.cpp:47<\/td>\n<td>fcntl \u8bb0\u5f55\u9501<\/td>\n<\/tr>\n<tr>\n<td>KeyValueHolder<\/td>\n<td>Core\/KeyValueHolder.h:32<\/td>\n<td>12 \u5b57\u8282 offset \u7d22\u5f15<\/td>\n<\/tr>\n<tr>\n<td>KeyValueHolderCrypt<\/td>\n<td>Core\/KeyValueHolder.h:53<\/td>\n<td>\u4e09\u6001 union<\/td>\n<\/tr>\n<tr>\n<td>isValueStoredAsOffset<\/td>\n<td>Core\/KeyValueHolder.h:85<\/td>\n<td>256B \u5206\u754c<\/td>\n<\/tr>\n<tr>\n<td>decodeOneMap<\/td>\n<td>Core\/MiniPBCoder.cpp:506<\/td>\n<td>\u2605\u5893\u7891 &#043; greedy<\/td>\n<\/tr>\n<tr>\n<td>MMKVMetaInfo<\/td>\n<td>Core\/MMKVMetaInfo.hpp:54\u201374<\/td>\n<td>\u8d26\u672c\u7ed3\u6784<\/td>\n<\/tr>\n<tr>\n<td>writeCRCAndActualSizeOnly<\/td>\n<td>Core\/MMKVMetaInfo.hpp:81<\/td>\n<td>\u70ed\u8def\u5f84 8 \u5b57\u8282<\/td>\n<\/tr>\n<tr>\n<td>static_assert \u9875\u7ea6\u675f<\/td>\n<td>Core\/MMKVMetaInfo.hpp:94<\/td>\n<td>\u2605\u539f\u5b50\u6027\u6839\u57fa<\/td>\n<\/tr>\n<tr>\n<td>AESCryptStatus<\/td>\n<td>Core\/aes\/AESCrypt.h:48<\/td>\n<td>\u6d41\u4f4d\u7f6e\u5b58\u6863\u70b9<\/td>\n<\/tr>\n<tr>\n<td>CFB-128 \u6ce8\u91ca<\/td>\n<td>Core\/aes\/AESCrypt.h:57<\/td>\n<td>\u7b97\u6cd5\u51fa\u5904<\/td>\n<\/tr>\n<tr>\n<td>randomItemSizeHolder<\/td>\n<td>Core\/aes\/AESCrypt.cpp:33<\/td>\n<td>\u957f\u5ea6\u4f2a\u88c5<\/td>\n<\/tr>\n<tr>\n<td>fillRandomIV<\/td>\n<td>Core\/aes\/AESCrypt.cpp:109<\/td>\n<td>IV \u968f\u673a\u5316<\/td>\n<\/tr>\n<tr>\n<td>Android ashmem \u6784\u9020<\/td>\n<td>Core\/MMKV_Android.cpp:90<\/td>\n<td>\u53cc fd \u53cc\u9501<\/td>\n<\/tr>\n<tr>\n<td>checkProcessMode()<\/td>\n<td>Core\/MMKV_Android.cpp:222<\/td>\n<td>\u72ec\u5360 vs \u5171\u4eab\u63a2\u6d4b<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>\u9644\u5f55 B&#xff1a;\u4e00\u56fe\u6d41\u603b\u7ed3<\/h3>\n<p>  #mermaid-svg-1rOwywQZRiyxp9qd{font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1rOwywQZRiyxp9qd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1rOwywQZRiyxp9qd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1rOwywQZRiyxp9qd .error-icon{fill:#552222;}#mermaid-svg-1rOwywQZRiyxp9qd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1rOwywQZRiyxp9qd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1rOwywQZRiyxp9qd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1rOwywQZRiyxp9qd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1rOwywQZRiyxp9qd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1rOwywQZRiyxp9qd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1rOwywQZRiyxp9qd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1rOwywQZRiyxp9qd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1rOwywQZRiyxp9qd .marker.cross{stroke:#333333;}#mermaid-svg-1rOwywQZRiyxp9qd svg{font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1rOwywQZRiyxp9qd p{margin:0;}#mermaid-svg-1rOwywQZRiyxp9qd .label{font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;color:#333;}#mermaid-svg-1rOwywQZRiyxp9qd .cluster-label text{fill:#333;}#mermaid-svg-1rOwywQZRiyxp9qd .cluster-label span{color:#333;}#mermaid-svg-1rOwywQZRiyxp9qd .cluster-label span p{background-color:transparent;}#mermaid-svg-1rOwywQZRiyxp9qd .label text,#mermaid-svg-1rOwywQZRiyxp9qd span{fill:#333;color:#333;}#mermaid-svg-1rOwywQZRiyxp9qd .node rect,#mermaid-svg-1rOwywQZRiyxp9qd .node circle,#mermaid-svg-1rOwywQZRiyxp9qd .node ellipse,#mermaid-svg-1rOwywQZRiyxp9qd .node polygon,#mermaid-svg-1rOwywQZRiyxp9qd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1rOwywQZRiyxp9qd .rough-node .label text,#mermaid-svg-1rOwywQZRiyxp9qd .node .label text,#mermaid-svg-1rOwywQZRiyxp9qd .image-shape .label,#mermaid-svg-1rOwywQZRiyxp9qd .icon-shape .label{text-anchor:middle;}#mermaid-svg-1rOwywQZRiyxp9qd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1rOwywQZRiyxp9qd .rough-node .label,#mermaid-svg-1rOwywQZRiyxp9qd .node .label,#mermaid-svg-1rOwywQZRiyxp9qd .image-shape .label,#mermaid-svg-1rOwywQZRiyxp9qd .icon-shape .label{text-align:center;}#mermaid-svg-1rOwywQZRiyxp9qd .node.clickable{cursor:pointer;}#mermaid-svg-1rOwywQZRiyxp9qd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1rOwywQZRiyxp9qd .arrowheadPath{fill:#333333;}#mermaid-svg-1rOwywQZRiyxp9qd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1rOwywQZRiyxp9qd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1rOwywQZRiyxp9qd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1rOwywQZRiyxp9qd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1rOwywQZRiyxp9qd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1rOwywQZRiyxp9qd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1rOwywQZRiyxp9qd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1rOwywQZRiyxp9qd .cluster text{fill:#333;}#mermaid-svg-1rOwywQZRiyxp9qd .cluster span{color:#333;}#mermaid-svg-1rOwywQZRiyxp9qd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1rOwywQZRiyxp9qd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1rOwywQZRiyxp9qd rect.text{fill:none;stroke-width:0;}#mermaid-svg-1rOwywQZRiyxp9qd .icon-shape,#mermaid-svg-1rOwywQZRiyxp9qd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1rOwywQZRiyxp9qd .icon-shape p,#mermaid-svg-1rOwywQZRiyxp9qd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1rOwywQZRiyxp9qd .icon-shape .label rect,#mermaid-svg-1rOwywQZRiyxp9qd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1rOwywQZRiyxp9qd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1rOwywQZRiyxp9qd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1rOwywQZRiyxp9qd :root{&#8211;mermaid-font-family:\\&#8221;trebuchet ms\\&#8221;,verdana,arial,sans-serif;}<\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>\u8bfb\u8def\u5f84<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>decodeXxx(k)<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>ThreadLock &#043; Shared flock<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>checkLoadData()<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>dic.find(k) \u2192 offset<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>MMBuffer NoCopy \u89c6\u56fe<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>CodedInputData \u5355\u503c\u89e3\u7801<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>\u5199\u8def\u5f84<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/p>\n<p>\u662f<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/p>\n<p>\u5426<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/p>\n<p>\u662f<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/p>\n<p>\u5426<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/p>\n<p>\u7a7a\u95f4\u4e0d\u8db3<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/p>\n<p>\u8db3\u591f<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"edgeLabel\"><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>encode(k,v)<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>MMBuffer \u7f16\u7801\u5806\u4e0a\u4e34\u65f6 buffer<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>setDataForKeyThreadLock &#043; Exclusive flock<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>checkLoadData()\u540c\u6b65\u4ed6\u8fdb\u7a0b\u589e\u91cf<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>compareBeforeSet\u503c\u76f8\u540c?<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>return true \u96f6\u5199\u5165<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>\u5355 key\u4e14\u975e\u591a\u8fdb\u7a0b?<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>override \u539f\u5730\u8986\u76d6<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>append \u8ffd\u52a0<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>ensureMemorySize<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>prepareEncode\u2192 expandAndWriteBack\u2192 memmoveDictionary<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>doFullWriteBacksequence&#043;&#043; &#043; msync<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>memcpy \u8fdb mmap \u533a<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>updateCRCDigest\u589e\u91cf CRC<\/p>\n<p><\/span><\/p>\n<p>           <span class=\"nodeLabel\"><\/p>\n<p>writeCRCAndActualSizeOnly\u5199 8 \u5b57\u8282\u5230\u8d26\u672c<\/p>\n<p><\/span><\/p>\n<p>\u6700\u540e\u51dd\u7f29\u6210 5 \u6761&#xff0c;\u591f\u5e94\u4ed8\u4efb\u4f55\u8ffd\u95ee&#xff1a;<\/p>\n<li>\u4e24\u4e2a\u6587\u4ef6&#xff1a;\u6570\u636e\u6587\u4ef6&#xff08;\u8ffd\u52a0\u5f0f protobuf \u8bb0\u5f55\u6d41&#xff09;&#043; .crc \u5143\u6587\u4ef6&#xff08;\u4e00\u9875\u4ee5\u5185\u7684\u8d26\u672c&#xff1a;actualSize \/ crcDigest \/ sequence \/ IV \/ flags&#xff09;\u3002<\/li>\n<li>\u4e00\u4efd\u7d22\u5f15&#xff1a;unordered_map&lt;key, {keySize, valueSize, offset}&gt;&#xff0c;\u8bfb\u503c &#061; \u6307\u9488\u7b97\u672f &#043; \u96f6\u62f7\u8d1d\u89c6\u56fe\u3002<\/li>\n<li>\u4e09\u5c42\u9501&#xff1a;\u8fdb\u7a0b\u5185 ThreadLock\u3001\u8de8\u8fdb\u7a0b flock&#xff08;shared \u8bfb \/ exclusive \u5199&#xff0c;\u52a0\u5728 .crc \u7684 fd \u4e0a&#xff0c;\u8fdb\u7a0b\u6b7b\u5373\u9501\u91ca\u653e&#xff09;\u3002<\/li>\n<li>\u4e00\u5957\u589e\u91cf\u540c\u6b65\u534f\u8bae&#xff1a;\u8bfb\u5199\u524d\u6bd4 checkLoadData() \u7684\u4e09\u5143\u7ec4&#xff1b;\u80fd\u589e\u91cf\u5219 partialLoadFromFile&#xff08;\u589e\u91cf CRC &#043; \u53ea\u89e3\u65b0\u6bb5 &#043; \u5199\u6307\u9488\u8ddf\u8fdb&#xff09;&#xff0c;\u4e0d\u80fd\u5219\u5168\u91cf\u91cd\u6765\u3002<\/li>\n<li>\u4e00\u6761\u81ea\u6108\u94fe&#xff1a;CRC \u6821\u9a8c \u2192 \u964d\u7ea7\u517c\u5bb9 \u2192 lastConfirmed \u56de\u6eda \u2192 \u4e1a\u52a1\u7b56\u7565 \u2192 \u8d2a\u5fc3\u89e3\u7801\u62a2\u6551 \u2192 \u7acb\u5373\u91cd\u6574\u56fa\u5316\u3002<\/li>\n<hr \/>\n","protected":false},"excerpt":{"rendered":"<p>\u5206\u6790\u5bf9\u8c61 Core\/&#xff1a;\u8de8\u5e73\u53f0 C \u6838\u5fc3&#xff08;Android \/ iOS \/ macOS \/ HarmonyOS \/ Win32 \u5171\u7528&#xff09;Android\/MMKV\/mmkv\/src\/main\/java\/&#xff1a;Android Java \u58f3\u5c42Android\/MMKV\/mmkv\/src\/main\/cpp\/native-bridge.cpp&#xff1a;JNI \u6865\u63a5\u5c42 **\u6e90\u7801\u7248\u672c&#xff1a;v1.3.16 https:\/\/githu<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[11895,84,4209],"topic":[],"class_list":["post-104552","post","type-post","status-publish","format-standard","hentry","category-server","tag-mmkv","tag-android","tag-4209"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>MMKV \u6e90\u7801\u7ea7\u5256\u6790\uff08\u57fa\u4e8e v1.3.16 \u771f\u5b9e\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/104552.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"MMKV \u6e90\u7801\u7ea7\u5256\u6790\uff08\u57fa\u4e8e v1.3.16 \u771f\u5b9e\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u5206\u6790\u5bf9\u8c61 Core\/&#xff1a;\u8de8\u5e73\u53f0 C \u6838\u5fc3&#xff08;Android \/ iOS \/ macOS \/ HarmonyOS \/ Win32 \u5171\u7528&#xff09;Android\/MMKV\/mmkv\/src\/main\/java\/&#xff1a;Android Java \u58f3\u5c42Android\/MMKV\/mmkv\/src\/main\/cpp\/native-bridge.cpp&#xff1a;JNI \u6865\u63a5\u5c42 **\u6e90\u7801\u7248\u672c&#xff1a;v1.3.16 https:\/\/githu\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/104552.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-12T10:01:25+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"65 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/104552.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/104552.html\",\"name\":\"MMKV \u6e90\u7801\u7ea7\u5256\u6790\uff08\u57fa\u4e8e v1.3.16 \u771f\u5b9e\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-09-12T10:01:25+00:00\",\"dateModified\":\"2026-09-12T10:01:25+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/104552.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/104552.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/104552.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"MMKV \u6e90\u7801\u7ea7\u5256\u6790\uff08\u57fa\u4e8e v1.3.16 \u771f\u5b9e\u6e90\u7801\uff09\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"MMKV \u6e90\u7801\u7ea7\u5256\u6790\uff08\u57fa\u4e8e v1.3.16 \u771f\u5b9e\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/104552.html","og_locale":"zh_CN","og_type":"article","og_title":"MMKV \u6e90\u7801\u7ea7\u5256\u6790\uff08\u57fa\u4e8e v1.3.16 \u771f\u5b9e\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u5206\u6790\u5bf9\u8c61 Core\/&#xff1a;\u8de8\u5e73\u53f0 C \u6838\u5fc3&#xff08;Android \/ iOS \/ macOS \/ HarmonyOS \/ Win32 \u5171\u7528&#xff09;Android\/MMKV\/mmkv\/src\/main\/java\/&#xff1a;Android Java \u58f3\u5c42Android\/MMKV\/mmkv\/src\/main\/cpp\/native-bridge.cpp&#xff1a;JNI \u6865\u63a5\u5c42 **\u6e90\u7801\u7248\u672c&#xff1a;v1.3.16 https:\/\/githu","og_url":"https:\/\/www.wsisp.com\/helps\/104552.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-09-12T10:01:25+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"65 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/104552.html","url":"https:\/\/www.wsisp.com\/helps\/104552.html","name":"MMKV \u6e90\u7801\u7ea7\u5256\u6790\uff08\u57fa\u4e8e v1.3.16 \u771f\u5b9e\u6e90\u7801\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-09-12T10:01:25+00:00","dateModified":"2026-09-12T10:01:25+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/104552.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/104552.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/104552.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"MMKV \u6e90\u7801\u7ea7\u5256\u6790\uff08\u57fa\u4e8e v1.3.16 \u771f\u5b9e\u6e90\u7801\uff09"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/104552","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=104552"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/104552\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=104552"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=104552"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=104552"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=104552"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}