במסמך הזה מתוארים הפריסה והתוכן של קובצי .dex
, שמשמשים לאחסון קבוצה של הגדרות של כיתות והנתונים המשניים המשויכים אליהן.
מדריך לסוגי המודעות
שם | תיאור |
---|---|
בייט | int signed 8-bit |
ubyte | int לא חתום של 8 ביט |
סרטון קצר | int signed 16-bit, little-endian |
ushort | int לא חתום של 16 ביט, little-endian |
INT | מספר שלם עם סימן באורך 32 ביט, בסדר קטן-גדול |
uint | int לא חתום של 32 ביט, little-endian |
ארוך | int signed של 64 ביט, little-endian |
ulong | int לא חתום של 64 ביט, little-endian |
sleb128 | LEB128 חתום, באורך משתנה (ראו בהמשך) |
uleb128 | LEB128 ללא סימן, באורך משתנה (ראו בהמשך) |
uleb128p1 | LEB128 ללא סימן ו-1 , באורך משתנה (ראו בהמשך) |
LEB128
LEB128 ('Little-Endian Base 128') הוא קידוד באורך משתנה של כמויות שלמים שרירותיים עם סימן או ללא סימן. הפורמט הועתק מהמפרט של DWARF3. בקובץ .dex
, LEB128 משמש רק לקידוד כמויות של 32 ביט.
כל ערך בקידוד LEB128 מורכב מבאיט אחד עד חמישה, שמייצגים יחד ערך יחיד של 32 ביט. כל בייט מוגדר לפי הביט המשמעותי ביותר שלו, מלבד הבייט האחרון ברצף, שהביט המשמעותי ביותר שלו לא מוגדר. שבע הביטים הנותרים בכל בייט הם נתוני המטען, כאשר שבע הביטים הפחות משמעותיים של הכמות נמצאים בבייטים הראשון, שבע הביטים הבאים נמצאים בבייטים השני וכן הלאה. במקרה של LEB128 עם סימן (sleb128
), ביט המטען המשמעותי ביותר של הבייט האחרון ברצף מורחב עם סימן כדי ליצור את הערך הסופי. במקרה ללא סימן (uleb128
), כל הביטים שלא מיוצגים באופן מפורש מפורשים כ-0
.
תרשים ביטתי של ערך LEB128 באורך שני בייטים | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
הבייט הראשון | הבייט השני | ||||||||||||||
1 |
ביט6 | bit5 | ביט4 | ביט3 | ביט2 | ביט1 | ביט0 | 0 |
ביט13 | bit12 | ביט11 | bit10 | ביט9 | bit8 | ביט7 |
הווריאנט uleb128p1
משמש לייצוג ערך חתום, שבו הייצוג הוא הערך פלוס אחד בקידוד uleb128
. כך, קידוד הערך -1
(או הערך ללא סימן 0xffffffff
) – אבל לא מספר שלילי אחר – הוא ביייט אחד, והוא שימושי בדיוק במקרים שבהם המספר שמיוצג חייב להיות חיובי או -1
(או 0xffffffff
), ושאין ערכים שליליים אחרים שמותר להשתמש בהם (או במקרים שבהם סביר להניח שלא תצטרכו ערכים גדולים ללא סימן).
ריכזנו כאן כמה דוגמאות לפורמטים:
רצף מקודד | בתור sleb128 |
בתור uleb128 |
בתור uleb128p1 |
---|---|---|---|
00 | 0 | 0 | -1 |
01 | 1 | 1 | 0 |
7f | -1 | 127 | 126 |
80 7f | -128 | 16256 | 16255 |
פריסת הקובץ
שם | פורמט | תיאור |
---|---|---|
כותרת | header_item | הכותרת |
string_ids | string_id_item[] | רשימת מזהים של מחרוזות. אלה מזהים לכל המחרוזות שבהן הקובץ הזה משתמש, לצורכי שמות פנימיים (למשל, מתארי טיפוסים) או כאובייקטים קבועים שמקודם מפנה אליהם. הרשימה הזו צריכה להיות ממוינת לפי תוכן המחרוזת, באמצעות ערכי נקודות קוד של UTF-16 (לא באופן תלוי-אזור), בלי להכיל רשומות כפולות. |
type_ids | type_id_item[] | רשימת מזהי הסוגים. אלה המזהים של כל הסוגים (כיתות, מערכי נתונים או סוגים פרימיטיביים) שהקובץ הזה מפנה אליהם, בין שהם מוגדרים בקובץ ובין שלא. הרשימה הזו חייבת להיות ממוינת לפי אינדקס string_id , ואי אפשר לכלול בה רשומות כפולות.
|
proto_ids | proto_id_item[] | רשימת המזהים של אב טיפוס השיטה. אלה המזהים של כל אב הטיפוס שאליו מתייחס הקובץ הזה. הרשימה הזו צריכה להיות ממוינת לפי סדר ראשי של סוג ההחזרה (לפי אינדקס type_id ), ואז לפי רשימת הארגומנטים (מיון לקסיקלי, ארגומנטים נפרדים שממוינים לפי אינדקס type_id ). הרשימה לא יכולה לכלול רשומות כפולות.
|
field_ids | field_id_item[] | רשימת מזהי השדות. אלה המזהים של כל השדות שאליהם מתייחס הקובץ, בין שהם מוגדרים בקובץ ובין שלא. הרשימה הזו צריכה להיות ממוינת, כאשר הסוג המגדיר (לפי אינדקס type_id ) הוא הסדר הראשי, שם השדה (לפי אינדקס string_id ) הוא הסדר הביניים והסוג (לפי אינדקס type_id ) הוא הסדר המשני. הרשימה לא יכולה לכלול רשומות כפולות.
|
method_ids | method_id_item[] | רשימת מזהי השיטות. אלה המזהים של כל השיטות שאל הקובץ הזה מפנה אליהן, בין שהן מוגדרות בקובץ ובין שלא. הרשימה הזו צריכה להיות ממוינת, כאשר הסוג המגדיר (לפי אינדקס type_id ) הוא הסדר הראשי, שם method (לפי אינדקס string_id ) הוא הסדר הביניים ו-method prototype (לפי אינדקס proto_id ) הוא הסדר המשני. הרשימה לא יכולה לכלול רשומות כפולות.
|
class_defs | class_def_item[] | רשימת הגדרות הכיתות. הכיתות צריכות להיות מסודרות כך שסופר-הקלאס של הכיתה הנתונה והממשקים המוטמעים שלה יופיעו ברשימה לפני הכיתה המפנה. בנוסף, לא ניתן להגדיר כיתה באותו שם יותר מפעם אחת ברשימה. |
call_site_ids | call_site_id_item[] | רשימת המזהים של אתרי השיחות. אלה המזהים של כל אתרי הקריאה שאליהם מתייחס הקובץ הזה, גם אם הם מוגדרים בקובץ וגם אם לא. הרשימה הזו צריכה להיות ממוינת בסדר עולה של call_site_off .
|
method_handles | method_handle_item[] | method מטפלת ברשימה. רשימה של כל רכיבי ה-method handle שאליהם מתייחס הקובץ הזה, גם אם הם מוגדרים בקובץ וגם אם לא. הרשימה הזו לא ממוינת ועשויה להכיל כפילויות שתואמות באופן לוגי למופעים שונים של פקדי שיטות. |
נתונים | ubyte[] | אזור נתונים שמכיל את כל נתוני התמיכה של הטבלאות שצוינו למעלה. לפריטים שונים יש דרישות התאמה שונות, ואפשר להוסיף בייטים של מילוי לפני כל פריט אם צריך כדי להשיג התאמה נכונה. |
link_data | ubyte[] | נתונים שמשמשים בקבצים מקושרים באופן סטטי. הפורמט של הנתונים בקטע הזה לא מצוין במסמך הזה. הקטע הזה ריק בקבצים ללא קישור, והטמעות בסביבת זמן הריצה יכולות להשתמש בו כפי שהן רואות לנכון. |
פורמט הקונטיינר
בגרסה 41 נוסף פורמט מאגר חדש לנתוני DEX, במטרה לחסוך מקום. פורמט הקונטיינר הזה מאפשר לשלב כמה קובצי DEX לוגיים בקובץ פיזי אחד. הפורמט החדש הוא בעיקר רק שרשור פשוט של קבצים בפורמט הקודם, עם כמה הבדלים:
- הערך של
file_size
הוא הגודל של הקובץ הלוגי, ולא של הקובץ הפיזי. אפשר להשתמש בו כדי להריץ איטרציה על כל הקבצים הלוגיים בקונטיינר. - קובצי dex לוגיים יכולים להפנות לנתונים מאוחרים יותר בקונטיינר (אבל לא לנתונים קודמים). כך קבצי dex יכולים לשתף ביניהם נתונים, כמו מחרוזות.
- כל הזזות האופרטור הן ביחס לקובץ הפיזי. אין שום הזזה ביחס לכותרת. כך אפשר לשתף קטעים עם סטיות בין קבצים לוגיים.
- הכותרת מוסיפה שני שדות חדשים שמתארים את גבולות המאגר. זוהי בדיקת עקביות נוספת, והיא מאפשרת להעביר קוד לפורמט החדש בקלות רבה יותר.
- התגים
data_size
ו-data_off
לא בשימוש. הנתונים יכולים להיות מפוזרים במספר קבצים לוגיים, והם לא חייבים להיות רציפים.
הגדרות של שדות ביט, מחרוזות וקבועים
DEX_FILE_MAGIC
מוטמע ב-header_item
מערך/מחרוזת הקבוע DEX_FILE_MAGIC
הוא רשימת הבייטים שצריכה להופיע בתחילת קובץ .dex
כדי שהוא יזוהה ככזה. הערך מכיל בכוונה שורת חדשה ("\n"
או 0x0a
) ו-byte null ("\0"
או 0x00
) כדי לעזור בזיהוי של צורות מסוימות של פגיעה. הערך גם מכיל קידוד של מספר גרסת הפורמט בתור שלוש ספרות עשרוניות, שצפוי לעלות באופן מונוטוני לאורך זמן ככל שהפורמט יתפתח.
ubyte[8] DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x39 0x00 } = "dex\n039\0"
הערה: התמיכה בגרסה 040
של הפורמט נוספה במהדורה 10.0 של Android, והרחיבה את קבוצת התווים המותרים ב-SimpleNames.
הערה: התמיכה בגרסה 039
של הפורמט נוספה במהדורה 9.0 של Android, שבה הוצגו שני בייטים חדשים, const-method-handle
ו-const-method-type
. (האפשרויות האלה מתוארות בטבלה סיכום של קבוצת קוד באקטי (bytecode)). ב-Android 10, גרסה 039
מרחיבה את פורמט קובץ ה-DEX כך שיכלול מידע API מוסתר שרלוונטי רק לקובצי DEX בנתיב של סיווג האתחול.
הערה: התמיכה בגרסה 038
של הפורמט נוספה במהדורה 8.0 של Android. בגרסה 038
נוספו קודי בייט חדשים (invoke-polymorphic
ו-invoke-custom
) ונתונים למטמון השיטות.
הערה: התמיכה בגרסה 037
של הפורמט נוספה במהדורת Android 7.0. לפני הגרסה 037
, רוב הגרסאות של Android השתמשו בגרסה 035
של הפורמט. ההבדל היחיד בין הגרסאות 035
ו-037
הוא הוספת שיטות ברירת מחדל והתאמת invoke
.
הערה: לפחות כמה גרסאות קודמות של הפורמט שימשו במהדורות תוכנה ציבוריות שזמינות באופן נרחב. לדוגמה, גרסה 009
שימשה למהדורות M3 של פלטפורמת Android (נובמבר-דצמבר 2007), וגרסה 013
שימשה למהדורות M5 של פלטפורמת Android (פברואר-מרץ 2008). יש כמה הבדלים משמעותיים בין הגרסאות הקודמות של הפורמט לבין הגרסה שמתוארת במסמך הזה.
ENDIAN_CONSTANT ו-REVERSE_ENDIAN_CONSTANT
מוטמע ב-header_item
הקבוע ENDIAN_CONSTANT
משמש לציון endianness של הקובץ שבו הוא נמצא. אמנם הפורמט הסטנדרטי של .dex
הוא little-endian, אבל בהטמעות מסוימות יכול להיות שיתבצע החלפת בייטים. אם במהלך הטמעה יתגלה כותרת שבה הערך של endian_tag
הוא REVERSE_ENDIAN_CONSTANT
במקום ENDIAN_CONSTANT
, תהיה אפשרות לדעת שהקובץ עבר החלפה של ביטים מהפורמט הצפוי.
uint ENDIAN_CONSTANT = 0x12345678; uint REVERSE_ENDIAN_CONSTANT = 0x78563412;
NO_INDEX
מוטמעים ב-class_def_item וב-debug_info_item
הקבוע NO_INDEX
משמש לציון שהערך של המדד חסר.
הערה: הערך הזה לא מוגדר כ-0
, כי בדרך כלל זהו אינדקס תקין.
הערך שנבחר ל-NO_INDEX
יכול להיות מיוצג כבייט יחיד בקידוד uleb128p1
.
uint NO_INDEX = 0xffffffff; // == -1 if treated as a signed int
הגדרות של access_flags
מוטמע ב-class_def_item, encoded_field, encoded_method ו-InnerClass
שדות הביט של הדגלים האלה משמשים לציון הנגישות והמאפיינים הכוללים של כיתות ומשתני מחלקה.
שם | ערך | לכיתות (ולתווית הערה InnerClass ) |
לשדות | לשיטות |
---|---|---|---|---|
ACC_PUBLIC | 0x1 | public : גלוי בכל מקום |
public : גלוי בכל מקום |
public : גלוי בכל מקום |
ACC_PRIVATE | 0x2 | private : גלוי רק לכיתה המגדירה
|
private : גלוי רק לכיתה המגדירה |
private : גלוי רק לכיתה המגדירה |
ACC_PROTECTED | 0x4 | protected : גלוי לחבילה ולתת-הסוגים
|
protected : גלוי לחבילה ולתת-כיתות |
protected : גלוי לחבילה ולתת-כיתות |
ACC_STATIC | 0x8 | static : לא נוצר באמצעות הפניה חיצונית של this |
static : גלובלי לכיתה המגדירה |
static : לא מקבלת ארגומנט this |
ACC_FINAL | 0x10 | final : לא ניתן ליצור צאצאים שלהם |
final : לא ניתן לשינוי אחרי היצירה |
final : לא ניתן לשנות |
ACC_SYNCHRONIZED | 0x20 | synchronized : נעילת המפתח שמשויכת לקריאה לשיטה הזו נרכשת באופן אוטומטי. הערה: אפשר להגדיר את הערך הזה רק כשגם הערך |
||
ACC_VOLATILE | 0x40 | volatile : כללי גישה מיוחדים שיעזרו לשמור על הבטיחות בשרשור |
||
ACC_BRIDGE | 0x40 | שיטת גשר, שנוספת באופן אוטומטי על ידי המהדר כגשר בטוח לסוגים | ||
ACC_TRANSIENT | 0x80 | transient : לא יישמרו בסריאליזציה כברירת מחדל |
||
ACC_VARARGS | 0x80 | הארגומנט האחרון צריך להיחשב כארגומנט 'שאר' על ידי המהדר | ||
ACC_NATIVE | 0x100 | native : מוטמע בקוד Native |
||
ACC_INTERFACE | 0x200 | interface : מחלקה מופשטת שאפשר להטמיע אותה בכמה דרכים |
||
ACC_ABSTRACT | 0x400 | abstract : לא ניתן ליצור אובייקט ישירות |
abstract : לא מיושם על ידי הכיתה הזו |
|
ACC_STRICT | 0x800 | strictfp : כללים מחמירים לחשבון של נקודה צפה |
||
ACC_SYNTHETIC | 0x1000 | לא מוגדרים ישירות בקוד המקור | לא מוגדרים ישירות בקוד המקור | לא מוגדרים ישירות בקוד המקור |
ACC_ANNOTATION | 0x2000 | מוצהרת ככיתה של הערות | ||
ACC_ENUM | 0x4000 | מוצהרים כסוגים של ערכים ממוספרים | מוצהר כערך ממוספר | |
(לא בשימוש) | 0x8000 | |||
ACC_CONSTRUCTOR | 0x10000 | שיטת constructor (מפעילה של סוג או מופע) | ||
ACC_DECLARED_ SYNCHRONIZED |
0x20000 | הצהרת על synchronized . הערה: אין לכך השפעה על הביצוע (מלבד השתקפות הדגל הזה, כשלעצמו). |
InnerClass
, אסור להפעיל אותה ב-class_def_item
.
קידוד UTF-8 שעבר שינוי
כדי לאפשר תמיכה קלה יותר בקוד מדור קודם, הפורמט .dex
מקודד את נתוני המחרוזות שלו בצורה של UTF-8 שהותאמה לתקן בפועל, שנקראת מעכשיו MUTF-8. הטופס הזה זהה ל-UTF-8 רגיל, מלבד:
- נעשה שימוש רק בקידוד של בייטים אחדים, שניים ושלושה.
- נקודות קוד בטווח
U+10000
…U+10ffff
מקודדות כזוג סמלי עזר, שכל אחד מהם מיוצג כערך מקודד בן שלושה בייטים. - נקודת הקוד
U+0000
מקודדת בפורמט של שני בייטים. - בית אפס רגיל (ערך
0
) מציין את סוף המחרוזת, בהתאם למשמעות הרגילה בשפת C.
אפשר לסכם את שני הפריטים הראשונים שלמעלה כך: MUTF-8 הוא פורמט קידוד של UTF-16, במקום פורמט קידוד ישיר יותר של תווים ב-Unicode.
שני הפריטים האחרונים שלמעלה מאפשרים לכלול בו-זמנית את נקודת הקוד U+0000
במחרוזת וגם לבצע בה מניפולציות כמחרוזת מסוג C עם סיומת null.
עם זאת, הקידוד המיוחד של U+0000
אומר שבניגוד ל-UTF-8 רגיל, התוצאה של קריאה לפונקציית C הרגילה strcmp()
על זוג מחרוזות MUTF-8 לא תמיד מציינת את התוצאה החתומה כראוי של השוואה בין מחרוזות לא שוות.
כשחשוב לשמור על הסדר (ולא רק על השוויון), הדרך הפשוטה ביותר להשוות בין מחרוזות MUTF-8 היא לפענח אותן תו אחר תו ולהשוות בין הערכים שפורשו. (עם זאת, אפשר גם לבצע הטמעות חכמות יותר).
מידע נוסף על קידוד תווים זמין בתקן Unicode. למעשה, MUTF-8 קרוב יותר לקידוד CESU-8 (פחות ידוע יחסית) מאשר ל-UTF-8.
קידוד של encoded_value
מוטמע ב-annotation_element וב-encoded_array_item
encoded_value
הוא קטע נתונים מקודד של נתונים (כמעט) שרירותיים שמאורגנים בהיררכיה. ההמרה אמורה להיות קומפקטית ופשוטה לניתוח.
שם | פורמט | תיאור |
---|---|---|
(value_arg << 5) | value_type | ubyte | בייט שמציין את הסוג של value שמיד אחריו, יחד עם ארגומנטים מפורטים אופציונליים בשלושת הביטים הבכירים.
בהמשך מפורטות ההגדרות השונות של value .
ברוב המקרים, value_arg מקודד את האורך של value העוקב אחריו מיידית ביחידות ביייט, כפי שמתואר ב-(size - 1) , לדוגמה: הערך 0 מציין שהערך נדרש בתור בית אחד, והערך 7 מציין שהערך נדרש בתור שמונה בתים. עם זאת, יש יוצאים מן הכלל כפי שמפורט בהמשך.
|
ערך | ubyte[] | בייטים שמייצגים את הערך, באורך משתנה, ומתפרשים באופן שונה לבייטים שונים של value_type , אבל תמיד בפורמט little-endian. בהמשך מפורטות הגדרות הערכים השונות.
|
פורמטים של ערכים
שם הסוג | value_type |
value_arg פורמט |
value פורמט |
תיאור |
---|---|---|---|---|
VALUE_BYTE | 0x00 | (ללא; חייב להיות 0 ) |
ubyte[1] | ערך שלם חתום באורך ביייט אחד |
VALUE_SHORT | 0x02 | size - 1 (0…1) | ubyte[size] | ערך שלם חתום באורך שני בתים, עם סימן מורחב |
VALUE_CHAR | 0x03 | size - 1 (0…1) | ubyte[size] | ערך שלם ללא סימן באורך שני בייטים, עם הרחבה לאפס |
VALUE_INT | 0x04 | size - 1 (0…3) | ubyte[size] | ערך שלם חתום באורך ארבעה בתים, עם סימן מורחב |
VALUE_LONG | 0x06 | size - 1 (0…7) | ubyte[size] | ערך שלם חתום באורך שמונה בתים, עם סימן מורחב |
VALUE_FLOAT | 0x10 | size - 1 (0…3) | ubyte[size] | תבנית ביטים של ארבעה בתים, עם הרחבה של אפס ימינה, ופרשנוּת כערך של נקודה צפה (floating point) של 32 ביט בתקן IEEE754 |
VALUE_DOUBLE | 0x11 | size - 1 (0…7) | ubyte[size] | תבנית ביטים של שמונה בייטים, עם הרחבה של אפס ימינה, ופרשנוּת כערך של נקודה צפה (floating point) של 64 ביט בתקן IEEE754 |
VALUE_METHOD_TYPE | 0x15 | size - 1 (0…3) | ubyte[size] | ערך שלם של ארבעה בתים ללא סימן (מורחב לאפס), שמתפרש כאינדקס לקטע proto_ids ומייצג ערך של סוג שיטת
|
VALUE_METHOD_HANDLE | 0x16 | size - 1 (0…3) | ubyte[size] | ערך שלם לא חתום (מורחב לאפס) באורך ארבעה בתים, שמתפרש כאינדקס לקטע method_handles ומייצג ערך של טיפולי שיטות
|
VALUE_STRING | 0x17 | size - 1 (0…3) | ubyte[size] | ערך שלם ללא סימן (מורחב לאפס) באורך ארבעה בתים, שמתפרש כאינדקס לקטע string_ids ומייצג ערך מחרוזת
|
VALUE_TYPE | 0x18 | size - 1 (0…3) | ubyte[size] | ערך שלם של ארבעה בתים ללא סימן (מורחב באפס), שמתפרש כאינדקס לקטע type_ids ומייצג ערך של סוג/כיתה רפלקטיבי
|
VALUE_FIELD | 0x19 | size - 1 (0…3) | ubyte[size] | ערך שלם של ארבעה בתים ללא סימן (מורחב באפס), שמתפרש כאינדקס לקטע field_ids ומייצג ערך שדה רפלקטיבי
|
VALUE_METHOD | 0x1a | size - 1 (0…3) | ubyte[size] | ערך שלם לא חתום (מורחב לאפס) באורך ארבעה בייטים, שמתפרש כאינדקס לקטע method_ids ומייצג ערך של שיטת רפלקציה
|
VALUE_ENUM | 0x1b | size - 1 (0…3) | ubyte[size] | ערך שלם של ארבעה בתים ללא סימן (מורחב לאפס), שמתורגם כאינדקס בקטע field_ids ומייצג את הערך של קבוע מסוג Enumeration
|
VALUE_ARRAY | 0x1c | (ללא; חייב להיות 0 ) |
encoded_array | מערך ערכים, בפורמט שצוין בקטע 'פורמט encoded_array ' בהמשך. הגודל של value הוא סמוי בקידוד.
|
VALUE_ANNOTATION | 0x1d | (ללא; חייב להיות 0 ) |
encoded_annotation | הערה משנית, בפורמט שמפורט בקטע 'פורמט encoded_annotation ' בהמשך. הגודל של value הוא סמוי בקידוד.
|
VALUE_NULL | 0x1e | (ללא; חייב להיות 0 ) |
(none) | ערך העזר של null |
VALUE_BOOLEAN | 0x1f | בוליאני (0…1) | (none) | ערך של ביט אחד: 0 עבור false ו-1 עבור true . הבייט מיוצג ב-value_arg .
|
פורמט encoded_array
שם | פורמט | תיאור |
---|---|---|
size | uleb128 | מספר הרכיבים במערך |
ערכים | encoded_value[size] | סדרה של רצפי size encoded_value בייטים בפורמט שצוין בקטע הזה, שמקושרים בסדר.
|
הפורמט של encoded_annotation
שם | פורמט | תיאור |
---|---|---|
type_idx | uleb128 | סוג ההערה. זה חייב להיות טיפוס של כיתה (לא מערך או פרימיטיבי). |
size | uleb128 | מספר המיפויים של שם-ערך בהערה הזו |
רכיבים | annotation_element[size] | רכיבי ההערה, שמוצגים ישירות בשורה (לא בתור הרכיבים צריכים להיות ממוינים בסדר עולה לפי אינדקס string_id .
|
פורמט של annotation_element
שם | פורמט | תיאור |
---|---|---|
name_idx | uleb128 | שם הרכיב, שמיוצג כאינדקס בקטע string_ids . המחרוזת חייבת להיות תואמת לתחביר של MemberName, שמוגדר למעלה.
|
ערך | encoded_value | ערך רכיב |
תחביר של מחרוזת
יש כמה סוגים של פריטים בקובץ .dex
, שבסופו של דבר מפנים למחרוזת. ההגדרות הבאות בסגנון BNF מצביעות על התחביר הקביל למחרוזות האלה.
SimpleName
SimpleName הוא הבסיס לתחביר של שמות של דברים אחרים. הפורמט .dex
מאפשר הרבה גמישות (יותר מרוב שפות המקור הנפוצות). בקצרה, שם פשוט מורכב מכל תו או ספרה אלפביתי ב-ASCII נמוך, כמה סמלים ספציפיים ב-ASCII נמוך ורוב נקודות הקוד שאינן ASCII, שאינן תווים של בקרה, רווח או תווים מיוחדים. החל מגרסה 040
, הפורמט מאפשר גם להשתמש בתווי רווח (קטגוריה Zs
ב-Unicode). שימו לב שקודי סמלי חלופי (בטווח U+d800
… U+dfff
) לא נחשבים כתוויות שם תקינות, אבל תווים משלימים של Unicode כן תקינים (והם מיוצגים על ידי החלופה האחרונה של הכלל ל-SimpleNameChar), וצריך לייצג אותם בקובץ כזוגות של קודי סמלי חלופי בקידוד MUTF-8.
SimpleName → | ||
SimpleNameChar (SimpleNameChar)* | ||
SimpleNameChar → | ||
'A' … 'Z' |
||
| | 'a' … 'z' |
|
| | '0' … '9' |
|
| | ' ' |
מגרסה 040 של DEX והלאה |
| | '$' |
|
| | '-' |
|
| | '_' |
|
| | U+00a0 |
מגרסה 040 של DEX והלאה |
| | U+00a1 … U+1fff |
|
| | U+2000 … U+200a |
מגרסה 040 של DEX והלאה |
| | U+2010 … U+2027 |
|
| | U+202f |
מגרסה 040 של DEX והלאה |
| | U+2030 … U+d7ff |
|
| | U+e000 … U+ffef |
|
| | U+10000 … U+10ffff |
MemberName
משמש את field_id_item ואת method_id_item
MemberName הוא השם של חבר מחלקה, כאשר חברים הם שדות, שיטות ומחלקות פנימיות.
MemberName → | |
SimpleName | |
| | '<' SimpleName '>' |
FullClassName
FullClassName הוא שם כיתה מלא, כולל מפריד חבילה אופציונלי ואחריו שם נדרש.
FullClassName → | |
OptionalPackagePrefix SimpleName | |
OptionalPackagePrefix → | |
(SimpleName '/' )* |
TypeDescriptor
בשימוש על ידי type_id_item
TypeDescriptor הוא ייצוג של כל סוג, כולל פרימיטיבים, מחלקות, מערכים ו-void
. בהמשך מוסבר מה המשמעות של הגרסאות השונות.
TypeDescriptor → | |
'V' |
|
| | FieldTypeDescriptor |
FieldTypeDescriptor → | |
NonArrayFieldTypeDescriptor | |
| | ('[' * 1…255)
NonArrayFieldTypeDescriptor |
NonArrayFieldTypeDescriptor→ | |
'Z' |
|
| | 'B' |
| | 'S' |
| | 'C' |
| | 'I' |
| | 'J' |
| | 'F' |
| | 'D' |
| | 'L' FullClassName ';' |
ShortyDescriptor
בשימוש על ידי proto_id_item
ShortyDescriptor הוא ייצוג בפורמט קצר של אב טיפוס של שיטה, כולל סוגי ההחזרה והפרמטרים, מלבד העובדה שאין הבחנה בין סוגי הפניות שונים (כיתה או מערך). במקום זאת, כל סוגי ההפניות מיוצגים על ידי תו 'L'
יחיד.
ShortyDescriptor → | |
ShortyReturnType (ShortyFieldType)* | |
ShortyReturnType → | |
'V' |
|
| | ShortyFieldType |
ShortyFieldType → | |
'Z' |
|
| | 'B' |
| | 'S' |
| | 'C' |
| | 'I' |
| | 'J' |
| | 'F' |
| | 'D' |
| | 'L' |
סמנטיקה של TypeDescriptor
זהו המשמעות של כל אחת מהוריאציות של TypeDescriptor.
תחביר | משמעות |
---|---|
V | void ; תקף רק לסוגים של ערכים שמוחזרים |
Z | boolean |
B | byte |
S | short |
C | char |
I | int |
J | long |
F | float |
D | double |
Lfully/qualified/Name; | הכיתה fully.qualified.Name |
[descriptor | מערך של descriptor , שאפשר להשתמש בו באופן רפלוקטיבי למערכים של מערכים, אבל לא ניתן לכלול יותר מ-255 מאפיינים.
|
פריטים ומבנים קשורים
בקטע הזה מפורטות הגדרות של כל הפריטים ברמה העליונה שעשויים להופיע בקובץ .dex
.
header_item
מופיע בקטע הכותרת
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
magic | ubyte[8] = DEX_FILE_MAGIC | ערך קסום. פרטים נוספים מופיעים בקטע DEX_FILE_MAGIC למעלה.
|
סכום כולל | uint | סיכום הביקורת של adler32 של שאר הקובץ (כל מה שחוץ מ-magic והשדה הזה). משמש לזיהוי פגיעה בקובץ
|
חתימה | ubyte[20] | חתימה (hash) מסוג SHA-1 של שאר הקובץ (כל מה שחוץ מ-magic , checksum והשדה הזה). החתימה משמשת לזיהוי ייחודי של קבצים.
|
file_size | uint |
הגודל של הקובץ כולו (כולל הכותרת), בבייטים (גרסה 40 ואילך) המרחק בבייט מתחילת הכותרת הזו לכותרת הבאה או לסוף הקובץ כולו (המארז). (גרסה 41 ואילך) |
header_size | uint |
גודל הכותרת (כל הקטע הזה), בבייטים. כך אפשר לאפשר לפחות תאימות מוגבלת לאחור או קדימה בלי לפסול את הפורמט. חייב להיות באורך 0x70 (112) בייטים (גרסה 40 ואילך) חייב להיות 0x78 (120) בייטים (גרסה 41 ואילך) |
endian_tag | uint = ENDIAN_CONSTANT | תג endianness. פרטים נוספים מופיעים למעלה בקטע 'ENDIAN_CONSTANT
ו-REVERSE_ENDIAN_CONSTANT '.
|
link_size | uint | הגודל של קטע הקישור, או 0 אם הקובץ לא מקושר באופן סטטי |
link_off | uint | הזזה מתחילת הקובץ לקטע הקישור, או
0 אם link_size == 0 . אם הערך של ההיסט הוא לא אפס, הוא צריך להצביע להיסט בתוך הקטע link_data . הפורמט של הנתונים שמוצגים לא צוין במסמך הזה. שדה הכותרת הזה (והקודם) נשארים כוונטיות לשימוש בהטמעות בסביבת זמן הריצה.
|
map_off | uint | אופסט מתחילת הקובץ לפריט המפה. ההיסט, שחייב להיות שונה מאפס, צריך להצביע על היסט בקטע data , והנתונים צריכים להיות בפורמט שצוין ב-map_list בהמשך.
|
string_ids_size | uint | מספר המחרוזות ברשימה של מזהי המחרוזות |
string_ids_off | uint | הזזה מתחילת הקובץ לרשימה של מזהים של מחרוזות, או 0 אם string_ids_size == 0 (אמנם מקרה קיצוני מוזר). אם הערך של ההיסט שונה מאפס, הוא צריך להיות בתחילת הקטע string_ids .
|
type_ids_size | uint | מספר הפריטים ברשימת מזהי הסוגים, לכל היותר 65,535 |
type_ids_off | uint | אופסט מתחילת הקובץ לרשימה של מזהי הסוגים, או 0 אם type_ids_size == 0 (אמנם מקרה קיצוני מוזר). אם הערך של ההיסט שונה מאפס, הוא צריך להיות בתחילת הקטע type_ids .
|
proto_ids_size | uint | מספר הפריטים ברשימה של מזהי האב טיפוס, לכל היותר 65,535 |
proto_ids_off | uint | אופסט מתחילת הקובץ לרשימה של מזהי האב טיפוס, או 0 אם proto_ids_size == 0 (אמנם מקרה קיצוני מוזר). אם הערך של ההיסט שונה מאפס, הוא צריך להיות בתחילת הקטע proto_ids .
|
field_ids_size | uint | מספר הפריטים ברשימת מזהי השדות |
field_ids_off | uint | הזזה מתחילת הקובץ לרשימת מזהי השדות, או 0 אם field_ids_size == 0 . אם הערך של ההיסט שונה מאפס, הוא צריך להיות בתחילת הקטע field_ids . |
method_ids_size | uint | מספר הרכיבים ברשימת מזהי השיטות |
method_ids_off | uint | הזזה מתחילת הקובץ לרשימה של מזהי השיטות, או 0 אם method_ids_size == 0 . אם הערך של ההיסט שונה מאפס, הוא צריך להיות בתחילת הקטע method_ids . |
class_defs_size | uint | מספר הפריטים ברשימת הגדרות הכיתה |
class_defs_off | uint | OFFSET מתחילת הקובץ לרשימה של הגדרות הכיתות, או 0 אם class_defs_size == 0 (אמנם מקרה קיצוני ומוזר). אם הערך של ההיסט שונה מאפס, הוא צריך להיות בתחילת הקטע class_defs .
|
data_size | uint |
הגודל של הקטע לא בשימוש (גרסה 41 ואילך) |
data_off | uint |
הזזה מתחילת הקובץ לתחילת הקטע לא בשימוש (גרסה 41 ואילך) |
container_size | uint |
השדה הזה לא קיים. אפשר להניח שהוא שווה ל- הגודל של הקובץ כולו (כולל כותרות dex אחרות והנתונים שלהן). (גרסה 41 ואילך) |
header_offset | uint |
השדה הזה לא קיים. אפשר להניח שהוא שווה ל- היסט מתחילת הקובץ לתחילת הכותרת הזו. (גרסה 41 ואילך) |
map_list
מופיע בקטע 'נתונים'
הפניה מ-header_item
התאמה: 4 בייטים
זוהי רשימה של כל התוכן בקובץ, לפי סדר. הוא מכיל קצת יתירות ביחס ל-header_item
, אבל הוא מיועד להיות טופס קל לשימוש כדי לבצע איטרציה על קובץ שלם. סוג מסוים חייב להופיע במפה רק פעם אחת, אבל אין הגבלה על סוגי ההזמנות שיכולים להופיע, מלבד ההגבלות שמשתמעות משאר הפורמט (למשל, הקטע header
חייב להופיע קודם, ואחריו הקטע string_ids
וכו'). בנוסף, רשומות המפה צריכות להיות מסודרות לפי הזזה ראשונית ואסור שהן יחפפו.
שם | פורמט | תיאור |
---|---|---|
size | uint | גודל הרשימה, בכניסות |
רשימה | map_item[size] | הרכיבים של הרשימה |
הפורמט של map_item
שם | פורמט | תיאור |
---|---|---|
סוג | ushort | סוג הפריטים. אפשר לעיין בטבלה שבהמשך. |
unused | ushort | (לא בשימוש) |
size | uint | מספר הפריטים שצריך למצוא בהיסט שצוין |
לקזז | uint | הזזה מתחילת הקובץ לפריטים הרלוונטיים |
הקלדה של קודים
סוג הפריט | קבוע | ערך | גודל הפריט בבייטים |
---|---|---|---|
header_item | TYPE_HEADER_ITEM | 0x0000 | 0x70 |
string_id_item | TYPE_STRING_ID_ITEM | 0x0001 | 0x04 |
type_id_item | TYPE_TYPE_ID_ITEM | 0x0002 | 0x04 |
proto_id_item | TYPE_PROTO_ID_ITEM | 0x0003 | 0x0c |
field_id_item | TYPE_FIELD_ID_ITEM | 0x0004 | 0x08 |
method_id_item | TYPE_METHOD_ID_ITEM | 0x0005 | 0x08 |
class_def_item | TYPE_CLASS_DEF_ITEM | 0x0006 | 0x20 |
call_site_id_item | TYPE_CALL_SITE_ID_ITEM | 0x0007 | 0x04 |
method_handle_item | TYPE_METHOD_HANDLE_ITEM | 0x0008 | 0x08 |
map_list | TYPE_MAP_LIST | 0x1000 | 4 + (item.size * 12) |
type_list | TYPE_TYPE_LIST | 0x1001 | 4 + (item.size * 2) |
annotation_set_ref_list | TYPE_ANNOTATION_SET_REF_LIST | 0x1002 | 4 + (item.size * 4) |
annotation_set_item | TYPE_ANNOTATION_SET_ITEM | 0x1003 | 4 + (item.size * 4) |
class_data_item | TYPE_CLASS_DATA_ITEM | 0x2000 | משתמע; חייב לנתח |
code_item | TYPE_CODE_ITEM | 0x2001 | משתמע; חייב לנתח |
string_data_item | TYPE_STRING_DATA_ITEM | 0x2002 | משתמע; חייב לנתח |
debug_info_item | TYPE_DEBUG_INFO_ITEM | 0x2003 | משתמע; חייב לנתח |
annotation_item | TYPE_ANNOTATION_ITEM | 0x2004 | משתמע; חייב לנתח |
encoded_array_item | TYPE_ENCODED_ARRAY_ITEM | 0x2005 | משתמע; חייב לנתח |
annotations_directory_item | TYPE_ANNOTATIONS_DIRECTORY_ITEM | 0x2006 | משתמע; חייב לנתח |
hiddenapi_class_data_item | TYPE_HIDDENAPI_CLASS_DATA_ITEM | 0xF000 | משתמע; חייב לנתח |
string_id_item
מופיע בקטע string_ids
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
string_data_off | uint | הזזה מתחילת הקובץ לנתוני המחרוזת של הפריט הזה. ההיסט צריך להיות למיקום בקטע data , והנתונים צריכים להיות בפורמט שמפורט ב-string_data_item בהמשך.
אין דרישה ליישור של ההיסט.
|
string_data_item
מופיע בקטע 'נתונים'
התאמה: ללא (יישור לפי בייטים)
שם | פורמט | תיאור |
---|---|---|
utf16_size | uleb128 | הגודל של המחרוזת הזו, ביחידות קוד UTF-16 (הגודל הזה נקרא 'אורך המחרוזת' במערכות רבות). כלומר, זהו האורך של המחרוזת לאחר פענוח. (אורך ההצפנה נגזר מהמיקום של הבית 0 ). |
נתונים | ubyte[] | סדרה של יחידות קוד MUTF-8 (שנקראות גם אוקטטים או בייטים) ואחריה בייט עם הערך 0 . למידע נוסף על פורמט הנתונים, ראו 'קידוד MUTF-8 (UTF-8 שונה)' למעלה.
הערה: מותר לכלול במחרוזת (את הצורה הקודדת של) יחידות קוד חלופיות של UTF-16 (כלומר, |
type_id_item
מופיע בקטע type_ids
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
descriptor_idx | uint | מאתרים את מחרוזת המתאר של הסוג הזה ברשימה string_ids . המחרוזת חייבת להתאים לתחביר של TypeDescriptor, שמוגדר למעלה.
|
proto_id_item
מופיע בקטע proto_ids
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
shorty_idx | uint | מאתרים את המחרוזת של התיאור המקוצר של אב הטיפוס ברשימה string_ids . המחרוזת חייבת להתאים לתחביר של ShortyDescriptor, שהוגדר למעלה, ולהתאים לסוג ההחזרה ולפרמטרים של הפריט הזה.
|
return_type_idx | uint | מאתרים את סוג ההחזרה של אב הטיפוס הזה ברשימה type_ids
|
parameters_off | uint | הזזה מתחילת הקובץ אל רשימת סוגי הפרמטרים של האב-טיפוס, או 0 אם אין לאב-טיפוס פרמטרים. אם הערך של ההיסט הוא לא אפס, הוא צריך להופיע בקטע data , והנתונים שם צריכים להיות בפורמט שמוגדר על ידי "type_list" בהמשך. בנוסף, לא אמורה להיות ברשימה הפניה לסוג void .
|
field_id_item
מופיע בקטע field_ids
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
class_idx | ushort | אינדקס ברשימה type_ids של מי שהגדיר את השדה הזה. זה חייב להיות טיפוס של כיתה, ולא מערך או טיפוס פרימיטיבי.
|
type_idx | ushort | חיפוש ברשימה type_ids לפי סוג השדה
|
name_idx | uint | מחפשים את השם של השדה הזה ברשימה string_ids . המחרוזת חייבת להיות תואמת לתחביר של MemberName, שמוגדר למעלה.
|
method_id_item
מופיע בקטע method_ids
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
class_idx | ushort | האינדקס ברשימה type_ids של המגדיר של השיטה הזו. זה חייב להיות טיפוס של מחלקה או מערך, ולא טיפוס פרימיטיבי.
|
proto_idx | ushort | מאתרים את האב טיפוס של השיטה הזו ברשימה proto_ids
|
name_idx | uint | מחפשים את השם של השיטה הזו ברשימה string_ids . המחרוזת חייבת להיות תואמת לתחביר של MemberName, שמוגדר למעלה.
|
class_def_item
מופיע בקטע class_defs
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
class_idx | uint | להוסיף את הכיתה הזו לאינדקס של רשימת type_ids .
זה חייב להיות טיפוס של כיתה, ולא מערך או טיפוס פרימיטיבי.
|
access_flags | uint | דגלים של גישה לכיתה (public , final וכו'). פרטים נוספים זמינים בקטע access_flags הגדרות.
|
superclass_idx | uint | אינדקס ברשימה type_ids של הסוג ההורה, או הערך הקבוע NO_INDEX אם אין לסוג הזה סוג הורה (כלומר, הוא סוג ברמה הבסיסית, כמו Object ). אם הוא קיים, הוא חייב להיות סוג של סוג ולא מערך או סוג פרימיטיבי.
|
interfaces_off | uint | הזזה מתחילת הקובץ לרשימה של הממשקים, או 0 אם אין כאלה. ההיסט הזה צריך להיות בקטע data , והנתונים שם צריכים להיות בפורמט שמפורט ב-type_list בהמשך. כל אחד מהאלמנטים ברשימה חייב להיות מסוג class (לא מערך או סוג פרימיטיבי), ואסור שיהיו עותקים כפולים.
|
source_file_idx | uint | מאתרים ברשימה string_ids את השם של הקובץ שמכיל את המקור המקורי (לפחות רוב) של הכיתה הזו, או את הערך המיוחד NO_INDEX כדי לייצג את היעדר המידע הזה. ה-debug_info_item של כל שיטה נתונה יכול לשנות את קובץ המקור הזה, אבל ההנחה היא שרוב הכיתות יגיעו מקובץ מקור אחד בלבד.
|
annotations_off | uint | הזזה מתחילת הקובץ למבנה ההערות של הכיתה הזו, או 0 אם אין הערות בכיתה הזו. אם הערך של ההיסט הוא לא אפס, הוא צריך להופיע בקטע data , והנתונים שם צריכים להיות בפורמט שמוגדר ב-annotations_directory_item בהמשך, כאשר כל הפריטים מתייחסים לכיתה הזו בתור המגדיר.
|
class_data_off | uint | הזזה מתחילת הקובץ לנתוני הכיתה המשויכים לפריט הזה, או 0 אם אין נתוני כיתה לכיתה הזו. (הדבר יכול לקרות, למשל, אם הכיתה היא ממשק סמן). אם הערך של ההיסט הוא לא אפס, הוא צריך להופיע בקטע data , והנתונים שם צריכים להיות בפורמט שמפורט ב-class_data_item בהמשך, כאשר כל הפריטים מתייחסים לכיתה הזו בתור המגדיר.
|
static_values_off | uint | הזזה מתחילת הקובץ לרשימה של הערכים הראשוניים לשדות static , או 0 אם אין כאלה (וכל שדות static צריכים להיות מוגדרים ב-0 או ב-null ). ההזזה הזו צריכה להיות בקטע data , והנתונים שם צריכים להיות בפורמט שצוין ב-encoded_array_item בהמשך. הגודל של המערך לא יכול להיות גדול ממספר השדות מסוג static שהוגדר בכיתה הזו, והרכיבים תואמים לשדות static באותו הסדר שבו הם הוגדרו ב-field_list התואם. הסוג של כל רכיב במערך חייב להתאים לסוג המוצהר של השדה התואם.
אם יש ברשימה פחות רכיבים ממספר השדות של static , השדות הנותרים יופעלו עם 0 או null שמתאימים לסוג.
|
call_site_id_item
מופיע בקטע call_site_ids
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
call_site_off | uint | הזזה מתחילת הקובץ כדי לקרוא להגדרת האתר. ההיסט צריך להיות בקטע הנתונים, והנתונים שם צריכים להיות בפורמט שמפורט בהמשך בקטע 'call_site_item'. |
call_site_item
מופיע בקטע 'נתונים'
התאמה: ללא (יישור לפי בייטים)
ה-call_site_item הוא encoded_array_item שהאלמנטים שלו תואמים לארגומנטים שסופקו לשיטת הקישור של Bootstrap. שלושת הארגומנטים הראשונים הם:
- מאגר שיטות שמייצג את שיטת הקישור של האתחול (VALUE_METHOD_HANDLE).
- שם של שיטה שהמקשר של Bootstrap צריך לפתור (VALUE_STRING).
- סוג method שתואם לסוג של שם method שצריך לפתור (VALUE_METHOD_TYPE).
כל ארגומנטים נוספים הם ערכים קבועים שמועברים לשיטת הקישור של Bootstrap. הארגומנטים האלה מועברים לפי הסדר וללא המרות של סוגים.
לסוג ההחזרה של ה-method handle שמייצג את שיטת הקישור של האתחול צריך להיות java.lang.invoke.CallSite
. שלושת סוגי הפרמטרים הראשונים הם:
java.lang.invoke.Lookup
java.lang.String
java.lang.invoke.MethodType
סוגי הפרמטרים של ארגומנטים נוספים נקבעים על סמך הערכים הקבועים שלהם.
method_handle_item
מופיע בקטע method_handles
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
method_handle_type | ushort | הסוג של ה-method handle. אפשר לעיין בטבלה שבהמשך. |
unused | ushort | (לא בשימוש) |
field_or_method_id | ushort | מזהה שדה או שיטת, בהתאם לסוג של רכיב הטיפול בשיטה (method handle) שהוא רכיב גישה או מפעיל שיטות |
unused | ushort | (לא בשימוש) |
קודים של סוגי הידית של שיטות
קבוע | ערך | תיאור |
---|---|---|
METHOD_HANDLE_TYPE_STATIC_PUT | 0x00 | Method handle הוא מגדיר שדה סטטי (רכיב גישה) |
METHOD_HANDLE_TYPE_STATIC_GET | 0x01 | Method handle הוא פונקציית אחזור סטטית של שדה (accessor) |
METHOD_HANDLE_TYPE_INSTANCE_PUT | 0x02 | ה-method handle הוא מגדיר שדה של מופע (רכיב גישה) |
METHOD_HANDLE_TYPE_INSTANCE_GET | 0x03 | Method handle הוא פונקציית אחזור (accessor) של שדה מופע |
METHOD_HANDLE_TYPE_INVOKE_STATIC | 0x04 | Method handle הוא מפעיל סטטי של שיטות |
METHOD_HANDLE_TYPE_INVOKE_INSTANCE | 0x05 | Method handle הוא מבצע של קריאה לשיטת מופע |
METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR | 0x06 | Method handle הוא מבצע קריאה לשיטת קונסטרוקטור |
METHOD_HANDLE_TYPE_INVOKE_DIRECT | 0x07 | Method handle הוא מפעיל שיטות ישיר |
METHOD_HANDLE_TYPE_INVOKE_INTERFACE | 0x08 | Method handle הוא מבצע קריאה לשיטת ממשק |
class_data_item
הפניה מ-class_def_item
מופיע בקטע 'נתונים'
התאמה: ללא (יישור לפי בייטים)
שם | פורמט | תיאור |
---|---|---|
static_fields_size | uleb128 | מספר השדות הסטטיים שמוגדרים בפריט הזה |
instance_fields_size | uleb128 | מספר שדות המכונה שמוגדרים בפריט הזה |
direct_methods_size | uleb128 | מספר השיטות הישירות שהוגדרו בפריט הזה |
virtual_methods_size | uleb128 | מספר השיטות הווירטואליות שמוגדרות בפריט הזה |
static_fields | encoded_field[static_fields_size] | השדות הסטטיים שהוגדרו, שמיוצגים כרצף של רכיבים מקודדים. צריך למיין את השדות לפי field_idx בסדר עולה.
|
instance_fields | encoded_field[instance_fields_size] | שדות המכונה שהוגדרו, שמיוצגים כרצף של רכיבים מקודדים. צריך למיין את השדות לפי field_idx בסדר עולה.
|
direct_methods | encoded_method[direct_methods_size] | השיטות הישירות שהוגדרו (כל אחת מ-static , private או ה-constructor), שמיוצגות כרצף של רכיבים מקודדים. צריך למיין את השיטות לפי method_idx בסדר עולה.
|
virtual_methods | encoded_method[virtual_methods_size] | השיטות הווירטואליות שהוגדרו (לא static , private או ה-constructor), שמיוצגות כרצף של אלמנטים מקודדים. הרשימה הזו לא צריכה לכלול שיטות שעברו בירושה, אלא אם הן שונו על ידי הכיתה שהפריט הזה מייצג. צריך למיין את השיטות לפי method_idx בסדר עולה.
method_idx של שיטת וירטואלית לא יכול להיות זהה לשיטה ישירה כלשהי.
|
הערה: כל המופעים של field_id
ו-method_id
של הרכיבים חייבים להפנות לאותה כיתה מגדירה.
הפורמט של encoded_field
שם | פורמט | תיאור |
---|---|---|
field_idx_diff | uleb128 | מאתרים ברשימה field_ids את הזהות של השדה הזה (כולל השם והתיאורים), שמיוצגת כהפרש מהאינדקס של הרכיב הקודם ברשימה. האינדקס של הרכיב הראשון ברשימה מיוצג ישירות.
|
access_flags | uleb128 | דגלי גישה לשדה (public , final וכו'). פרטים נוספים זמינים בקטע access_flags הגדרות.
|
הפורמט של encoded_method
שם | פורמט | תיאור |
---|---|---|
method_idx_diff | uleb128 | האינדקס ברשימה method_ids של הזהות של השיטה הזו (כולל השם והתיאורים), שמיוצג כהפרש מהאינדקס של הרכיב הקודם ברשימה. האינדקס של הרכיב הראשון ברשימה מיוצג ישירות.
|
access_flags | uleb128 | דגלי גישה לשיטה (public , final וכו'). פרטים נוספים זמינים בקטע access_flags הגדרות.
|
code_off | uleb128 | אופסט מתחילת הקובץ למבנה הקוד של השיטה הזו, או 0 אם השיטה הזו היא abstract או native . ההיסט צריך להיות למיקום בקטע data . הפורמט של הנתונים מצוין ב-code_item בהמשך.
|
type_list
הפניה מ-class_def_item ומ-proto_id_item
מופיע בקטע 'נתונים'
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
size | uint | גודל הרשימה, בכניסות |
רשימה | type_item[size] | הרכיבים של הרשימה |
הפורמט של type_item
שם | פורמט | תיאור |
---|---|---|
type_idx | ushort | אינדקס ברשימה type_ids |
code_item
הפניה מ-encoded_method
מופיע בקטע 'נתונים'
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
registers_size | ushort | מספר הרשומות שבהן הקוד הזה משתמש |
ins_size | ushort | מספר המילים של הארגומנטים הנכנסים לשיטה שהקוד הזה מיועד לה |
outs_size | ushort | מספר המילים של שטח הארגומנטים היוצאים שנדרש לקוד הזה להפעלת השיטה |
tries_size | ushort | מספר ה-try_item של המופע הזה. אם הערך שונה מאפס, הערכים האלה מופיעים כמערך tries מיד אחרי הערך insns במופע הזה.
|
debug_info_off | uint | הזזה מתחילת הקובץ לרצף של פרטי ניפוי הבאגים (מספרי שורות + פרטי המשתנים המקומיים) של הקוד הזה, או 0 אם פשוט אין מידע. אם הערך של ההיסט שונה מאפס, הוא צריך להצביע למיקום בקטע data . הפורמט של הנתונים מצוין ב-debug_info_item בהמשך.
|
insns_size | uint | הגודל של רשימת ההוראות, ביחידות קוד של 16 ביט |
insns | ushort[insns_size] | מערך הבייטקוד בפועל. הפורמט של הקוד במערך insns מצוין במסמך הנלווה Dalvik bytecode. חשוב לשים לב שלמרות שהמבנה מוגדר כמערך של ushort , יש מבנים פנימיים מסוימים שמעדיפים התאמה של ארבעה בייט. בנוסף, אם הקובץ הזה הוא קובץ עם החלפת endian, ההחלפה מתבצעת רק במופעים נפרדים של ushort ולא במבנים הפנימיים הגדולים יותר.
|
padding | ushort (אופציונלי) = 0 | שני בייטים של מילוי כדי שהשדה tries יתאים לארבעה בייטים.
הרכיב הזה קיים רק אם tries_size שונה מאפס ו-insns_size הוא מספר אי-זוגי.
|
ניסיונות | try_item[tries_size] (אופציונלי) | מערך שמציין איפה בקוד מתרחשות חריגות ואיך מטפלים בהן. הרכיבים של המערך לא יכולים להיות חופפים בטווח, והם צריכים להיות מסודרים מהכתובת הנמוכה לכתובת הגבוהה. האלמנט הזה נמצא רק אם הערך של tries_size שונה מאפס.
|
רכיבי handler | encoded_catch_handler_list (אופציונלי) | בייטים שמייצגים רשימה של רשימות של סוגי catch וכתובות טיפול משויכות. לכל try_item יש סטייה של בייטים במבנה הזה. האלמנט הזה נמצא רק אם הערך של tries_size שונה מאפס.
|
הפורמט של try_item
שם | פורמט | תיאור |
---|---|---|
start_addr | uint | כתובת ההתחלה של בלוק הקוד שמתואר ברשומה הזו. הכתובת היא ספירה של יחידות קוד של 16 ביט עד לתחילת ההוראה הראשונה המכוסה. |
insn_count | ushort | מספר יחידות הקוד של 16 ביט שמפורטות ברשומה הזו. יחידת הקוד האחרונה שכלולה בהסכם היא start_addr + insn_count - 1 .
|
handler_off | ushort | הזזה בבייטים מתחילת ה-encoded_catch_hander_list המשויך אל ה-encoded_catch_handler של הרשומה הזו. זה חייב להיות היסט לתחילת encoded_catch_handler .
|
הפורמט של encoded_catch_handler_list
שם | פורמט | תיאור |
---|---|---|
size | uleb128 | הגודל של הרשימה הזו, במספר רשומות |
רשימה | encoded_catch_handler[handlers_size] | רשימת רשימות הטיפולנים בפועל, שמיוצגת ישירות (לא כאופסים) ומקונצנטרנת ברצף |
הפורמט של encoded_catch_handler
שם | פורמט | תיאור |
---|---|---|
size | sleb128 | מספר סוגי ה-catch ברשימה הזו. אם הערך לא חיובי, הוא הערך השלילי של מספר סוגי ה-catch, ואחריהם מופיע טיפול catch-all. לדוגמה: size של 0
פירושו שיש כלל לכולם, אבל אין קטגוריות ספציפיות לאירועים.
size של 2 פירושו שיש שני טיפים של catch שצוינו במפורש, ואין catch-all. ו-size של -1
פירושו שיש כלל מסנן אחד ידני וכלל מסנן כללי.
|
רכיבי handler | encoded_type_addr_pair[abs(size)] | מקור נתונים של abs(size) פריטים מקודדים, אחד לכל סוג שנלכד, בסדר שבו צריך לבדוק את הסוגים.
|
catch_all_addr | uleb128 (אופציונלי) | כתובת ה-bytecode של הטיפול בכל הכתובות. האלמנט הזה מופיע רק אם הערך של size הוא שלילי.
|
הפורמט של encoded_type_addr_pair
שם | פורמט | תיאור |
---|---|---|
type_idx | uleb128 | חיפוש ברשימה type_ids לפי סוג החריג שרוצים לתפוס
|
addr | uleb128 | כתובת ה-bytecode של בורר החריגות המשויך |
debug_info_item
הפניה מ-code_item
מופיע בקטע 'נתונים'
התאמה: ללא (יישור לפי בייטים)
כל debug_info_item
מגדיר מכונת מצב בקידוד בייט בהשראת DWARF3, שבמהלך הפענוח שלה היא משדרת את טבלת המיקומים ואת פרטי המשתנה המקומי (אם רלוונטי) של code_item
. הרצף מתחיל בכותרת באורך משתנה (האורך שלה תלוי במספר הפרמטרים של השיטה), ואחריה מופיעים הבייטקודים של מכונת המצבים, והוא מסתיים בבייט DBG_END_SEQUENCE
.
מכונת המצב מורכבת מחמישה מרשם. הרישום address
מייצג את ההיסט של ההוראה ב-insns_item
המשויך ביחידות קוד של 16 ביט. המרשם address
מתחיל ב-0
בתחילת כל רצף debug_info
, וצריך רק לגדול באופן מונוטונית.
המרשם line
מייצג את מספר שורת המקור שצריך לשייך לרשומה הבאה בטבלת המיקומים שמופעלת על ידי מכונת המצבים. הוא מופעל בכותרת הרצף, ויכול להשתנות בכיוון חיובי או שלילי, אבל הוא אף פעם לא יכול להיות קטן מ-1
. המרשם source_file
מייצג את קובץ המקור שאליו מתייחסות הרשומות של מספרי השורות. הוא מופעל לערך של source_file_idx
ב-class_def_item
.
שני המשתנים האחרים, prologue_end
ו-epilogue_begin
, הם דגלים בוליאנים (שמוגדרים ל-false
) שמציינים אם המיקום הבא שיופץ צריך להיחשב כמבוא או כסיומת של method. מכונת המצבים צריכה גם לעקוב אחרי השם והסוג של המשתנה המקומי האחרון שפעיל בכל מרשם של קוד DBG_RESTART_LOCAL
.
הכותרת נראית כך:
שם | פורמט | תיאור |
---|---|---|
line_start | uleb128 | הערך הראשוני של הרישום line של מכונת המצב.
לא מייצג רשומה בפועל של עמדות.
|
parameters_size | uleb128 | מספר שמות הפרמטרים שמקודדים. צריך להיות אחד לכל פרמטר של שיטת, לא כולל this של שיטת מופע, אם יש כזה.
|
parameter_names | uleb128p1[parameters_size] | אינדקס המחרוזת של שם הפרמטר של השיטה. ערך מקודד של NO_INDEX מציין שאין שם זמין לפרמטר המשויך. התיאור והחתימה של הסוג משתמעים מהתיאור והחתימה של השיטה.
|
הערכים של קוד הבייטים הם:
שם | ערך | פורמט | ארגומנטים | תיאור |
---|---|---|---|---|
DBG_END_SEQUENCE | 0x00 | (none) | סיום רצף של מידע על תוצאות ניפוי באגים של code_item |
|
DBG_ADVANCE_PC | 0x01 | uleb128 addr_diff | addr_diff : הסכום להוספה למרשם הכתובות |
מקדמים את מרשם הכתובות בלי להפיק רשומה של מיקומים |
DBG_ADVANCE_LINE | 0x02 | sleb128 line_diff | line_diff : הסכום שרוצים לשנות ברשומת הקו |
מקדמת את מרשם השורות בלי להפיק רשומה של מיקומים |
DBG_START_LOCAL | 0x03 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx |
register_num : מרשם שיכיל את המשתנה המקומיname_idx : אינדקס המחרוזת של השםtype_idx : אינדקס הסוג של הסוג
|
יוצרת משתנה מקומי בכתובת הנוכחית. הערך של name_idx או type_idx יכול להיות NO_INDEX כדי לציין שהערך לא ידוע.
|
DBG_START_LOCAL_EXTENDED | 0x04 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx uleb128p1 sig_idx |
register_num : מרשם שיכיל מקומיname_idx : אינדקס מחרוזת של השםtype_idx : אינדקס סוג של הסוגsig_idx : אינדקס מחרוזת של חתימה של סוג
|
מגדיר משתנה מקומי עם חתימה של טיפוס בכתובת הנוכחית.
כל אחד מהערכים name_idx , type_idx או sig_idx יכול להיות NO_INDEX כדי לציין שהערך לא ידוע. (עם זאת, אם sig_idx הוא -1 , אפשר לייצג את אותם נתונים בצורה יעילה יותר באמצעות קוד הפקודה DBG_START_LOCAL ).
הערה: בהמשך, בקטע |
DBG_END_LOCAL | 0x05 | uleb128 register_num | register_num : רישום שהכיל local |
סימון משתנה מקומי פעיל כמשתנה מחוץ להיקף בכתובת הנוכחית |
DBG_RESTART_LOCAL | 0x06 | uleb128 register_num | register_num : רישום להפעלה מחדש |
מגדיר מחדש משתנה מקומי בכתובת הנוכחית. השם והסוג זהים לשם ולסוג של המזהה המקומי האחרון שהיה פעיל במרשם שצוין. |
DBG_SET_PROLOGUE_END | 0x07 | (none) | מגדיר את המרשם של מכונת המצב prologue_end , ומציין שצריך להתייחס לרשומת המיקום הבאה שנוספה כסוף של תחילת השיטה (מקום מתאים לנקודת עצירה בקוד של השיטה). כל קוד פעולה מיוחד (>= 0x0a ) מנקה את המרשם prologue_end .
|
|
DBG_SET_EPILOGUE_BEGIN | 0x08 | (none) | מגדיר את המרשם של מכונת המצב epilogue_begin , ומציין שצריך להתייחס לרשומת המיקום הבאה שתתווסף כתחילת חותמת הסיום של השיטה (מקום מתאים להשעיית הביצוע לפני יציאה מהשיטה).
כל קוד פעולה מיוחד (>= 0x0a ) מנקה את המרשם epilogue_begin .
|
|
DBG_SET_FILE | 0x09 | uleb128p1 name_idx | name_idx : אינדקס המחרוזת של שם קובץ המקור. אם הוא לא ידוע, הערך יהיה NO_INDEX .
|
מציין שכל הרשומות הבאות של מספרי השורות יפנו לשם של קובץ המקור הזה, במקום לשם ברירת המחדל שצוין ב-code_item .
|
Opcodes מיוחדים | 0x0a…0xff | (none) | מקדמת את המרשמים line ו-address , פולטת רשומת מיקום ומאפסת את prologue_end ו-epilogue_begin . תיאור מופיע בהמשך.
|
קודי פעולה מיוחדים
קוד הפקודה עם ערכים בין 0x0a
ל-0xff
(כולל) מעביר את הרישומים line
ו-address
בקטנה ואז פולט רשומה חדשה בטבלת המיקומים.
הנוסחה לחישוב העלייה היא:
DBG_FIRST_SPECIAL = 0x0a // the smallest special opcode DBG_LINE_BASE = -4 // the smallest line number increment DBG_LINE_RANGE = 15 // the number of line increments represented adjusted_opcode = opcode - DBG_FIRST_SPECIAL line += DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE) address += (adjusted_opcode / DBG_LINE_RANGE)
annotations_directory_item
הפניה מ-class_def_item
מופיע בקטע 'נתונים'
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
class_annotations_off | uint | הפרש מתחילת הקובץ אל ההערות שנוצרו ישירות על הכיתה, או 0 אם אין בכיתה הערות ישירות.
אם הערך של ההיסט שונה מאפס, הוא צריך להצביע למיקום בקטע data . הפורמט של הנתונים מצוין ב-annotation_set_item בהמשך.
|
fields_size | uint | מספר השדות שנוספה להם הערה על ידי הפריט הזה |
annotated_methods_size | uint | מספר השיטות שנוספה להן הערה על ידי הפריט הזה |
annotated_parameters_size | uint | מספר רשימות הפרמטרים של השיטות שנוספה להן הערה על ידי הפריט הזה |
field_annotations | field_annotation[fields_size] (אופציונלי) | רשימה של הערות שמשויכות לשדות. האלמנטים ברשימה חייבים להיות ממויינים בסדר עולה לפי field_idx .
|
method_annotations | method_annotation[methods_size] (אופציונלי) | רשימה של הערות לשיטות המשויכות. האלמנטים ברשימה חייבים להיות ממויינים בסדר עולה לפי method_idx .
|
parameter_annotations | parameter_annotation[parameters_size] (אופציונלי) | רשימה של הערות של פרמטרים משויכים של שיטות. צריך למיין את הרכיבים של הרשימה בסדר עולה לפי method_idx .
|
הערה: כל המופעים של field_id
ו-method_id
של הרכיבים חייבים להפנות לאותה כיתה מגדירה.
הפורמט של field_annotation
שם | פורמט | תיאור |
---|---|---|
field_idx | uint | חיפוש ברשימה field_ids כדי לזהות את השדה שאליו מצורפת ההערה
|
annotations_off | uint | הזזה מתחילת הקובץ אל רשימת ההערות של השדה. ההיסט צריך להיות למיקום בקטע data . הפורמט של הנתונים מצוין ב-annotation_set_item בהמשך.
|
פורמט method_annotation
שם | פורמט | תיאור |
---|---|---|
method_idx | uint | חיפוש ברשימה method_ids כדי לזהות את השיטה שרוצים להוסיף לה הערה
|
annotations_off | uint | מההתחלה של הקובץ ועד לרשימת ההערות של השיטה. ההיסט צריך להיות למיקום בקטע data . הפורמט של הנתונים מצוין ב-annotation_set_item בהמשך.
|
הפורמט של parameter_annotation
שם | פורמט | תיאור |
---|---|---|
method_idx | uint | חיפוש ברשימה method_ids כדי למצוא את הזהות של השיטה שאליה מצורפות הערות על הפרמטרים
|
annotations_off | uint | הזזה מתחילת הקובץ אל רשימת ההערות של פרמטרים של שיטות. ההיסט צריך להיות למיקום בקטע data . הפורמט של הנתונים מצוין ב-annotation_set_ref_list בהמשך.
|
annotation_set_ref_list
הפניה מ-parameter_annotations_item
מופיע בקטע 'נתונים'
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
size | uint | גודל הרשימה, בכניסות |
רשימה | annotation_set_ref_item[size] | הרכיבים של הרשימה |
הפורמט annotation_set_ref_item
שם | פורמט | תיאור |
---|---|---|
annotations_off | uint | הזזה מתחילת הקובץ אל קבוצת ההערות שצוינה,
או 0 אם אין הערות לאלמנט הזה.
אם הערך של ההיסט שונה מאפס, הוא צריך להצביע למיקום בקטע data . הפורמט של הנתונים מצוין ב-annotation_set_item בהמשך.
|
annotation_set_item
הפניה מ-annotations_directory_item, field_annotations_item, method_annotations_item ו-annotation_set_ref_item
מופיע בקטע 'נתונים'
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
size | uint | גודל הקבוצה, בכניסות |
רשומות | annotation_off_item[size] | הרכיבים של הקבוצה. האלמנטים חייבים להיות ממוינים בסדר עולה לפי type_idx .
|
פורמט annotation_off_item
שם | פורמט | תיאור |
---|---|---|
annotation_off | uint | הזזה מתחילת הקובץ להערה.
ההיסט צריך להיות למיקום בקטע data , והפורמט של הנתונים במיקום הזה מצוין ב-annotation_item שבהמשך.
|
annotation_item
הפניה מ-annotation_set_item
מופיע בקטע 'נתונים'
התאמה: ללא (יישור לפי בייטים)
שם | פורמט | תיאור |
---|---|---|
חשיפה | ubyte | רמת החשיפה המיועדת של ההערה הזו (ראו בהמשך) |
הערה | encoded_annotation | תוכן של הערות קודקדו, בפורמט שמתואר בקטע 'encoded_annotation format' בקטע 'encoded_value encoding' למעלה.
|
ערכי הרשאות הגישה
אלה האפשרויות בשדה visibility
ב-annotation_item
:
שם | ערך | תיאור |
---|---|---|
VISIBILITY_BUILD | 0x00 | מיועדים להיות גלויים רק בזמן ה-build (למשל, במהלך הידור של קוד אחר) |
VISIBILITY_RUNTIME | 0x01 | מיועדים להיות גלויים בזמן הריצה |
VISIBILITY_SYSTEM | 0x02 | נועדו להיות גלויים במהלך זמן הריצה, אבל רק למערכת הבסיסית (ולא לקוד משתמש רגיל) |
encoded_array_item
הפניה מ-class_def_item
מופיע בקטע 'נתונים'
התאמה: ללא (יישור לפי בייטים)
שם | פורמט | תיאור |
---|---|---|
ערך | encoded_array | ביטים שמייצגים את ערך המערך המקודד, בפורמט שצוין בשדה encoded_array Format בקטע encoded_value Encoding למעלה.
|
hiddenapi_class_data_item
הקטע הזה מכיל נתונים על ממשקים מוגבלים שבהם כל כיתה משתמשת.
הערה: התכונה של ה-API המוסתר הוצגה ב-Android 10.0 והיא רלוונטית רק לקובצי ה-DEX של הכיתות בנתיב הכיתות של האתחול. רשימת הדגלים שמתוארת בהמשך עשויה להתארך בגרסאות עתידיות של Android. מידע נוסף זמין במאמר הגבלות על ממשקים שאינם SDK.
שם | פורמט | תיאור |
---|---|---|
size | uint | הגודל הכולל של הקטע |
קיזוזים | uint[] | מערך של סטיות (offsets) שנוספו לאינדקס על ידי class_idx .
אם הערך ב-array הוא אפס ב-index class_idx , המשמעות היא שאין נתונים עבור class_idx הזה, או שכל הדגלים של ה-API המוסתרים הם אפס.
אחרת, הערך של רשומת המערך הוא לא אפס והוא מכיל את הזזת האופרטור (offset) מתחילת הקטע למערך של דגלים מוסתרים של API עבור class_idx הזה.
|
דגלים | uleb128[] | מערכי מחרוזות של דגלים מוסתרים של ממשקי API לכל כיתה. בטבלה הבאה מתוארים ערכי הדגל האפשריים. הדגלים מקודדים באותו סדר שבו השדות והשיטות מקודדים בנתוני הכיתה. |
סוגי דגלים של הגבלות:
שם | ערך | תיאור |
---|---|---|
רשימת היתרים | 0 | ממשקים שאפשר להשתמש בהם באופן חופשי ונתמכים כחלק ממסגרת Android הרשמית, Package Index. |
רשימה אפורה | 1 | ממשקים שאינם ב-SDK שאפשר להשתמש בהם ללא קשר לרמת ה-API לטירגוט של האפליקציה. |
הוסף לרשימה השחורה | 2 | ממשקים שאינם ב-SDK, שלא ניתן להשתמש בהם ללא קשר לרמת ה-API לטירגוט של האפליקציה. הגישה לאחד מהממשקים האלה גורמת לשגיאת זמן ריצה. |
greylist‑max‑o | 3 | ממשקים שאינם ב-SDK שאפשר להשתמש בהם ב-Android מגרסה 8.x ומטה, אלא אם הם מוגבלים. |
greylist‑max‑p | 4 | ממשקים שאינם SDK שאפשר להשתמש בהם ב-Android 9.x, אלא אם הם מוגבלים. |
greylist‑max‑q | 5 | ממשקים שאינם SDK שאפשר להשתמש בהם ב-Android 10.x, אלא אם הם מוגבלים. |
greylist‑max‑r | 6 | ממשקים שאינם SDK שאפשר להשתמש בהם ב-Android 11.x, אלא אם הם מוגבלים. |
הערות מערכת
הערות מערכת משמשות לייצוג קטעים שונים של מידע רפלקטיבי על כיתות (וגם על שיטות ושדות). בדרך כלל, קוד לקוח (לא מערכת) ניגש למידע הזה באופן עקיף בלבד.
הערות מערכת מיוצגות בקובצי .dex
בתור הערות שההרשאות הגישה שלהן מוגדרות לערך VISIBILITY_SYSTEM
.
dalvik.annotation.AnnotationDefault
מופיע בשיטות בממשקי הערה
הערה AnnotationDefault
מצורפת לכל ממשק הערה שרוצים לציין בו קישורי ברירת מחדל.
שם | פורמט | תיאור |
---|---|---|
ערך | הערה | קישורי ברירת המחדל של ההערה הזו, שמיוצגים כהערה מסוג זה. ההערה לא חייבת לכלול את כל השמות שמוגדרים בה. שמות חסרים פשוט לא יהיו להם ברירת מחדל. |
dalvik.annotation.EnclosingClass
מופיע בכיתות
הערה EnclosingClass
מצורפת לכל מחלקה שמוגדרת כחברה במחלקה אחרת, או כאנונימית אבל לא מוגדרת בגוף של method (למשל, מחלקה פנימית סינתטית). לכל כיתה עם ההערה הזו צריכה להיות גם הערה מסוג InnerClass
. בנוסף, אסור לכלול בכיתה גם הערה מסוג EnclosingClass
וגם הערה מסוג EnclosingMethod
.
שם | פורמט | תיאור |
---|---|---|
ערך | דרגה | הכיתה שהכי קרובה לכיתה הזו מבחינה לקסיקלית |
dalvik.annotation.EnclosingMethod
מופיע בכיתות
הערה EnclosingMethod
מצורפת לכל כיתה שמוגדרת בגוף של שיטה. לכל כיתה עם ההערה הזו צריכה להיות גם הערה מסוג InnerClass
.
בנוסף, אסור שיהיו בכיתה גם הערה מסוג EnclosingClass
וגם הערה מסוג EnclosingMethod
.
שם | פורמט | תיאור |
---|---|---|
ערך | שיטה | השיטה שמתאימה ביותר להיקף הלקסיקלי של הכיתה |
dalvik.annotation.InnerClass
מופיע בכיתות
הערה InnerClass
מצורפת לכל כיתה שמוגדרת בהיקף הלקסיקלי של הגדרת כיתה אחרת.
כל כיתה עם ההערה הזו חייבת לכלול גם הערה מסוג EnclosingClass
או הערה מסוג EnclosingMethod
.
שם | פורמט | תיאור |
---|---|---|
שם | מחרוזת | השם הפשוט שהוצהר במקור של הכיתה הזו (לא כולל תחילית של חבילה). אם הכיתה הזו אנונימית, השם הוא null .
|
accessFlags | INT | דגלים של גישה שהוצהרו במקור על הכיתה (שעשויים להיות שונים מדגלים יעילים בגלל חוסר התאמה בין מודלים של ביצוע של שפת המקור לבין מכונה וירטואלית של היעד) |
dalvik.annotation.MemberClasses
מופיע בכיתות
הערה MemberClasses
מצורפת לכל כיתה שמצהירה על כיתות חברות. (כיתה חברת היא כיתה פנימית ישירה שיש לה שם).
שם | פורמט | תיאור |
---|---|---|
ערך | Class[] | מערך של כיתות החברים |
dalvik.annotation.MethodParameters
מופיע בשיטות
הערה: ההערה הזו נוספה אחרי Android 7.1. המערכת תתעלם מהנוכחות שלו בגרסאות Android קודמות.
הערה MethodParameters
היא אופציונלית, וניתן להשתמש בה כדי לספק מטא-נתונים של פרמטרים, כמו שמות פרמטרים ומשתני פונקציה.
אפשר להשמיט את ההערה מ-method או מ-constructor באופן בטוח אם המטא-נתונים של הפרמטר לא נדרשים במהלך זמן הריצה.
אפשר להשתמש ב-java.lang.reflect.Parameter.isNamePresent()
כדי לבדוק אם יש מטא-נתונים לפרמטר, ושיטות ההשתקפות המשויכות, כמו java.lang.reflect.Parameter.getName()
, יחזרו להתנהגות ברירת המחדל בזמן הריצה אם המידע לא קיים.
כשכוללים מטא-נתונים של פרמטרים, המהדרים חייבים לכלול מידע על כיתות שנוצרו, כמו enums, כי המטא-נתונים של הפרמטרים כוללים את הקביעה אם הפרמטר הוא סינתטי או נדרש.
הערה מסוג MethodParameters
מתארת רק פרמטרים נפרדים של שיטות. לכן, כדי לצמצם את גודל הקוד ולשפר את היעילות בסביבת זמן הריצה, המהדרים עשויים להשמיט את ההערה לגמרי לגבי קונסטרוקטורים ושיטות ללא פרמטרים.
המערכים שמתוארים בהמשך חייבים להיות באותו גודל כמו המבנה של method_id_item
dex שמשויך לשיטה, אחרת תופיע הודעת השגיאה java.lang.reflect.MalformedParametersException
בזמן הריצה.
כלומר: method_id_item.proto_idx
->
proto_id_item.parameters_off
->
type_list.size
חייב להיות זהה ל-names().length
ול-accessFlags().length
.
מכיוון ש-MethodParameters
מתאר את כל הפרמטרים הפורמליים של השיטה, גם אלה שלא הוגדרו במפורש או במשתמע בקוד המקור, ייתכן שהגודל של המערכי יכול להיות שונה מהחתימה או מנתוני המטא-נתונים האחרים שמבוססים רק על פרמטרים מפורשים שהוגדרו בקוד המקור. MethodParameters
לא יכלול גם מידע על פרמטרים של מקבלים של הערות לסוגים שלא קיימים בחתימת השיטה בפועל.
שם | פורמט | תיאור |
---|---|---|
שמות | String[] | השמות של הפרמטרים הפורמליים של השיטה המשויכת. המערך לא יכול להיות null, אבל הוא חייב להיות ריק אם אין פרמטרים רשמיים. אם לפרמטר הפורמלי עם האינדקס הזה אין שם, הערך במערך חייב להיות null. אם מחרוזות של שמות פרמטרים ריקות או מכילות את התו '.', ';', '[' או '/', תושלח הודעת השגיאה java.lang.reflect.MalformedParametersException בזמן הריצה.
|
accessFlags | int[] | דגלים של גישה של הפרמטרים הפורמליים של השיטה המשויכת. המערך לא יכול להיות null, אבל הוא חייב להיות ריק אם אין פרמטרים פורמליים. הערך הוא מסכת ביט עם הערכים הבאים:
java.lang.reflect.MalformedParametersException בסביבת זמן הריצה.
|
dalvik.annotation.Signature
מופיע בכיתות, בשדות ובשיטות
הערה מסוג Signature
מצורפת לכל כיתה, שדה או שיטה שמוגדרים במונחים של טיפוס מורכב יותר שלא ניתן לייצג באמצעות type_id_item
. הפורמט .dex
לא מגדיר את הפורמט לחתימות, אלא רק מאפשר לייצג את כל החתימות שנדרשות בשפת המקור כדי להטמיע בהצלחה את הסמנטיקה של השפה הזו. לכן, בדרך כלל חתימות לא מנותחות (או מאומתות) על ידי הטמעות של מכונות וירטואליות. החתימה מועברת ל-API ולכלים ברמה גבוהה יותר (כמו מניפולי קוד). לכן, כל שימוש בחתימה צריך להיכתב כך שלא יתבסס על הנחה שתקבלו רק חתימות תקינות, ויש להימנע מכך באופן מפורש כדי להימנע מהאפשרות לקבל חתימה לא תקינה מבחינה תחבירית.
מאחר שמחרוזות חתימה נוטים להכיל הרבה תוכן כפול, הערה מסוג Signature
מוגדרת כמערך של מחרוזות, שבהן רכיבים כפולים מתייחסים באופן טבעי לאותו נתון בסיסי, והחתימה נחשבת לשרשור של כל המחרוזות במערך. אין כללים לגבי אופן הפירוק של חתימה למחרוזות נפרדות. הדבר תלוי לחלוטין בכלים שיוצרים את קובצי ה-.dex
.
שם | פורמט | תיאור |
---|---|---|
ערך | String[] | החתימה של הכיתה או המשתנה, כמערך של מחרוזות שצריך לשרשור יחד |
dalvik.annotation.Throws
מופיע בשיטות
הערה מסוג Throws
מצורפת לכל שיטה שמוצהרת כמייצרת סוג אחד או יותר של חריגות.
שם | פורמט | תיאור |
---|---|---|
ערך | Class[] | מערך סוגי החריגות שהופעלו |