Android का 16 KB पेज साइज़ माइग्रेशन: असल में क्या टूटता है और अपना APK कैसे जांचें
Google अब चाहता है कि Android ऐप्स 16 KB मेमोरी पेज सपोर्ट करें। व्यवहार में इसका क्या मतलब है, नेटिव लाइब्रेरीज़ ही क्यों टूटती हैं, और यह कैसे जांचें कि आपकी ऐप सुरक्षित है।
अगर आपकी ऐप कोई भी नेटिव कोड ले जाती है — आपका अपना JNI, या बस कोई थर्ड-पार्टी SDK जिसमें .so फ़ाइल बंडल है — तो अच्छी संभावना है कि आप एक ऐसा माइन ढो रहे हैं जो सिर्फ नए हार्डवेयर पर फटता है। Android अब पारंपरिक 4 KB पेजों के साथ-साथ 16 KB मेमोरी पेजों को भी सपोर्ट करता है, और Google Play मांग करता है कि हाल के Android वर्ज़न को टारगेट करने वाली ऐप्स दोनों पर सही तरीके से काम करें। ज़्यादातर सिर्फ-Kotlin वाली ऐप्स इसमें से बिना किसी बदलाव के निकल जाती हैं। नेटिव डिपेंडेंसी वाली ऐप्स अक्सर नहीं निकल पातीं, और फेलियर का तरीका बदसूरत है: यह कोई lint चेतावनी नहीं, बल्कि इंस्टॉल या पहली बार खोलने पर क्रैश है — और वह भी सिर्फ उन डिवाइसों पर जो असल में 16 KB पेज इस्तेमाल करते हैं।
मैंने पूरी सुइट में यह माइग्रेशन किया — ज़्यादातर हिस्सा बिना किसी झंझट के निकल गया, सिवाय एक डिपेंडेंसी के। यहाँ बताया गया है कि यह जांच असल में क्या शामिल करती है।
पेज साइज़ क्यों मायने रखता है
मेमोरी पेज वह सबसे छोटी इकाई है जिसमें OS मेमोरी को मैनेज करता है। Android शुरू से ही 4 KB पेज इस्तेमाल करता आया है; कुछ नए चिपसेट अब डिफ़ॉल्ट रूप से 16 KB पेज इस्तेमाल करते हैं, क्योंकि बड़े पेज RAM-भारी वर्कलोड के लिए मेमोरी मैनेज करने की ओवरहेड कम करते हैं — कम पेज-टेबल एंट्रीज़, कम TLB मिस, और औसतन ऐप का तेज़ लॉन्च। OS और Android Runtime सामान्य Kotlin और Java कोड के लिए इसे पारदर्शी तरीके से हैंडल करते हैं। यह ViewModel, Room, Compose के लिए अदृश्य है — इनमें से किसी को भी नीचे वाले पेज साइज़ की परवाह नहीं।
नेटिव कोड को परवाह होती है, क्योंकि नेटिव लाइब्रेरीज़ ELF बाइनरी होती हैं, और ELF बाइनरी के लोड करने योग्य सेगमेंट बिल्ड के समय एक तय सीमा पर अलाइन किए जाते हैं। 4 KB-अलाइन सेगमेंट के साथ बना .so 4 KB-पेज डिवाइस पर ठीक चलता है। उसी फ़ाइल को 16 KB पेज चलाने वाले डिवाइस पर लोड करें, तो डायनामिक लिंकर उसे सही तरीके से मैप करने में नाकाम हो सकता है — ऐप शुरू नहीं होती, या उस लाइब्रेरी को छूते ही क्रैश हो जाती है।
असल में क्या टूटता है
आपका Kotlin कोड नहीं। असल जोखिम की लिस्ट छोटी और सटीक है:
- आपके अपने NDK/JNI मॉड्यूल्स, अगर आप कोई बनाते हैं।
- वे थर्ड-पार्टी AAR जो पहले से बनी नेटिव लाइब्रेरीज़ बंडल करते हैं — इमेज प्रोसेसिंग, क्रैश रिपोर्टिंग, डेटाबेस इंजन, ML रनटाइम। जिसके AAR के अंदर
.soहै, वह उम्मीदवार है। - पुरानी टूलचेन का आउटपुट। टूलचेन के डिफ़ॉल्ट रूप से 16 KB-अलाइन सेगमेंट बनाने से पहले, किसी पुराने NDK से बनी लाइब्रेरी — यह सबसे आम फेलियर केस है, भले ही SDK की एक्टिव मेंटेनेंस हो रही हो। बाइनरी बस तब से दोबारा बिल्ड नहीं हुई जब से अलाइनमेंट का डिफ़ॉल्ट बदला।
क्या नहीं टूटता: शुद्ध Kotlin डिपेंडेंसीज़, वह सब कुछ जो बिना नेटिव कोड के सिर्फ़ .jar या .aar के रूप में शिप होता है, और Google की अपनी फर्स्ट-पार्टी लाइब्रेरीज़ के हाल के वर्ज़न, जो पहले ही सही अलाइनमेंट के साथ दोबारा बनाई जा चुकी हैं।
अपने APK में असल में क्या है, यह जांचना
बिल्ड कॉन्फ़िग को छूने से पहले, यह पता करें कि आप असल में जोखिम में हैं या नहीं:
unzip -l app-release.apk | grep '\.so$'
अगर इससे कुछ नहीं मिलता, तो आपका काम हो गया — अलाइन करने के लिए कोई नेटिव कोड नहीं है। अगर एंट्रीज़ मिलती हैं, तो हर लाइब्रेरी की सेगमेंट अलाइनमेंट सीधे जांचें:
unzip -p app-release.apk lib/arm64-v8a/libsomething.so | \
readelf -l - | grep LOAD
हर LOAD सेगमेंट के Align कॉलम को देखें। 0x4000 (16 KB) का मतलब है वह लाइब्रेरी पहले से सही तरीके से अलाइन है। 0x1000 (4 KB) का मतलब है नहीं है, और यही वह है जिसका पीछा करना है — या तो जिस SDK से आई, उसका अपडेटेड वर्ज़न, या अगर यह आपका अपना कोड है तो दोबारा बिल्ड।
Android Studio का APK Analyzer कमांड लाइन के बिना यही जानकारी दिखाता है: APK खोलें, lib/ के नीचे किसी .so फ़ाइल में जाएं, और यह सिर्फ़-4 KB अलाइनमेंट को सीधे फ्लैग करता है।
समाधान, आपके पास कितना नियंत्रण है उसके क्रम में
- आपका अपना नेटिव कोड: एक मौजूदा NDK के साथ दोबारा बिल्ड करें। हाल की टूलचेन वर्ज़न डिफ़ॉल्ट रूप से 16 KB-अलाइन आउटपुट बनाती हैं, तो यह अक्सर सिर्फ़
build.gradle.ktsमें वर्ज़न बंप और एक क्लीन रीबिल्ड होता है — सोर्स कोड में कोई बदलाव नहीं। - पुराने
.soवाला थर्ड-पार्टी SDK: डिपेंडेंसी अपडेट करें। लगभग हर एक्टिव रूप से मेंटेन किए जा रहे SDK ने 16 KB-अलाइन बिल्ड शिप कर दिया है; समाधान वर्क-अराउंड नहीं, वर्ज़न बंप है। - वह डिपेंडेंसी जो अपडेट नहीं हुई: यह असहज मामला है। आपके असल विकल्प हैं: SDK के खिलाफ एक इशू फाइल करना, अगर ओपन सोर्स है तो फोर्क करके दोबारा बिल्ड करना, या डिपेंडेंसी हटाना। कोई APK-लेवल ट्रिक नहीं है जो आपके द्वारा न बनाई गई
.soको दोबारा अलाइन कर दे।
जिस लाइब्रेरी ने मुझे पकड़ा वह ठीक केस 2 थी — एक डेटाबेस एक्सटेंशन जो Granyn की ट्रांज़ैक्शन हिस्ट्री के पीछे के एट-रेस्ट एन्क्रिप्शन के लिए पहले से बनी नेटिव बाइनरीज़ शिप कर रहा था। एक छोटे वर्ज़न बंप ने अलाइन बिल्ड ला दी; इंटीग्रेशन कोड में कुछ भी नहीं बदला।
असल 16 KB डिवाइस पर टेस्ट करना
अलाइनमेंट चेक बताते हैं कि क्या होना चाहिए; असल 16 KB पेजों पर टेस्ट करना बताता है कि क्या होता है। Android Emulator में खासतौर पर इसके लिए बनी सिस्टम इमेजेस आती हैं — SDK Manager में किसी हाल के API लेवल का “16 KB Page Size” वैरिएंट खोजें, उससे एक AVD बनाएं, और अपना APK ठीक वैसे ही इंस्टॉल करें जैसे रिलीज़ के लिए करते। अगर कोई ऐसी चीज़ जो एक बिना-अलाइन लाइब्रेरी इस्तेमाल करती है, क्रैश होने वाली है, तो वह वहीं, तुरंत और दोबारा-पैदा-करने-लायक तरीके से क्रैश होगी — जो किसी ऐसे डिवाइस से आई सपोर्ट टिकट से कहीं बेहतर जगह है जो आपके पास नहीं है।
निष्कर्ष
ज़्यादातर Kotlin-प्रधान ऐप्स के लिए यह माइग्रेशन अदृश्य है — कोई नेटिव कोड नहीं, कोई जोखिम नहीं, करने के लिए कुछ नहीं। जो भी नेटिव डिपेंडेंसीज़ खींचती है, उसके लिए समाधान लगभग हमेशा दोबारा-लिखना नहीं, बल्कि डिपेंडेंसी वर्ज़न बंप होता है: readelf से बिना-अलाइन .so ढूंढें, जिसने उसे शिप किया उसे अपडेट करें, दोबारा बिल्ड करें, और शिप करने से पहले 16 KB सिस्टम इमेज पर वेरिफाई करें। यह जांच दस मिनट लेती है। इसे छोड़ना मतलब इसे बाद में क्रैश रिपोर्ट से जानना।
// संबंधित पठन
जर्नल से और भी
Android का In-App Review API: बिना परेशान किए रेटिंग माँगना
Google के In-App Review API की एक व्यावहारिक गाइड — यह असल में कैसे काम करता है, इसे कब ट्रिगर करना चाहिए, और सामान्य 'हमें रेट करें' पॉपअप आपकी Play Store रेटिंग को चुपचाप कैसे नुकसान पहुँचा रहा है।
Android ऐप शॉर्टकट्स और Quick Settings Tiles: बिना ऐप खोले पानी लॉग करना
Android के डायनामिक ShortcutManager API और TileService की एक व्यावहारिक गाइड — कैसे एक-टैप एक्शन को पूरी तरह ऐप को छोड़कर काम करने दें, साथ ही वे गड़बड़ियाँ जो ज़्यादातर इम्प्लीमेंटेशन को फँसा देती हैं।
2026 में Android पर फोरग्राउंड सर्विस टाइप्स: वह चुनना जो आपके फीचर पर सच में लागू हो
Android के फोरग्राउंड सर्विस टाइप प्रतिबंधों की एक व्यावहारिक गाइड — dataSync, mediaPlayback, specialUse, shortService — और बिना मारे या रिजेक्ट हुए सही वाला कैसे चुनें।