במסמך הזה מתואר הפריסה והתוכן של קובצי .dex
, שמשמשים להחזקת קבוצה של הגדרות מחלקה ונתוני העזר המשויכים אליהם.
מדריך לסוגים
שם | תיאור |
---|---|
בייט | 8-bit signed int |
ubyte | 8-bit unsigned int |
סרטון קצר | 16-bit signed int, little-endian |
ushort | 16 ביט ללא סימן, little-endian |
INT | מספר שלם עם סימן ב-32 ביט, little-endian |
uint | 32-bit unsigned int, little-endian |
ארוך | 64-bit signed int, little-endian |
ulong | 64 ביט ללא סימן, little-endian |
sleb128 | LEB128 חתום, באורך משתנה (ראו בהמשך) |
uleb128 | LEB128 לא חתום, באורך משתנה (ראו בהמשך) |
uleb128p1 | LEB128 לא חתום בתוספת 1 , אורך משתנה (ראו בהמשך) |
LEB128
LEB128 (קיצור של Little-Endian Base 128) הוא קידוד באורך משתנה של כמויות של מספרים שלמים חיוביים או שליליים. הפורמט נלקח ממפרט DWARF3. בקובץ .dex
, נעשה שימוש ב-LEB128 רק כדי לקודד כמויות של 32 ביט.
כל ערך בקידוד LEB128 מורכב מ-1 עד 5 בייטים, שמייצגים ביחד ערך יחיד של 32 ביט. הביט הכי משמעותי של כל בייט מוגדר, חוץ מהבייט האחרון ברצף, שבו הביט הכי משמעותי לא מוגדר. שבעת הביטים הנותרים של כל בייט הם מטען ייעודי (payload), כאשר שבעת הביטים הכי פחות משמעותיים של הכמות נמצאים בבייט הראשון, שבעת הביטים הבאים נמצאים בבייט השני וכן הלאה. במקרה של LEB128 עם סימן (sleb128
), הביט הכי משמעותי של המטען הייעודי (payload) בבייט האחרון ברצף הוא הרחבת הסימן כדי ליצור את הערך הסופי. במקרה של מספר לא חתום (uleb128
), כל הביטים שלא מיוצגים במפורש מתפרשים כ-0
.
תרשים ברמת הסיביות של ערך LEB128 באורך שני בייטים | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
הבייט הראשון | הבייט השני | ||||||||||||||
1 |
bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | 0 |
bit13 | bit12 | bit11 | bit10 | bit9 | bit8 | bit7 |
הווריאנט 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 (לפי אינדקס proto_id ) הוא הסדר הזניח. הרשימה לא יכולה להכיל רשומות כפולות.
|
class_defs | class_def_item[] | רשימת הגדרות הכיתות. הסדר של המחלקות צריך להיות כזה שהמחלקה העל והממשקים המיושמים של מחלקה נתונה יופיעו ברשימה לפני המחלקה המפנה. בנוסף, אסור להגדיר את אותו שם של מחלקה יותר מפעם אחת ברשימה. |
call_site_ids | call_site_id_item[] | רשימת מזהי אתרים לשיחות. אלה מזהים של כל האתרים שמוזכרים בקובץ הזה, בין אם הם מוגדרים בקובץ ובין אם לא. הרשימה הזו צריכה להיות ממוינת בסדר עולה לפי call_site_off .
|
method_handles | method_handle_item[] | רשימת method handles. רשימה של כל ה-method handles שאליהם יש הפניה בקובץ הזה, בין אם הם מוגדרים בקובץ ובין אם לא. הרשימה הזו לא ממוינת ועשויות להיות בה כפילויות, שיתאימו באופן לוגי למופעים שונים של טיפול בשיטות. |
נתונים | 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
) ובייט null ("\0"
או 0x00
) כדי לעזור בזיהוי של סוגים מסוימים של נזק. הערך גם מקודד מספר גרסת פורמט כשלוש ספרות עשרוניות, שאמורות לגדול באופן מונוטוני לאורך זמן ככל שהפורמט מתפתח.
ubyte[8] DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x39 0x00 } = "dex\n039\0"
הערה: התמיכה בגרסה 041
של הפורמט נוספה בגרסה Android 16, עם תמיכה בפורמט המאגר.
הערה: התמיכה בגרסה 040
של הפורמט נוספה בגרסת Android 10.0, שהרחיבה את קבוצת התווים המותרים ב-SimpleNames.
הערה: התמיכה בגרסה 039
של הפורמט נוספה בגרסת Android 9.0, שכללה שני בייטקודים חדשים, const-method-handle
ו-const-method-type
. (כל אחד מהם מתואר בטבלה סיכום של קבוצת בייטקוד). ב-Android 10, גרסה 039
מרחיבה את פורמט קובץ ה-DEX וכוללת מידע על API מוסתר שרלוונטי רק לקובצי DEX בנתיב המחלקה של אתחול המערכת.
הערה: התמיכה בגרסה 038
של הפורמט נוספה בגרסה Android 8.0. בגרסה 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 : global to defining class |
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 | הארגומנט האחרון צריך להיות מטופל כארגומנט 'rest' על ידי הקומפיילר | ||
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
מקודדת בפורמט של שני בייטים. - בדומה לפרשנות הסטנדרטית בשפת C, בייט null רגיל (ערך
0
) מציין את סוף המחרוזת.
אפשר לסכם את שני הפריטים הראשונים שלמעלה כך: 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 | (none; must be 0 ) |
ubyte[1] | ערך של מספר שלם חתום באורך בית אחד |
VALUE_SHORT | 0x02 | גודל – 1 (0…1) | ubyte[size] | ערך של מספר שלם עם סימן בגודל שני בתים, עם הרחבת סימן |
VALUE_CHAR | 0x03 | גודל – 1 (0…1) | ubyte[size] | ערך של מספר שלם לא מסומן באורך שני בייטים, עם הרחבה לאפס |
VALUE_INT | 0x04 | גודל – 1 (0…3) | ubyte[size] | ערך של מספר שלם עם סימן באורך ארבעה בתים, עם הרחבת סימן |
VALUE_LONG | 0x06 | מידה – 1 (0…7) | ubyte[size] | ערך של מספר שלם עם סימן בגודל שמונה בתים, עם הרחבת סימן |
VALUE_FLOAT | 0x10 | גודל – 1 (0…3) | ubyte[size] | תבנית סיביות של ארבעה בייטים, עם הרחבה לאפס מימין, ועם פירוש כערך נקודה צפה של 32 ביט לפי IEEE754 |
VALUE_DOUBLE | 0x11 | מידה – 1 (0…7) | ubyte[size] | תבנית ביטים של שמונה בייטים, עם הרחבה לאפס מימין, ועם פירוש כערך נקודה צפה של 64 ביט לפי IEEE754 |
VALUE_METHOD_TYPE | 0x15 | גודל – 1 (0…3) | ubyte[size] | ערך שלם לא חתום (עם הרחבה לאפס) באורך ארבעה בייטים,
שמתפרש כאינדקס בקטע proto_ids ומייצג ערך של סוג שיטה
|
VALUE_METHOD_HANDLE | 0x16 | גודל – 1 (0…3) | ubyte[size] | ערך של מספר שלם לא חתום (עם הרחבת אפסים) באורך ארבעה בייטים,
שמתפרש כאינדקס בקטע method_handles ומייצג ערך של נקודת אחיזה למתודה
|
VALUE_STRING | 0x17 | גודל – 1 (0…3) | ubyte[size] | ערך שלם ללא סימן (עם הרחבה לאפס) באורך ארבעה בייטים,
מתפרש כאינדקס בקטע string_ids ומייצג ערך מחרוזת
|
VALUE_TYPE | 0x18 | גודל – 1 (0…3) | ubyte[size] | ערך שלם ללא סימן (עם הרחבה לאפס) באורך ארבעה בייטים,
שמפורש כאינדקס בקטע type_ids ומייצג ערך רפלקטיבי של סוג או מחלקה
|
VALUE_FIELD | 0x19 | גודל – 1 (0…3) | ubyte[size] | ערך שלם ללא סימן (עם הרחבה לאפס) באורך ארבעה בייטים,
שמפורש כאינדקס בקטע field_ids ומייצג ערך שדה רפלקטיבי
|
VALUE_METHOD | 0x1a | גודל – 1 (0…3) | ubyte[size] | ערך של מספר שלם לא חתום (עם הרחבה לאפס) באורך ארבעה בייטים,
שמתפרש כאינדקס בקטע method_ids ומייצג ערך של שיטה רפלקטיבית
|
VALUE_ENUM | 0x1b | גודל – 1 (0…3) | ubyte[size] | ערך של מספר שלם ללא סימן (עם הרחבה לאפס) באורך ארבעה בייטים,
שמפורש כאינדקס בקטע field_ids ומייצג את הערך של
קבוע מסוג מנומר
|
VALUE_ARRAY | 0x1c | (none; must be 0 ) |
encoded_array | מערך של ערכים, בפורמט שצוין בקטע
'encoded_array format' שבהמשך. הגודל
של value מרומז בקידוד.
|
VALUE_ANNOTATION | 0x1d | (none; must be 0 ) |
encoded_annotation | הערת משנה, בפורמט שצוין בקטע
encoded_annotation format למטה. הגודל
של value מרומז בקידוד.
|
VALUE_NULL | 0x1e | (none; must be 0 ) |
(none) | ערך הייחוס null |
VALUE_BOOLEAN | 0x1f | בוליאני (0…1) | (none) | ערך של ביט אחד; 0 עבור false ו-1 עבור true . הביט מיוצג ב-value_arg .
|
הפורמט של encoded_array
שם | פורמט | תיאור |
---|---|---|
size | uleb128 | מספר הרכיבים במערך |
values | encoded_value[size] | סדרה של רצפי size encoded_value בייט
בפורמט שצוין בקטע הזה, שמשורשרים
בסדר.
|
הפורמט של encoded_annotation
שם | פורמט | תיאור |
---|---|---|
type_idx | uleb128 | הסוג של ההערה. הערך הזה חייב להיות מסוג class (לא array או primitive). |
size | uleb128 | מספר המיפויים של שם-ערך בהערה הזו |
רכיבים | annotation_element[size] | רכיבים של ההערה, שמיוצגים ישירות בשורה (לא כהיסטים). צריך למיין את הרכיבים בסדר עולה לפי אינדקס string_id .
|
הפורמט של רכיב ההערה
שם | פורמט | תיאור |
---|---|---|
name_idx | uleb128 | שם הרכיב, שמיוצג כמדד בקטע string_ids . המחרוזת צריכה להיות תואמת לתחביר של MemberName, שמוגדר למעלה.
|
ערך | encoded_value | ערך של רכיב |
תחביר של מחרוזות
יש כמה סוגים של פריטים בקובץ .dex
, שבסופו של דבר מתייחסים למחרוזת. ההגדרות הבאות בסגנון BNF מציינות את התחביר המקובל למחרוזות האלה.
SimpleName
SimpleName הוא הבסיס לתחביר של שמות של דברים אחרים. .dex
הפורמט מאפשר מידה רבה של חופש פעולה (הרבה יותר משפות מקור נפוצות). בקצרה, שם פשוט מורכב מכל תו אלפביתי או ספרה ב-ASCII נמוך, כמה סמלים ספציפיים ב-ASCII נמוך ורוב נקודות הקוד שאינן ASCII, שלא משמשות כתווי בקרה, רווח או תווים מיוחדים. החל מגרסה 040
הפורמט מאפשר גם רווחים (קטגוריית Unicode Zs
). שימו לב שנקודות קוד חלופיות (בטווח U+d800
עד U+dfff
) לא נחשבות כתווים חוקיים בשם, אבל תווים משלימים של Unicode כן נחשבים חוקיים (והם מיוצגים על ידי האפשרות האחרונה של הכלל ל-SimpleNameChar), והם צריכים להיות מיוצגים בקובץ כזוגות של נקודות קוד חלופיות בקידוד MUTF-8.
SimpleName → | ||
SimpleNameChar (SimpleNameChar)* | ||
SimpleNameChar → | ||
'A' … 'Z' |
||
| | 'a' … 'z' |
|
| | '0' … '9' |
|
| | ' ' |
מגרסת DEX 040 ואילך |
| | '$' |
|
| | '-' |
|
| | '_' |
|
| | U+00a0 |
מגרסת DEX 040 ואילך |
| | U+00a1 … U+1fff |
|
| | U+2000 … U+200a |
מגרסת DEX 040 ואילך |
| | U+2010 … U+2027 |
|
| | U+202f |
מגרסת DEX 040 ואילך |
| | U+2030 … U+d7ff |
|
| | U+e000 … U+ffef |
|
| | U+10000 … U+10ffff |
שם החבר
משמש את 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 בייטים
שם | פורמט | תיאור |
---|---|---|
קסם | ubyte[8] = DEX_FILE_MAGIC | ערך קסום. פרטים נוספים מופיעים בדיון שלמעלה בקטע DEX_FILE_MAGIC .
|
סכום ביקורת | uint | סכום ביקורת מסוג adler32 של שאר הקובץ (הכול חוץ מ-
magic והשדה הזה); משמש לזיהוי קובץ פגום
|
חתימה | ubyte[20] | חתימת 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 | ההיסט מתחילת הקובץ לרשימת הגדרות המחלקה, או
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 | גודל הרשימה, במספר הרשומות |
list | 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
מופיע בקטע הנתונים
התאמה: none (byte-aligned)
שם | פורמט | תיאור |
---|---|---|
utf16_size | uleb128 | הגודל של המחרוזת הזו, ביחידות קוד UTF-16 (שזה ה-'string
length' במערכות רבות). כלומר, זהו האורך המפוענח של המחרוזת. (האורך המקודד משתמע ממיקום הבייט 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 | index into the type_ids list for the return type
of this prototype
|
parameters_off | uint | ההיסט מתחילת הקובץ עד לרשימת סוגי הפרמטרים
בפרוטוטייפ הזה, או 0 אם בפרוטוטייפ הזה אין
פרמטרים. אם ההיסט הזה שונה מאפס, הוא צריך להיות בקטע data , והנתונים שם צריכים להיות בפורמט שצוין ב-"type_list" למטה. בנוסף, ברשימה לא צריכה להיות הפניה לסוג void .
|
field_id_item
מופיע בקטע field_ids
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
class_idx | ushort | אינדקס ברשימה type_ids של מגדיר השדה הזה. המאפיין הזה חייב להיות מסוג class, ולא מסוג מערך או מסוג פרימיטיבי.
|
type_idx | ushort | אינדקס ברשימה type_ids של סוג השדה
|
name_idx | uint | index into the string_ids list for the name of this
field. המחרוזת חייבת להיות תואמת לתחביר של MemberName,
שמוגדר למעלה.
|
method_id_item
מופיע בקטע method_ids
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
class_idx | ushort | אינדקס ברשימה type_ids של מגדיר השיטה הזו. המאפיין הזה חייב להיות מסוג class או array, ולא מסוג primitive.
|
proto_idx | ushort | אינדקס ברשימת proto_ids לאב-טיפוס של השיטה הזו
|
name_idx | uint | אינדקס לתוך הרשימה string_ids כדי לקבל את השם של השיטה הזו. המחרוזת חייבת להיות תואמת לתחביר של MemberName,
שמוגדר למעלה.
|
class_def_item
מופיע בקטע class_defs
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
class_idx | uint | אינדקס לתוך רשימת type_ids של הכיתה הזו.
המאפיין הזה חייב להיות מסוג class, ולא מסוג מערך או מסוג פרימיטיבי.
|
access_flags | uint | דגלי גישה לכיתה (public , final וכו'). פרטים נוספים מופיעים בקטע access_flags הגדרות.
|
superclass_idx | uint | האינדקס ברשימה type_ids של מחלקת העל, או
הערך הקבוע NO_INDEX אם למחלקה הזו אין
מחלקת על (כלומר, זו מחלקת בסיס כמו Object ).
אם השדה הזה קיים, הוא חייב להיות מסוג מחלקה, ולא מסוג מערך או מסוג פרימיטיבי.
|
interfaces_off | uint | ההיסט מתחילת הקובץ עד לרשימת הממשקים, או 0 אם אין ממשקים. ההיסט הזה
צריך להיות בקטע data , והנתונים
שם צריכים להיות בפורמט שצוין
בקטע type_list שבהמשך. כל אחד מהאלמנטים ברשימה
חייב להיות מסוג מחלקה (לא מערך או סוג פרימיטיבי), ואסור שיהיו כפילויות.
|
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
מופיע בקטע הנתונים
התאמה: none (byte aligned)
call_site_item הוא encoded_array_item שהאלמנטים שלו תואמים לארגומנטים שסופקו לשיטת bootstrap linker. שלושת הארגומנטים הראשונים הם:
- method handle שמייצג את שיטת ה-bootstrap linker (VALUE_METHOD_HANDLE).
- שם של שיטה שצריך לפתור באמצעות bootstrap linker (VALUE_STRING).
- סוג ה-method שמתאים לסוג של שם ה-method שצריך לפתור (VALUE_METHOD_TYPE).
כל הארגומנטים הנוספים הם ערכים קבועים שמועברים לשיטת הקישור של bootstrap. הארגומנטים האלה מועברים לפי הסדר וללא המרות מסוג כלשהו.
לשיטת ה-handle שמייצגת את שיטת ה-bootstrap linker צריך להיות סוג החזרה 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 הוא שדה סטטי setter (רכיב גישה) |
METHOD_HANDLE_TYPE_STATIC_GET | 0x01 | Method handle is a static field getter (accessor) |
METHOD_HANDLE_TYPE_INSTANCE_PUT | 0x02 | Method handle הוא שדה מופע של setter (אחזור נתונים) |
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 is an interface method invoker |
class_data_item
הפניה מ-class_def_item
מופיע בקטע הנתונים
התאמה: none (byte-aligned)
שם | פורמט | תיאור |
---|---|---|
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 | ההיסט מתחילת הקובץ למבנה הקוד של ה-method הזה, או 0 אם ה-method הזה הוא abstract או native . ההיסט צריך להיות למיקום בקטע data . הפורמט של הנתונים מוגדר על ידי
"code_item " בהמשך.
|
type_list
הפניה מ-class_def_item ומ-proto_id_item
מופיע בקטע הנתונים
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
size | uint | גודל הרשימה, במספר הרשומות |
list | type_item[size] | אלמנטים ברשימה |
type_item format
שם | פורמט | תיאור |
---|---|---|
type_idx | ushort | אינדקס לרשימה type_ids |
code_item
הפניה מ-encoded_method
מופיע בקטע הנתונים
התאמה: 4 בייטים
שם | פורמט | תיאור |
---|---|---|
registers_size | ushort | מספר הרגיסטרים שנעשה בהם שימוש בקוד הזה |
ins_size | ushort | מספר המילים של הארגומנטים הנכנסים לשיטה שאליה הקוד הזה מתייחס |
outs_size | ushort | מספר המילים של מרחב הארגומנטים היוצא שנדרש לקוד הזה להפעלת שיטה |
tries_size | ushort | מספר ה-try_item s במופע הזה. אם הערך שמוגדר הוא לא אפס,
הם מופיעים כמערך tries מיד אחרי
insns במופע הזה.
|
debug_info_off | uint | ההיסט מתחילת הקובץ לרצף של פרטי הניפוי (מספרי שורות +
פרטים על משתנים מקומיים) של הקוד הזה, או 0 אם פשוט אין פרטים. אם ההיסט שונה מאפס, הוא צריך להיות
במיקום בקטע data . הפורמט של
הנתונים מפורט בקטע debug_info_item שבהמשך.
|
insns_size | uint | הגודל של רשימת ההוראות, ביחידות קוד של 16 ביט |
insns | ushort[insns_size] | מערך בפועל של קוד בייט. הפורמט של הקוד במערך insns מפורט במסמך הנלווה Dalvik bytecode. הערה: למרות שההגדרה היא מערך של ushort , יש כמה מבנים פנימיים שמעדיפים יישור של ארבעה בייטים. בנוסף,
אם זה קורה בקובץ עם החלפת סדר בתים, ההחלפה מתבצעת רק במופעים של ushort ולא במבנים הפנימיים הגדולים יותר.
|
padding | ushort (אופציונלי) = 0 | שני בייטים של ריפוד כדי ש-tries יהיה מיושר לארבעה בייטים.
האלמנט הזה מופיע רק אם tries_size שונה מאפס ו-insns_size הוא מספר אי-זוגי.
|
מנסה | מידת הפריט [tries_size](אופציונלי) | מערך שמציין איפה בקוד נתפסים חריגים ואיך לטפל בהם. האלמנטים במערך לא יכולים להיות חופפים בטווח, והם צריכים להיות מסודרים מהכתובת הנמוכה לכתובת הגבוהה. האלמנט הזה מופיע רק אם הערך של tries_size הוא לא אפס.
|
רכיבי handler | encoded_catch_handler_list (אופציונלי) | בייטים שמייצגים רשימה של רשימות של סוגי חריגים וכתובות של
מטפלים משויכים. לכל 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 | גודל הרשימה הזו, במספר הרשומות |
list | encoded_catch_handler[handlers_size] | רשימה בפועל של רשימות handler, שמוצגת ישירות (לא כהיסטים), ומשורשרת ברצף |
הפורמט של encoded_catch_handler
שם | פורמט | תיאור |
---|---|---|
size | sleb128 | מספר סוגי התפיסה ברשימה הזו. אם הערך לא חיובי, הוא יהיה שווה לערך השלילי של מספר סוגי ה-catch, ואחרי ה-catch יופיע handler של catch-all. לדוגמה: A size of 0
means that there is a catch-all but no explicitly typed catches.
הערך size של 2 מציין שיש שני תנאי catch עם הקלדה מפורשת, ואין תנאי catch כללי. size of -1
פירושו שיש כתובת אחת עם הקלדה שגויה וכתובת אחת עם כלל.
|
רכיבי handler | encoded_type_addr_pair[abs(size)] | זרם של abs(size) פריטים מקודדים, אחד לכל סוג שנתפס, בסדר שבו הסוגים צריכים להיבדק.
|
catch_all_addr | uleb128 (אופציונלי) | כתובת bytecode של ה-handler של כתובת מסלקת דואר. האלמנט הזה מופיע רק אם הערך של size הוא לא חיובי.
|
הפורמט של encoded_type_addr_pair
שם | פורמט | תיאור |
---|---|---|
type_idx | uleb128 | index into the type_ids list for the type of the
exception to catch
|
addr | uleb128 | כתובת ה-bytecode של ה-exception handler המשויך |
debug_info_item
הפניה מ-code_item
מופיע בקטע הנתונים
התאמה: none (byte-aligned)
כל debug_info_item
מגדיר מכונת מצבים בקידוד בייטים בהשראת DWARF3, שכשהיא מפורשת, היא פולטת את טבלת המיקומים ואת מידע המשתנים המקומיים של code_item
(אם יש). הרצף מתחיל בכותרת באורך משתנה (האורך תלוי במספר הפרמטרים של השיטה), ואחריה מופיעים בייטים של קוד מכונת המצבים, והוא מסתיים בבייט DBG_END_SEQUENCE
.
מכונת המצבים מורכבת מחמישה אוגרים. address
register מייצג את ההיסט של ההוראה ב-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 : רישום שיכיל את המשתנה localname_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 : register שיכיל את המידע המקומי 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 : register that contained local |
מסמן משתנה מקומי שפעיל כרגע כמשתנה שלא נמצא בהיקף בכתובת הנוכחית |
DBG_RESTART_LOCAL | 0x06 | uleb128 register_num | register_num : צריך להירשם כדי להפעיל מחדש |
מגדיר מחדש משתנה מקומי בכתובת הנוכחית. השם והסוג זהים לאלה של הלוקאל האחרון שהיה פעיל ברשם שצוין. |
DBG_SET_PROLOGUE_END | 0x07 | (none) | מגדיר את הרגיסטר של מכונת המצבים prologue_end , כדי לציין שערך הכניסה הבא למיקום שנוסף צריך להיחשב כסוף של הקדמה של שיטה (מקום מתאים לנקודת עצירה של שיטה). הרישום prologue_end מתבצע על ידי כל קוד פעולה מיוחד (>= 0x0a ).
|
|
DBG_SET_EPILOGUE_BEGIN | 0x08 | (none) | מגדיר את epilogue_begin הרישום של מכונת המצבים, ומציין שרשומה של מיקום הבא שנוספת צריכה להיחשב כהתחלה של אפילוג של שיטה (מקום מתאים להשהיית הביצוע לפני היציאה מהשיטה).
הרישום epilogue_begin מתבטל על ידי כל קוד פעולה מיוחד (>= 0x0a ).
|
|
DBG_SET_FILE | 0x09 | uleb128p1 name_idx | name_idx : אינדקס המחרוזת של שם קובץ המקור; אם לא ידועNO_INDEX
|
מציין שכל הערכים הבאים של מספרי השורות מתייחסים לשם קובץ המקור הזה, במקום לשם ברירת המחדל שצוין ב-code_item
|
Special 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 | גודל הרשימה, במספר הרשומות |
list | annotation_set_ref_item[size] | אלמנטים ברשימה |
annotation_set_ref_item format
שם | פורמט | תיאור |
---|---|---|
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
מופיע בקטע הנתונים
התאמה: none (byte-aligned)
שם | פורמט | תיאור |
---|---|---|
חשיפה | ubyte | הגדרת החשיפה המיועדת של ההערה הזו (ראו בהמשך) |
הערה | encoded_annotation | תוכן ההערה המקודד, בפורמט שמתואר בקטע encoded_annotation format (פורמט encoded_annotation ) למעלה.encoded_value
|
ערכי הרשאות הגישה
אלה האפשרויות לשדה visibility
ב-annotation_item
:
שם | ערך | תיאור |
---|---|---|
VISIBILITY_BUILD | 0x00 | מיועד רק להיות גלוי בזמן הבנייה (למשל, במהלך קומפילציה של קוד אחר) |
VISIBILITY_RUNTIME | 0x01 | מיועד להיות גלוי בזמן ריצה |
VISIBILITY_SYSTEM | 0x02 | מיועד להיות גלוי בזמן הריצה, אבל רק למערכת הבסיסית (ולא לקוד משתמש רגיל) |
encoded_array_item
הפניה מ-class_def_item
מופיע בקטע הנתונים
התאמה: none (byte-aligned)
שם | פורמט | תיאור |
---|---|---|
ערך | encoded_array | בייטים שמייצגים את ערך המערך המקודד, בפורמט שצוין בקטע encoded_array פורמט בקטע encoded_value קידוד שלמעלה.
|
hiddenapi_class_data_item
בקטע הזה מופיעים נתונים על ממשקים מוגבלים שבהם נעשה שימוש בכל כיתה.
הערה: התכונה של API מוסתר הושקה ב-Android 10.0 והיא רלוונטית רק לקובצי DEX של מחלקות בנתיב המחלקה של אתחול המערכת. יכול להיות שרשימת הדגלים שמתוארת בהמשך תורחב בגרסאות עתידיות של Android. מידע נוסף זמין במאמר בנושא הגבלות על ממשקי SDK שאינם ממשקי SDK של Google.
שם | פורמט | תיאור |
---|---|---|
size | uint | הגודל הכולל של החלק |
קיזוזים | uint[] | מערך של היסטים שממוינים לפי class_idx .
ערך אפס במערך באינדקס class_idx מציין שאו שאין נתונים עבור class_idx , או שכל הדגלים של ה-API המוסתר הם אפס.
אחרת, הערך במערך שונה מאפס ומכיל היסט מתחילת הקטע למערך של דגלי API מוסתרים עבור class_idx .
|
דיווחים | uleb128[] | מערכים משורשרים של דגלים סמויים של API לכל מחלקה. בטבלה הבאה מתוארים הערכים האפשריים של הדגל. הדגלים מקודדים באותו סדר שבו השדות והשיטות מקודדים בנתוני הכיתה. |
סוגי דגלי הגבלה:
שם | ערך | תיאור |
---|---|---|
רשימת היתרים | 0 | ממשקים שאפשר להשתמש בהם באופן חופשי ונתמכים כחלק מאינדקס החבילות של מסגרת Android שמתועדת באופן רשמי. |
רשימה אפורה | 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
מצורפת לכל מחלקה שמוגדרת בהיקף המילוני של ההגדרה של מחלקה אחרת.
בכל כיתה שמופיעה בה ההערה הזו, צריך להופיע גם ההערה either EnclosingClass
or EnclosingMethod
.
שם | פורמט | תיאור |
---|---|---|
שם | מחרוזת | השם הפשוט שהוצהר במקור של המחלקה הזו (לא כולל קידומת של חבילה). אם הכיתה הזו אנונימית, השם הוא
null .
|
accessFlags | INT | דגלי הגישה שהוגדרו במקור עבור המחלקה (יכול להיות שהם שונים מהדגלים בפועל בגלל חוסר התאמה בין מודלי הביצוע של שפת המקור והמכונה הווירטואלית של היעד) |
dalvik.annotation.MemberClasses
מופיע בכיתות
MemberClasses
הערה מצורפת לכל מחלקה שמצהירה על מחלקות חברות. (מחלקת חברים היא מחלקה פנימית ישירה
שיש לה שם).
שם | פורמט | תיאור |
---|---|---|
ערך | Class[] | מערך של סוגי החברים |
dalvik.annotation.MethodParameters
מופיע בשיטות
הערה: ההערה הזו נוספה אחרי Android 7.1. המערכת תתעלם מהנוכחות שלה בגרסאות קודמות של Android.
ההערה MethodParameters
היא אופציונלית, ואפשר להשתמש בה כדי לספק מטא-נתונים של פרמטרים, כמו שמות פרמטרים ומשנים.
אפשר להשמיט את ההערה משיטה או מ-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
לא יכלול גם מידע על פרמטרים של מקבל הערות מסוג שלא קיימים בחתימה של השיטה בפועל.
שם | פורמט | תיאור |
---|---|---|
שמות | מחרוזת[] | השמות של הפרמטרים הפורמליים של השיטה המשויכת. המערך לא יכול להיות null, אבל הוא יכול להיות ריק אם אין פרמטרים רשמיים. ערך במערך צריך להיות null אם לפרמטר הרשמי עם האינדקס הזה אין שם. אם מחרוזות של שמות פרמטרים ריקות או מכילות את התווים '.', ';', '[' או '/', תופעל java.lang.reflect.MalformedParametersException בזמן הריצה.
|
accessFlags | int[] | דגלי הגישה של הפרמטרים הרשמיים של השיטה המשויכת. המערך לא יכול להיות null, אבל הוא יכול להיות ריק אם אין פרמטרים רשמיים. הערך הוא מסכת ביטים עם הערכים הבאים:
java.lang.reflect.MalformedParametersException .
|
dalvik.annotation.Signature
מופיע בכיתות, בשדות ובשיטות
Signature
הערה מצורפת לכל מחלקה, שדה או שיטה שמוגדרים במונחים של סוג מורכב יותר ממה שאפשר לייצג באמצעות type_id_item
. בפורמט .dex
לא מוגדר הפורמט של חתימות, אלא רק האפשרות לייצג חתימות ששפת המקור דורשת כדי ליישם בהצלחה את הסמנטיקה של השפה. לכן, בדרך כלל לא מתבצע ניתוח (או אימות) של חתימות בהטמעות של מכונות וירטואליות. החתימות פשוט מועברות לממשקי API ולכלים ברמה גבוהה יותר (כמו כלי ניפוי באגים). לכן, כל שימוש בחתימה צריך להיכתב כך שלא יניח הנחות לגבי קבלת חתימות תקפות בלבד, ויגן על עצמו מפני האפשרות של חתימה לא תקפה מבחינה תחבירית.
מחרוזות חתימה נוטות להכיל הרבה תוכן משוכפל, ולכן הערת Signature
מוגדרת כמערך של מחרוזות, שבהן רכיבים משוכפלים מתייחסים באופן טבעי לאותם נתונים בסיסיים, והחתימה נחשבת לשרשור של כל המחרוזות במערך. אין כללים לגבי האופן שבו מפרקים חתימה למחרוזות נפרדות. זה תלוי לחלוטין בכלים שיוצרים קובצי .dex
.
שם | פורמט | תיאור |
---|---|---|
ערך | מחרוזת[] | החתימה של המחלקה או של החבר הזה, כמערך של מחרוזות שצריך לשרשר יחד |
dalvik.annotation.Throws
מופיע בשיטות
Throws
הערה מצורפת לכל שיטה שמוצהר עליה שהיא מעלה סוג חריגה אחד או יותר.
שם | פורמט | תיאור |
---|---|---|
ערך | Class[] | מערך של סוגי חריגים שמוחזרים |