محدودیت ها

یک فایل .dex فرمت انتقال بایت کد Dalvik است. برای اینکه یک فایل یک فایل .dex معتبر باشد، محدودیت‌های نحوی و معنایی خاصی وجود دارد و برای پشتیبانی از فایل‌های .dex معتبر، زمان اجرا لازم است.

محدودیت های یکپارچگی عمومی .dex

محدودیت‌های یکپارچگی کلی مربوط به ساختار بزرگ‌تر یک فایل .dex است، همانطور که در قالب .dex به تفصیل توضیح داده شده است.

مشخص کننده شرح
G1 شماره magic فایل .dex باید dex\n035\0 یا dex\n037\0 باشد.
G2 چک‌سوم باید یک جمع‌سنجی Adler-32 از کل محتویات فایل به جز magic و فیلد checksum باشد.
G3 امضا باید یک هش SHA-1 از کل محتویات فایل به جز magic ، checksum و signature باشد.
G4 file_size باید با اندازه واقعی فایل بر حسب بایت مطابقت داشته باشد.
G5 header_size باید مقدار 0x70 را داشته باشد
G6 endian_tag باید دارای یک مقدار باشد: ENDIAN_CONSTANT یا REVERSE_ENDIAN_CONSTANT
G7 برای هر یک از link ، string_ids ، type_ids ، proto_ids ، field_ids ، method_ids ، class_defs و بخش‌های data ، فیلدهای offset و size باید هر دو صفر یا غیرصفر باشند. در مورد دوم، افست باید چهار بایت تراز شود.
G8 تمام فیلدهای offset در هدر به جز map_off باید چهار بایت تراز شوند.
G9 فیلد map_off باید یا صفر باشد یا به بخش داده اشاره کند. در مورد دوم، بخش data باید وجود داشته باشد.
G10 هیچ یک از link ، string_ids ، type_ids ، proto_ids ، field_ids ، method_ids ، class_defs و بخش‌های data نباید با یکدیگر یا سربرگ همپوشانی داشته باشند.
G11 اگر نقشه وجود داشته باشد، هر ورودی نقشه باید یک نوع معتبر داشته باشد. هر نوع ممکن است حداکثر یک بار ظاهر شود.
G12 اگر نقشه ای وجود داشته باشد، هر ورودی نقشه باید یک افست و اندازه غیر صفر داشته باشد. افست باید به بخش مربوط به فایل اشاره کند (یعنی یک string_id_item باید به بخش string_ids اشاره کند) و اندازه صریح یا ضمنی آیتم باید با محتویات و اندازه واقعی بخش مطابقت داشته باشد.
G13 اگر نقشه ای وجود داشته باشد، آنگاه افست ورودی نقشه n+1 باید بزرگتر یا مساوی با افست ورودی نقشه n plus than size of map entry n باشد. این به معنای ورودی های غیر همپوشانی و سفارش کم به بالا است.
G14 انواع ورودی‌های زیر باید دارای یک افست چهار بایتی باشند: string_id_item ، type_id_item ، proto_id_item ، field_id_item ، method_id_item ، class_def_item ، type_list ، code_item ، annotations_directory_item .
G15 برای هر string_id_item ، فیلد string_data_off باید دارای یک مرجع معتبر در بخش data باشد. برای string_data_item ارجاع شده، فیلد data باید دارای یک رشته معتبر MUTF-8 باشد و utf16_size باید با طول رمزگشایی شده رشته مطابقت داشته باشد.
G16 برای هر type_id_item ، فیلد descriptor_idx باید حاوی یک مرجع معتبر در لیست string_ids باشد. رشته ارجاع شده باید یک توصیفگر نوع معتبر باشد.
G17 برای هر proto_id_item ، فیلد shorty_idx باید حاوی یک مرجع معتبر در لیست string_ids باشد. رشته ارجاع شده باید یک توصیف کننده کوتاه معتبر باشد. همچنین، فیلد return_type_idx باید یک شاخص معتبر در بخش type_ids باشد و فیلد parameters_off باید صفر باشد یا یک افست معتبر که به بخش data اشاره می‌کند. اگر غیر صفر باشد، لیست پارامترها نباید حاوی هیچ ورودی خالی باشد.
G18 برای هر field_id_item ، هر دو فیلد class_idx و type_idx باید شاخص‌های معتبری در لیست type_ids باشند. ورودی ارجاع شده توسط class_idx باید یک نوع مرجع غیر آرایه باشد. علاوه بر این، فیلد name_idx باید یک مرجع معتبر در بخش string_ids باشد و محتوای ورودی ارجاع شده باید با مشخصات MemberName مطابقت داشته باشد.
G19 برای هر method_id_item ، فیلد class_idx باید یک شاخص معتبر در بخش type_ids باشد و ورودی ارجاع شده باید یک نوع مرجع غیر آرایه باشد. فیلد proto_id باید یک مرجع معتبر در لیست proto_ids باشد. فیلد name_idx باید یک مرجع معتبر در بخش string_ids باشد و محتوای ورودی ارجاع شده باید با مشخصات MemberName مطابقت داشته باشد.
G20 برای هر field_id_item ، فیلد class_idx باید یک فهرست معتبر در لیست type_ids باشد. ورودی ارجاع شده باید یک نوع مرجع غیر آرایه باشد.

محدودیت های بایت کد استاتیک

محدودیت‌های استاتیک، محدودیت‌هایی بر روی عناصر جداگانه بایت کد هستند. آنها معمولاً می توانند بدون استفاده از تکنیک های کنترل یا تجزیه و تحلیل جریان داده بررسی شوند.

مشخص کننده شرح
A1 آرایه insns نباید خالی باشد.
A2 اولین اپکد در آرایه insns باید دارای اندیس صفر باشد.
A3 آرایه insns باید فقط دارای کدهای آپشن معتبر Dalvik باشد.
A4 شاخص دستور n+1 باید با شاخص دستورالعمل n به اضافه طول دستورالعمل n برابر باشد، با در نظر گرفتن عملوندهای ممکن.
A5 آخرین دستور در آرایه insns باید به شاخص insns_size-1 ختم شود.
A6 همه اهداف goto و if-<kind> باید کدهای عملیاتی در یک روش باشند.
A7 تمام اهداف یک دستورالعمل packed-switch باید کدهای عملیاتی در همان روش باشند. اندازه و فهرست اهداف باید هماهنگ باشد.
A8 تمام اهداف یک دستورالعمل sparse-switch باید کدهای عملیاتی در همان روش باشند. جدول مربوطه باید سازگار و مرتب شده از کم به بالا باشد.
A9 عملوند B دستورات const-string و const-string/jumbo باید یک شاخص معتبر در مجموعه ثابت رشته باشد.
A10 عملوند C دستورات iget<kind> و iput<kind> باید یک شاخص معتبر در مخزن ثابت فیلد باشد. ورودی ارجاع شده باید نمایانگر یک فیلد نمونه باشد.
A11 عملوند C دستورات sget<kind> و sput<kind> باید یک شاخص معتبر در مخزن ثابت فیلد باشد. ورودی ارجاع شده باید نمایانگر یک فیلد ثابت باشد.
A12 عملوند C دستورات invoke-virtual ، invoke-super ، invoke-direct و invoke-static باید یک شاخص معتبر در استخر ثابت متد باشد.
A13 عملوند B دستورات invoke-virtual/range ، invoke-super/range ، invoke-direct/range و invoke-static/range باید یک شاخص معتبر در مخزن ثابت متد باشد.
A14 روشی که نام آن با «<» شروع می‌شود فقط باید به طور ضمنی توسط VM فراخوانی شود، نه با کدی که از یک فایل .dex منشا می‌گیرد. تنها استثناء اولیه ساز نمونه است که ممکن است توسط invoke-direct فراخوانی شود.
A15 عملوند C دستور invoke-interface باید یک شاخص معتبر در مخزن ثابت متد باشد. method_id ارجاع شده باید به یک رابط (نه کلاس) تعلق داشته باشد.
A16 عملوند B دستور invoke-interface/range باید یک شاخص معتبر در مخزن ثابت متد باشد. method_id ارجاع شده باید به یک رابط (نه کلاس) تعلق داشته باشد.
A17 عملوند B دستورات const-class ، check-cast ، new-instance و filled-new-array/range باید یک شاخص معتبر در مخزن ثابت نوع باشد.
A18 عملوند C دستورات instance-of ، new-array و filled-new-array باید یک شاخص معتبر برای نوع ثابت Pool باشد.
A19 ابعاد یک آرایه ایجاد شده توسط یک دستور new-array باید کمتر از 256 باشد.
A20 دستورالعمل new نباید به کلاس های آرایه، رابط ها یا کلاس های انتزاعی اشاره کند.
A21 نوع ارجاع شده توسط یک دستورالعمل new-array باید یک نوع معتبر و غیر مرجع باشد.
A22 همه رجیسترهایی که توسط یک دستورالعمل به صورت تک عرض (غیر جفتی) ارجاع می شوند باید برای روش فعلی معتبر باشند. یعنی شاخص های آنها باید غیر منفی و کوچکتر از registers_size باشد.
A23 همه رجیسترهایی که توسط یک دستورالعمل به صورت دو عرض (جفت) ارجاع می شوند باید برای روش فعلی معتبر باشند. یعنی شاخص های آنها باید غیر منفی و کوچکتر از registers_size-1 باشد.
A24 عملوند method_id دستورات invoke-virtual و invoke-direct باید متعلق به یک کلاس (نه یک رابط) باشد. در فایل‌های Dex قبل از نسخه 037 همین امر باید در مورد دستورالعمل‌های invoke-super و invoke-static صادق باشد.
A25 عملوند method_id دستورات invoke-virtual/range و invoke-direct/range باید به یک کلاس تعلق داشته باشد (نه یک رابط). در فایل‌های Dex قبل از نسخه 037 همین امر باید در مورد دستورالعمل‌های invoke-super/range و invoke-static/range صادق باشد.

محدودیت های بایت کد ساختاری

محدودیت های ساختاری محدودیت هایی در روابط بین چندین عنصر بایت کد هستند. آنها معمولاً بدون استفاده از تکنیک های کنترل یا تجزیه و تحلیل جریان داده قابل بررسی نیستند.

مشخص کننده شرح
B1 تعداد و انواع آرگومان ها (رجیسترها و مقادیر فوری) باید همیشه با دستورالعمل مطابقت داشته باشد.
B2 جفت های ثبت نام هرگز نباید از هم جدا شوند.
B3 یک ثبات (یا جفت) ابتدا باید قبل از خواندن آن اختصاص داده شود.
B4 یک دستور invoke-direct باید یک نمونه اولیه یا یک متد را فقط در کلاس فعلی یا یکی از ابر کلاس های آن فراخوانی کند.
B5 یک نمونه اولیه باید فقط در یک نمونه غیر اولیه فراخوانی شود.
B6 روش‌های نمونه را می‌توان فقط در فراخوانی کرد و فیلدهای نمونه را فقط در نمونه‌هایی که از قبل مقداردهی شده‌اند قابل دسترسی هستند.
B7 اگر همان دستورالعمل new-instance قبل از مقداردهی اولیه مجدداً اجرا شود، ثباتی که نتیجه یک دستورالعمل new-instance در خود نگه می دارد، نباید استفاده شود.
B8 قبل از اینکه بتوان به اعضای نمونه دسترسی داشت، یک مقداردهی اولیه باید یک نمونه اولیه دیگر (همان کلاس یا سوپرکلاس) را فراخوانی کند. استثنائات، فیلدهای نمونه غیر ارثی هستند که می توان آنها را قبل از فراخوانی مقداردهی اولیه دیگر و به طور کلی کلاس Object اختصاص داد.
B9 همه آرگومان های متد واقعی باید با آرگومان های رسمی مربوطه خود سازگار با انتساب باشند.
B10 برای هر فراخوانی روش نمونه، نمونه واقعی باید با کلاس یا رابط مشخص شده در دستورالعمل سازگار باشد.
B11 یک دستور return<kind> باید با نوع برگشتی متد خود مطابقت داشته باشد.
B12 هنگام دسترسی به اعضای محافظت شده یک سوپرکلاس، نوع واقعی نمونه مورد دسترسی باید کلاس فعلی یا یکی از زیر کلاس های آن باشد.
B13 نوع مقدار ذخیره شده در یک فیلد ثابت باید با نوع فیلد سازگار باشد یا به آن تبدیل شود.
B14 نوع مقدار ذخیره شده در یک فیلد باید با نوع فیلد سازگار باشد یا به آن تبدیل شود.
B15 نوع هر مقدار ذخیره شده در یک آرایه باید با نوع مولفه آرایه سازگار باشد.
B16 عملوند A دستور throw باید با java.lang.Throwable سازگار باشد.
B17 آخرین دستورالعمل قابل دسترسی یک متد باید یا یک goto به عقب یا شاخه، یک return یا یک دستورالعمل throw باشد. نباید امکان رها کردن آرایه insns در پایین وجود داشته باشد.
B18 نصف تخصیص‌نخورده یک جفت رجیستر سابق نمی‌تواند خوانده شود (نامعتبر در نظر گرفته می‌شود) تا زمانی که توسط دستورالعمل دیگری تخصیص داده نشده باشد.
B19 یک دستور move-result<kind> باید بلافاصله قبل از (در آرایه insns ) یک دستور invoke-<kind> باشد. تنها استثنا دستور move-result-object است که ممکن است قبل از یک دستور filled-new-array نیز باشد.
B20 دستور move-result<kind> باید بلافاصله قبل از آن (در جریان کنترل واقعی) با یک دستورالعمل return-<kind> منطبق باشد (نباید به آن پرش کرد). تنها استثنا دستور move-result-object است که ممکن است قبل از یک دستور filled-new-array نیز باشد.
B21 یک دستور move-exception باید فقط به عنوان اولین دستورالعمل در یک کنترل کننده استثنا ظاهر شود.
B22 دستورات شبه packed-switch-data ، sparse-switch-data ، و fill-array-data نباید توسط جریان کنترل قابل دسترسی باشند.