ระบบบิลด์ของแพลตฟอร์ม Android (Soong) จะเรียกใช้คอมไพเลอร์ R8 ในเป้าหมายที่คอมไพล์ไบต์โค้ด DEX ซึ่งรวมถึงแอป Android (android_app) การทดสอบ (android_test) และไลบรารี Java ที่ติดตั้งได้ซึ่งมี compile_dex: true (เช่น services.jar) เพื่อลดขนาด เพิ่มประสิทธิภาพ และลบโค้ดและทรัพยากรที่ไม่ได้ใช้ ในไลบรารีแบบคงที่ (android_library และ java_library แบบคงที่) Soong จะไม่เรียกใช้ R8 โดยตรง แต่จะใช้บล็อกพร็อพเพอร์ตี้ optimize เพื่อแนบและเผยแพร่กฎการเก็บรักษาสำหรับผู้ใช้ (export_proguard_flags_files: true) ไปยังเป้าหมาย DEX ที่ดาวน์สตรีมซึ่งลิงก์แบบคงที่
สำหรับวิศวกรแพลตฟอร์มที่สร้างอิมเมจระบบหรือแพ็กเกจของผู้ให้บริการ การกำจัด กฎการเก็บรักษาที่กว้างเกินไปจะช่วยให้ระบบมีสุขภาพดีขึ้นโดยตรง
- ร่องรอยพาร์ติชันของระบบที่เล็กลง: R8 จะนำคลาส เมธอด
และทรัพยากรที่ไม่ได้ใช้แล้วออกก่อนที่จะแพ็กเกจ APK และ JAR ลงใน
/system,/system_ext,/productและ/vendor - อาร์ติแฟกต์ที่คอมไพล์แล้วมีขนาดเล็กลง: เมธอด DEX น้อยลงหมายถึงไฟล์
.odexและ.vdexที่dex2oatสร้างขึ้นมีขนาดเล็กลงในระหว่างการคอมไพล์ขณะสร้างหรือในอุปกรณ์ - ลดแรงกดดันด้านหน่วยความจำรันไทม์: เนื่องจาก Android จะแมป
.odex,.vdexและตารางทรัพยากร APK ลงในหน่วยความจำของกระบวนการโดยใช้การเรียกmmapแบบดีมานด์เพจ ไบนารีขนาดเล็กจึงช่วยลดข้อผิดพลาดของหน้าเว็บที่สำคัญในระหว่างการเริ่มต้นแอป และลด โค้ดและหน่วยความจำของทรัพยากรที่อยู่ในกระบวนการต่างๆ ดูข้อมูลเพิ่มเติม เกี่ยวกับวิธีที่โค้ดแอปที่คอมไพล์แล้วส่งผลต่อหน่วยความจำของอุปกรณ์ได้ที่ โค้ดแอปคือหน่วยความจำ - การเพิ่มประสิทธิภาพทั้งโปรแกรมที่มีประสิทธิภาพมากขึ้น: ข้อจำกัดในการเก็บที่แคบลงช่วยให้ R8 สามารถแทรกเมธอด อินเทอร์เฟซแบบดีเวอร์ชวลไลซ์ และการเรียกแบบเวอร์ชวล ตัดฟิลด์ที่ไม่ได้ใช้ ออก และเผยแพร่ค่าคงที่ในคลาสต่างๆ
กำหนดค่าการเพิ่มประสิทธิภาพ R8 ใน Soong
ในไฟล์ Android.bp ให้กำหนดค่าการเพิ่มประสิทธิภาพ R8 โดยใช้พร็อพเพอร์ตี้ optimize
บล็อกในเป้าหมาย android_app และเป้าหมาย java_library ที่ติดตั้งได้ (หรือใน
โมดูล android_library และโมดูลแบบคงที่ java_library เพื่อส่งออกกฎการเก็บรักษาสำหรับผู้ใช้ทั่วไป):
android_app {
name: "MySystemApp",
srcs: ["src/**/*.java"],
optimize: {
obfuscate: true,
shrink_resources: true,
},
}
ตารางต่อไปนี้สรุปoptimizeพร็อพเพอร์ตี้ที่พบบ่อยที่สุดใน Soong
(กำหนดไว้ใน build/soong/java/dex.go)
| พร็อพเพอร์ตี้ | คำอธิบาย |
|---|---|
enabled |
ควบคุมว่าจะเรียกใช้ R8 ในเป้าหมายหรือไม่ ค่าเริ่มต้นคือ true
สําหรับเป้าหมาย android_app ทั้งหมด
|
shrink |
ควบคุมการกำจัดโค้ดที่ไม่จำเป็นเพื่อนำคลาส ฟิลด์ และ
เมธอดที่เข้าถึงไม่ได้ออก ค่าเริ่มต้นจะเป็น true สำหรับเป้าหมาย android_app (false สำหรับ java_library แบบสแตนด์อโลนและ
โมดูลทดสอบ ซึ่งส่งผ่าน -dontshrink เว้นแต่จะตั้งค่าอย่างชัดแจ้ง)
|
optimize |
ควบคุมการเพิ่มประสิทธิภาพไบต์โค้ด เช่น การแทรกเมธอด การผสานคลาส
การส่งต่อค่าคงที่ และการนำกิ่งที่ตายแล้วออก ค่าเริ่มต้นคือ
true สำหรับเป้าหมาย android_app (ควบคุมโดย
แฟล็กบิลด์ที่เผยแพร่ RELEASE_R8_OPTIMIZE_BY_DEFAULT)
|
obfuscate |
ควบคุมการย่อขนาดและการเปลี่ยนชื่อตัวระบุ ค่าเริ่มต้นคือ
false เพื่อความเข้ากันได้ในอดีต แต่ให้ตั้งค่าเป็น
true ทุกครั้งที่เป็นไปได้เพื่อลดขนาด DEX และปลดล็อก
การเพิ่มประสิทธิภาพที่ลึกซึ้งยิ่งขึ้น (ดู
เปิดใช้การปรับให้ยากต่อการอ่านทุกครั้งที่เป็นไปได้)
|
shrink_resources |
นำทรัพยากรที่ไม่ได้ใช้ (res/ รายการ) ออกจาก APK ที่แพ็กเกจแล้ว
หลังจากลดขนาดโค้ด ค่าเริ่มต้นคือ false
|
optimized_shrink_resources |
เรียกใช้ไปป์ไลน์เครื่องมือลดขนาดโค้ดและทรัพยากร R8 ที่ผสานรวมเพื่อให้ R8 ติดตาม
การอ้างอิงโค้ดและทรัพยากรพร้อมกันในรอบเดียว เมื่อตั้งค่า shrink_resources: true ค่าเริ่มต้นจะเป็น RELEASE_USE_OPTIMIZED_RESOURCE_SHRINKING_BY_DEFAULT
(true ในแพลตฟอร์มมาตรฐาน)
|
proguard_flags_files |
แสดงรายการไฟล์ .flags หรือ .pro เฉพาะโมดูล
ที่มีกฎการเก็บรักษาที่กำหนดเอง หลีกเลี่ยงการเพิ่มไฟล์ที่กำหนดเองเมื่อคำอธิบายประกอบมาตรฐาน
หรือค่าเริ่มต้นเพียงพอ
|
export_proguard_flags_files |
เผยแพร่ proguard_flags_files ของไลบรารีนี้ไปยัง
โมดูลดาวน์สตรีมที่ขึ้นอยู่กับไลบรารีนี้แบบคงที่
|
trace_references_from |
ระบุเป้าหมายคู่หูของไลบรารี Java ที่ bytecode อ้างอิงถึง เป้าหมายนี้ R8 จะติดตามและเก็บรักษาโดยอัตโนมัติ |
เปิดใช้การปรับให้ยากต่อการอ่าน (Obfuscation) ทุกที่ที่เป็นไปได้
ใน Soong obfuscate จะเป็นค่าเริ่มต้นของ false เพื่อให้เข้ากันได้กับเวอร์ชันก่อนหน้า แต่คุณ
ควรตั้งค่า obfuscate: true อย่างชัดเจนใน android_app และเป้าหมาย DEX แบบสแตนด์อโลน
ทุกครั้งที่เป็นไปได้
- ร่องรอยของ DEX และ
.vdexที่เล็กลง: การเปลี่ยนชื่อแพ็กเกจ คลาส ฟิลด์ และเมธอดเป็นตัวระบุแบบย่อ (a,b) จะลดขนาดกลุ่มสตริง DEX (string_idsและstring_data_item) และตัวอธิบายประเภท เนื่องจาก Android จะแมปไฟล์.vdexและ.odexลงในหน่วยความจำของกระบวนการ ตารางสัญลักษณ์ที่มีขนาดเล็กลง จึงช่วยลดทั้งขนาดพาร์ติชันของระบบและหน่วยความจำที่ใช้ขณะรันไทม์ได้โดยตรง - การเพิ่มประสิทธิภาพทั้งโปรแกรมที่ละเอียดยิ่งขึ้น: การอนุญาตให้ R8 เปลี่ยนชื่อตัวระบุ จะช่วยให้ผสานคลาส ลดระดับแพ็กเกจ และขจัดคลาสสังเคราะห์ที่ซ้ำกัน ในแพ็กเกจที่ R8 ต้องข้ามเพื่อหลีกเลี่ยงการตั้งชื่อที่ซ้ำกัน
- การสร้างสัญลักษณ์ของ Stack Trace ทั้งหมด: การเปิดใช้การปกปิดใน Soong ไม่ได้
ลดความสามารถในการแก้ไขข้อบกพร่อง สำหรับเป้าหมายที่คอมไพล์ด้วย R8 ทุกรายการ Soong จะสร้าง
proguard_dictionaryไฟล์แมปในไดเรกทอรีกลางของโมดูล รวมพจนานุกรมโมดูลทั้งหมดไว้ในอาร์ติแฟกต์proguard-dict.zipของบิลด์ ฝังแฮชแมป (--map-id-template) ไว้ในส่วนหัว DEX และเขียนแอตทริบิวต์ของคลาสSourceFile(--source-file-template) ใหม่เพื่อให้retraceสามารถสร้างสัญลักษณ์ของ Stack Trace โดยอัตโนมัติ
เก็บ obfuscate: false (หรือคงชื่อ API สาธารณะไว้อย่างชัดเจน) ไว้สำหรับกรณีต่อไปนี้เท่านั้น
- ไลบรารีที่แชร์ใน bootclasspath หรือ
system_serverclasspath: โมดูล (java_libraryหรือjava_sdk_library) ที่แสดง API ภายนอก จะเชื่อมโยงแบบไดนามิกโดยโมดูลอื่นๆ ในรันไทม์ (เช่น เป้าหมายframework.jar,services.jarหรือ<uses-library>) ต้อง เก็บobfuscate: falseไว้หรือคงพื้นผิว API อย่างชัดเจนโดยใช้ กฎ@KeepForApiหรือ-keep(พร้อมกับprotect_api_surface: trueสำหรับเป้าหมาย bootclasspath) เพื่อให้ผู้เรียกที่คอมไพล์ เทียบกับ Stub สามารถแก้ไขชื่อคลาสและชื่อสมาชิกในรันไทม์ได้
ก่อนเปิดใช้ obfuscate: true ในแอปพลิเคชัน ให้ตรวจสอบข้อกำหนดเบื้องต้นในการย้ายข้อมูลต่อไปนี้
- ทรัพยากร Dependency ของ APK ทดสอบภายนอก: หาก
android_testชุด APKinstrumentation_for: "MyApp"ภายนอกเรียกใช้คลาสหรือเมธอดภายในของMyAppโดยตรง การเปลี่ยนชื่อสัญลักษณ์เหล่านั้นจะทำให้เกิดNoSuchMethodErrorหรือNoClassDefFoundErrorในรันไทม์ของการทดสอบ ควรจัดโครงสร้างการทดสอบเป็น APK ที่ลิงก์แบบคงที่ซึ่งมีเครื่องมือในตัวMyApp.implใส่คำอธิบายประกอบฮุกทดสอบ ด้วย@VisibleForTestingหรือกำหนดค่าtrace_references_from(ดู ขั้นตอนที่ 2: ย้ายข้อมูลกฎการเก็บรักษาที่ขับเคลื่อนด้วยการทดสอบ) เพื่อให้ ระบบเก็บรักษาสัญลักษณ์ภายในที่การทดสอบต้องการไว้ในขณะที่ทำให้ส่วนอื่นๆ ของ แอปสับสน - การสะท้อนตามสตริงและ JNI: หากโมดูลค้นหาคลาส เมธอด หรือฟิลด์ตามชื่อสตริงตัวอักษร (
Class.forName,getDeclaredMethodหรือ JNIFindClassและGetMethodID) โดยไม่มีกฎหรือคำอธิบายประกอบ keep การปกปิดจะเปลี่ยนชื่อเป้าหมายเหล่านั้นและทำให้การค้นหาที่รันไทม์ใช้งานไม่ได้ (โปรดทราบว่าการสะท้อนที่ไม่มีคำอธิบายประกอบจะล้มเหลวภายใต้shrink: trueและoptimize: trueด้วย) ใส่คำอธิบายประกอบให้กับจุดแรกเข้าเหล่านั้นด้วยคำแนะนำในการใส่คำอธิบายประกอบ (@UsesReflection,@UsedByReflectionหรือ@UsedByNative) เพื่อให้ R8 เก็บชื่อไว้และปิดบังส่วนที่เหลือของโมดูล
ปฏิบัติตามหลักการไม่ใช้ฟีเจอร์ที่กำหนดเอง
โมดูลแพลตฟอร์ม Android ที่ดีที่สุดจะไม่มีไฟล์ proguard.flags หรือ keep.xml
ที่กำหนดเอง ในบิลด์แพลตฟอร์ม Android กฎการเก็บรักษาที่กำหนดเองส่วนใหญ่
ซ้ำซ้อน
- พื้นฐานของแพลตฟอร์มและ AAPT2: จุดแรกเข้าส่วนใหญ่จะยังคงอยู่
โดยอัตโนมัติตามพื้นฐานของแพลตฟอร์มทั่วโลก (เช่น
@Keep, JNInativeและ@VisibleForTesting) หรือสร้างโดย AAPT2 จากAndroidManifest.xmlและทรัพยากรเลย์เอาต์ (ดู ทำความเข้าใจกฎการคงค่าเริ่มต้นของแพลตฟอร์ม) - ทางเลือกที่กำหนดเป้าหมาย: ในกรณีที่ต้องรักษาจุดแรกเข้าไว้ ให้ใช้คำอธิบายประกอบในไฟล์ประกาศ (
keepanno,@VisibleForTesting), กฎของคลังที่ส่งออก (export_proguard_flags_files: true) หรือการลิงก์การทดสอบแบบคงที่แทนไฟล์.flagsที่แยกออกมา (ดูตรวจสอบและย้ายข้อมูลกฎการเก็บรักษาที่มีอยู่)
ก่อนเพิ่มหรือเก็บไฟล์ proguard.flags หรือ keep.xml ที่กำหนดเองไว้ ให้ตรวจสอบว่ากฎดังกล่าวได้รับการจัดการโดยค่าพื้นฐานเริ่มต้นอยู่แล้วหรือสามารถย้ายข้อมูลไปยัง
คำอธิบายประกอบโค้ดได้หรือไม่
ทำความเข้าใจกฎการเก็บรักษาเริ่มต้นของแพลตฟอร์ม
Soong จะส่งกฎพื้นฐานส่วนกลางต่อไปนี้ไปยังการเรียกใช้ R8 ทุกครั้งในเป้าหมายการคอมไพล์ DEX (โมดูล android_app, android_test และ java_library ที่ติดตั้งได้) ซึ่งกำหนดค่าไว้ใน build/soong/java/dex.go โดยอัตโนมัติ
build/make/core/proguard.flags: เก็บรักษาคลาสและสมาชิก ที่ใส่คำอธิบายประกอบด้วย@com.android.internal.annotations.VisibleForTestingใน ทุกแพ็กเกจ และด้วย@VisibleForTesting(androidx.annotation.VisibleForTestingหรือcom.google.common.annotations.VisibleForTesting) ภายในแพ็กเกจandroid.**,com.android.**และcom.google.android.**รวมถึงยังคง@TestApi,@Keep(androidx.annotation,android.support.annotation,com.android.internal.annotations),@KeepForWeakReference,@WeaklyReferencedCallbackและ@dalvik.annotation.optimization.**build/make/core/proguard_basic_keeps.flags: เก็บรักษาแอตทริบิวต์SourceFileสำหรับ Stack Trace, คำอธิบายประกอบการมองเห็นรันไทม์ (RuntimeVisible*Annotations), แอตทริบิวต์ExceptionsและAnnotationDefault, เมธอดnative, สมาชิกSerializable, เมธอด@JavascriptInterface, ตัวสร้างThrowable(String), ฟิลด์Parcelable$CREATORและ ฟิลด์MessageLiteของ Protobufbuild/make/core/proguard/kotlin.flags: ปิดเสียงคำเตือนที่ไม่เป็นอันตรายสำหรับ Meta-Annotation ของ Kotlin บางรายการ (kotlin.Metadataและkotlin.annotation.{AnnotationRetention,AnnotationTarget,Retention,Target}) และนำ AnnotationDebugMetadataของ Kotlin ออกในบิลด์ที่เผยแพร่build/make/core/proguard/checknotnull.flags: แทนที่การเรียกใช้ฟังก์ชันช่วยตรวจสอบค่า Null ทั่วไป (com.google.common.base.Preconditions.checkNotNullและdagger.internal.Preconditions.checkNotNull*) ด้วยการตรวจสอบค่า Null ในไบต์โค้ดแบบย่อ ไฟล์นี้จงใจละเว้นObjects.requireNonNullเพื่อรักษา ข้อความข้อยกเว้นที่ชัดเจนในขอบเขต API ของเฟรมเวิร์กbuild/make/core/proguard/enumvalues.flags: เก็บเมธอดvaluesและvalueOfไว้ในประเภทenumเว้นแต่จะปิดใช้โดยการกำหนดค่าบิลด์- กฎที่ AAPT2 สร้างขึ้นโดยอัตโนมัติ: AAPT2 จะตรวจสอบไฟล์
AndroidManifest.xmlที่ผสานรวมแล้ว XML ของเลย์เอาต์ และ XML ของค่ากำหนดเพื่อสร้างกฎการคงไว้ที่แน่นอนสำหรับActivity,Service,BroadcastReceiver,ContentProviderBackupAgent,Application, คลาสย่อยViewที่กำหนดเอง, คลาสย่อยPreferenceและเมธอดandroid:onClickของ XML ที่ลงทะเบียนทั้งหมด
ตรวจสอบและย้ายข้อมูลกฎการเก็บรักษาที่มีอยู่
เมื่อตรวจสอบไฟล์ proguard.flags หรือ keep.xml ที่มีอยู่แล้วในที่เก็บของแพลตฟอร์ม
ให้ประเมินแต่ละกฎตามลำดับเทียบกับลำดับชั้น 4 ขั้นตอนต่อไปนี้
ขั้นตอนที่ 1: ลบกฎที่ซ้ำซ้อนหรือล้าสมัย
ลบกฎที่ครอบคลุมโดยค่าพื้นฐานส่วนกลาง, กฎไฟล์ Manifest และเลย์เอาต์ของ AAPT2 หรือค่าเริ่มต้นของ R8 รวมถึงกฎที่อ้างอิงคลาสหรือแพ็กเกจที่ไม่มีอยู่อีกต่อไป
หากกฎทั้งหมดในไฟล์ .flags ซ้ำซ้อนกัน ให้ลบไฟล์และนำ proguard_flags_files ออกจาก Android.bp หากoptimizeที่เหลืออยู่
ระบุการตั้งค่าเริ่มต้นซ้ำ ให้นำบล็อกที่ซ้ำกันออกและจัดรูปแบบไฟล์บิลด์
ด้วย bpfmt -w Android.bp เมื่อล้างข้อมูลแพ็กเกจ ให้ตรวจสอบว่าโมดูลเสริมในไดเรกทอรีย่อย (เช่น ตัวแปรเป้าหมาย Kotlin) อ้างอิงไฟล์แฟล็กเดียวกันหรือไม่ แล้วอัปเดตพร้อมกัน
ขั้นตอนที่ 2: ย้ายข้อมูลกฎการเก็บรักษาที่ขับเคลื่อนด้วยการทดสอบ
ย้ายกฎการเก็บรักษาที่ขับเคลื่อนด้วยการทดสอบออกจากไฟล์การผลิตที่กำหนดเอง .flags โดยใช้รูปแบบใดรูปแบบหนึ่งต่อไปนี้
ลิงก์ไลบรารีการติดตั้งใช้งานในการทดสอบ (
static_libs): เมื่อandroid_testใช้รายละเอียดการติดตั้งใช้งานภายในหรือแบบแพ็กเกจส่วนตัว ของแอป สถาปัตยกรรมแพลตฟอร์มที่แนะนำคือการวางไฟล์แหล่งที่มาของแอป ในandroid_library(MyApp.impl) และลิงก์แบบคงที่MyApp.implทั้งในMyAppและMyAppTestsandroid_library { name: "MyApp.impl", srcs: ["src/**/*.java"], manifest: "AndroidManifest.xml", } android_app { name: "MyApp", static_libs: ["MyApp.impl"], optimize: { obfuscate: true, shrink_resources: true, }, } android_test { name: "MyAppTests", srcs: ["tests/**/*.java"], static_libs: ["MyApp.impl"], }รูปแบบ 3 โมดูลนี้ช่วยให้
MyAppTestsทำงานเป็นการทดสอบที่สร้างเครื่องมือด้วยตนเอง โดยมีสิทธิ์เข้าถึงคลาสภายในอย่างเต็มรูปแบบ ช่วยให้MyAppเปิดใช้obfuscate: trueได้อย่างอิสระโดยไม่ทำให้การทดสอบหยุดทำงาน หลีกเลี่ยงการจัดส่งจุดแรกเข้าสำหรับการทดสอบเท่านั้นใน APK ที่ใช้งานจริง และไม่ต้องสร้างMyAppใหม่เมื่อมีการเปลี่ยนแปลงโค้ดทดสอบใส่คำอธิบายประกอบให้กับ Hook การทดสอบด้วย
@VisibleForTesting: หากการทดสอบภายนอก APK เรียกใช้เมธอดหรือตัวสร้างภายในจำนวนเล็กน้อยในandroid_appเป้าหมาย และการปรับโครงสร้างเป็นไลบรารี.implเป็นไปไม่ได้ ให้ใส่คำอธิบายประกอบให้กับประกาศเหล่านั้นด้วย@VisibleForTestingbuild/make/core/proguard.flagsพื้นฐาน@VisibleForTestingทั่วโลกจะเก็บandroid.**รายการในแพ็กเกจcom.android.**และcom.google.android.**โดยอัตโนมัติโดยไม่ต้องใช้ไฟล์.flagsที่กำหนดเอง (สำหรับโมดูลของผู้ให้บริการภายนอกเนมสเปซเหล่านี้ ให้ใช้@UsedByReflectionหรือกฎของไลบรารีที่ส่งออก)ใช้
trace_references_fromข้ามขอบเขตไลบรารีของแพลตฟอร์ม: เมื่อการทดสอบลิงก์การติดตั้งใช้งานเป้าหมายแบบคงที่ไม่ได้ (เช่น การทดสอบที่ใช้บริการเซิร์ฟเวอร์ระบบหรือ JAR ของแพลตฟอร์ม เช่นframework-connectivity) ให้กำหนดค่าtrace_references_fromในโมดูลเป้าหมายที่ชี้ไปยังโมดูลคู่ของไลบรารี Java ที่มีแหล่งที่มาของการทดสอบ R8 จะติดตามและเก็บรักษาคลาสและสมาชิกทั้งหมดที่อ้างอิงโดย ไบต์โค้ดคู่
ขั้นตอนที่ 3: ส่งออกกฎจากคลังที่เป็นเจ้าของ
หาก java_library หรือ android_library ที่ใช้ร่วมกันต้องมีกฎการเก็บรักษาสำหรับการสะท้อนภายในหรือการเรียกกลับ JNI ของตัวเอง ให้กำหนดกฎในเป้าหมายไลบรารีและตั้งค่า export_proguard_flags_files: true ดังนี้
java_library {
name: "my-shared-library",
srcs: ["src/**/*.java"],
optimize: {
proguard_flags_files: ["proguard.flags"],
export_proguard_flags_files: true,
},
}
android_appและเป้าหมายไลบรารีทั้งหมดที่ลิงก์แบบคงที่
my-shared-libraryจะรับค่ากฎเหล่านั้นโดยอัตโนมัติ ดังนั้นแอปดาวน์สตรีมจึงไม่
จำเป็นต้องทำซ้ำ เมื่อโมดูลหลายรายการในไดเรกทอรีต่างๆ ต้องแชร์ชุดกฎที่ไม่ได้เชื่อมโยงกับไลบรารีโค้ดเดียว ให้เผยแพร่ไฟล์ .flags
ผ่าน filegroup ที่ชัดเจนใน Android.bp เพื่อให้โมดูลอ้างอิง :my-shared-flags ได้อย่างชัดเจนในขอบเขตของแพ็กเกจ ดูคำแนะนำทั่วไปเกี่ยวกับ
การเขียนกฎการเก็บรักษาของผู้ใช้ไลบรารีโดยไม่จำกัดการเพิ่มประสิทธิภาพแอปปลายทาง
ได้ที่การเพิ่มประสิทธิภาพสำหรับผู้เขียนไลบรารี
ขั้นตอนที่ 4: ใส่คำอธิบายประกอบการประกาศในซอร์สโค้ด
เมื่อเข้าถึงคลาส เมธอด ตัวสร้าง หรือฟิลด์ผ่านการสะท้อนหรือ JNI และไม่ได้ครอบคลุมโดย AAPT2 หรือค่าพื้นฐานส่วนกลาง ให้แทนที่กฎที่แยกออกมา-keep
ในไฟล์ .flags ด้วยคำอธิบายประกอบของแหล่งที่มาจาก
คำแนะนำเกี่ยวกับคำอธิบายประกอบ Keep (ดูkeepannoเอกสารอ้างอิง Javadoc)
@UsesReflection: ใช้คำอธิบายประกอบนี้เมื่อคุณควบคุมโค้ดที่ทำการรีเฟลกชัน วางไว้ที่การเรียกการสะท้อน เพื่อประกาศว่ามีการเข้าถึงคลาส เมธอด หรือฟิลด์เป้าหมายใด แบบไดนามิก เนื่องจาก@UsesReflectionจะเข้ารหัสเงื่อนไขเบื้องต้นโดยอัตโนมัติ ว่าเว็บไซต์ที่เรียกใช้ที่มีคำอธิบายประกอบสามารถเข้าถึงได้ R8 จึงตัดทั้งผู้เรียก และเป้าหมายการสะท้อนหากไม่มีการใช้เว็บไซต์ที่เรียกใช้@UsedByReflection: วางไว้ในคลาส เมธอด ฟิลด์ หรือตัวสร้างที่โค้ดหรือไลบรารีภายนอกสร้างอินสแตนซ์หรือเรียกใช้แบบรีเฟลกทีฟ เช่น คลาสที่โหลดด้วยClass.forNameจากคีย์BundleหรือSettingsหรือคลาสปลั๊กอินที่โหลดใน ClassLoader แบบไดนามิก ระบุkind(เช่นKeepItemKind.CLASS_AND_METHODS)preconditions(@KeepCondition) และข้อจำกัดของพารามิเตอร์เพื่อให้ R8 เก็บ เฉพาะสัญญาการสะท้อนที่แน่นอน และยังคงเพิ่มประสิทธิภาพหรือตัด สมาชิกที่ไม่ได้ใช้ของคลาสออกได้ อย่าเพิ่ม@UsedByReflectionลงในคอมโพเนนต์ที่ลงทะเบียนในไฟล์ Manifest เช่นJobServiceหรือBroadcastReceiverเนื่องจาก AAPT2 จะเก็บคอมโพเนนต์เหล่านี้ไว้แล้ว@UsedByNative: วางไว้ในเมธอดหรือฟิลด์ที่เข้าถึงจากโค้ด JNI ของ C หรือ C++ โดยใช้GetMethodID,GetStaticMethodIDหรือGetFieldID@KeepForApi: วางไว้ในคลาสหรือสมาชิก API ของไลบรารีที่ต้องคงไว้เหมือนเดิมเมื่อมีการลดขนาดไลบรารีเองก่อนการเผยแพร่@Keep(androidx.annotation.Keep): ใช้เป็นข้อมูลสำรอง เมื่อkeepannoใช้ไม่ได้ การใช้@Keepกับคลาสจะเก็บคลาสและสมาชิกทั้งหมดไว้โดยไม่มีเงื่อนไข การใช้@Keepกับเมธอดหรือฟิลด์จะทำหน้าที่เป็นจุดแรกเข้าแบบไม่มีเงื่อนไขซึ่งจะเก็บสมาชิกและคลาสที่มีสมาชิกนั้นไว้แม้ว่าจะไม่มีการสร้างอินสแตนซ์ของคลาสเลยก็ตาม ในขณะที่keepannoแสดงถึงการเข้าถึงแบบมีเงื่อนไข
วิธีใช้คำอธิบายประกอบ keepanno ของ R8 ในโมดูล Soong
วิธีเพิ่ม
"keepanno-annotations"ไปยังlibsในAndroid.bplibs: [ "keepanno-annotations", ],นำเข้า
com.android.tools.r8.keepanno.annotations.*และใส่คำอธิบายประกอบ การประกาศหรือตำแหน่งที่เรียกในซอร์สโค้ด Java หรือ Kotlinimport com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; public final class CustomPluginController { @UsedByReflection( description = "Instantiated via Class.forName from plugin config", kind = KeepItemKind.CLASS_AND_METHODS) public CustomPluginController(Context context) { // ... } }R8 จะแปล
keepannoคำอธิบายประกอบเป็นรูปแบบกฎการเก็บรักษาภายในโดยตรง และลบคำอธิบายประกอบออกจากเอาต์พุต DEX สุดท้าย โดยไม่เพิ่ม ค่าใช้จ่ายไบต์โค้ดรันไทม์
หลีกเลี่ยงข้อผิดพลาดที่พบบ่อย
ส่วนต่อไปนี้จะอธิบายkeep.xml
ข้อผิดพลาดที่พบบ่อยproguard.flagsในโค้ดแพลตฟอร์มและวิธีแก้ไข
กฎการเก็บรักษาคอมโพเนนต์แบบกว้าง
# Don't do this:
-keep class * extends android.app.Activity
-keep class * extends android.app.Service
-keep class * extends android.content.BroadcastReceiver
- เหตุใดจึงส่งผลเสียต่อประสิทธิภาพ: กฎนี้ซ้ำซ้อนกับ AAPT2 โดยสมบูรณ์
เนื่องจากใช้ไวลด์การ์ดโดยไม่ได้ตรวจสอบว่าคอมโพเนนต์ลงทะเบียนใน
AndroidManifest.xmlที่ผสานขั้นสุดท้ายหรือไม่ จึงบังคับให้ R8 เก็บActivity,Serviceหรือคลาสย่อยBroadcastReceiverทุกรายการที่พบในคลาสพาธ รวมถึงคอมโพเนนต์ไลบรารีที่ไม่ได้ใช้และกิจกรรมการแก้ไขข้อบกพร่องที่ปิดใช้ - การแก้ไขที่แนะนำ: ลบกฎ AAPT2 จะตรวจสอบไฟล์ Manifest ที่ผสานแล้วและ
สร้าง
-keepที่แน่นอนสำหรับคอมโพเนนต์ที่ลงทะเบียน
กฎการเก็บตัวแฮนเดิลการคลิก XML แบบกว้าง
# Don't do this:
-keepclassmembers class * {
public void *(android.view.View);
}
- เหตุใดจึงทำให้ประสิทธิภาพลดลง: การเก็บรักษาวิธีการ
public void *(View)ทั้งหมด ในทุกคลาสของโมดูลจะทำให้ R8 ไม่สามารถลบหรือแทรกวิธีการ ที่รับพารามิเตอร์Viewรายการเดียว - การแก้ไขที่แนะนำ: ลบกฎ AAPT2 จะสแกนไฟล์ XML ของเลย์เอาต์และ
สร้างกฎการเก็บเป้าหมายสำหรับเมธอดที่อ้างอิงโดยแอตทริบิวต์
android:onClick
กฎการเก็บรักษา Getter และ Setter ของ Broad View
# Don't do this:
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
public *** get*();
}
- เหตุผลที่ทำให้ประสิทธิภาพลดลง: กฎนี้บังคับให้ R8 เก็บตัวรับและตัวตั้งค่าทุกรายการในทุกคลาสย่อย
Viewในแอปและไลบรารีที่ลิงก์ทั้งหมด (รวมถึงไลบรารี AndroidX และ Material) ซึ่งบล็อกการนำเมธอดที่ไม่ได้ใช้ออก และการแทรกโค้ดในโค้ด UI - การแก้ไขที่แนะนำ: ลบกฎ AAPT2 จะเก็บรักษาตัวสร้าง
สำหรับคลาส
Viewที่กำหนดเองซึ่งขยายจากไฟล์ XML ของเลย์เอาต์อยู่แล้ว หากโค้ดเคลื่อนไหวพร็อพเพอร์ตี้ของ View โดยใช้ชื่อสตริงแบบรีเฟลกทีฟ เช่นObjectAnimator.ofFloat(view, "translationZ", ...)ให้แทนที่ชื่อสตริง ด้วยการอ้างอิงพร็อพเพอร์ตี้ที่พิมพ์ (View.TRANSLATION_Zหรือการใช้งานFloatPropertyหรือIntPropertyที่กำหนดเอง) เพื่อหลีกเลี่ยงการรีเฟลกชัน โดยสิ้นเชิง หากหลีกเลี่ยงการเข้าถึงพร็อพเพอร์ตี้แบบรีเฟลกชันไม่ได้ ให้ใส่คำอธิบายประกอบใน Getter หรือ Setter ที่เฉพาะเจาะจงด้วย@UsedByReflection
การปิดใช้การเพิ่มประสิทธิภาพหรือการปกปิดทั้งหมด
# Don't do this in proguard.flags:
-dontoptimize
-dontshrink
-dontobfuscate
- เหตุใดจึงส่งผลเสียต่อประสิทธิภาพ: การวาง
-dontoptimizeหรือ-dontshrinkภายในไฟล์.flagsจะลบล้างการตั้งค่าAndroid.bpของโมดูลโดยไม่มีการแจ้งเตือน และปิดใช้การเพิ่มประสิทธิภาพทั่วทั้งเป้าหมาย ที่แย่กว่านั้นคือ หากไลบรารีส่งออกไฟล์.flagsที่มี-dontoptimizeระบบจะปิดใช้การเพิ่มประสิทธิภาพ R8 สำหรับandroid_appทุกรายการที่ลิงก์ไลบรารี - วิธีแก้ไขที่แนะนำ: นำ
-dontoptimize,-dontshrinkและ-dontobfuscateออกจากไฟล์.flagsควบคุมลักษณะการเพิ่มประสิทธิภาพ อย่างชัดเจนในAndroid.bpโดยใช้บล็อกoptimize(shrink,optimize,obfuscate) ในเป้าหมายใบ
การแจ้งการวินิจฉัยในกฎที่คอมมิต
# Don't do this in proguard.flags:
-verbose
-printmapping proguard.map
-printusage usage.txt
-printconfiguration config.txt
- เหตุใดจึงทำให้บิลด์ช้าลง: แฟล็กการวินิจฉัยจะทำให้บันทึกบิลด์เต็มไปด้วยข้อความหรือพยายามเขียนไฟล์เอาต์พุตไปยังเส้นทางในเครื่องระหว่างการสร้าง Soong ในแซนด์บ็อกซ์
- วิธีแก้ไขที่แนะนำ: ลบ Flag เหล่านี้ออกจากไฟล์
.flagsที่คอมมิตแล้ว Soong จะเขียนเอาต์พุตการแมปและการใช้งาน R8 โดยอัตโนมัติ เช่นproguard_dictionaryและproguard_usage.zipไปยังไดเรกทอรีกลางของโมดูล ภายใต้out/soong/.intermediates/
กฎการเก็บรักษาเวอร์ชันที่ใช้งานจริงสำหรับโค้ดทดสอบ
- เหตุผลที่ทำให้ประสิทธิภาพลดลง: การเพิ่มกฎ
-keepที่กำหนดเองเพื่อการทดสอบ การเข้าถึงเพียงอย่างเดียวจะบังคับให้โค้ดนั้นยังคงไม่ได้รับการปกปิดและยังคงอยู่ในบิลด์เวอร์ชันที่ใช้งานจริง แม้ว่าการใส่คำอธิบายประกอบเมธอดด้วย@VisibleForTestingหรือการกำหนดค่าtrace_references_fromจะช่วยให้ไม่ต้องดูแลกฎ-keepด้วยตนเอง แต่สัญลักษณ์เหล่านั้นจะยังคงอยู่ในไบนารีที่ใช้งานจริง - การแก้ไขที่แนะนำ: หากต้องการให้จุดแรกเข้าสำหรับการทดสอบเท่านั้นอยู่นอก APK ของเวอร์ชันที่ใช้งานจริงอย่างสมบูรณ์ ให้จัดโครงสร้างแอปพลิเคชันเป็นไลบรารี
.implแล้วลิงก์เข้ากับ APK ของการทดสอบที่ใช้เครื่องมือด้วยตนเองโดยใช้static_libsตามที่อธิบายไว้ในขั้นตอนที่ 2: ย้ายข้อมูลกฎการเก็บรักษาที่ขับเคลื่อนด้วยการทดสอบ
ไวลด์การ์ดทรัพยากรแบบครอบคลุมใน keep.xml
<!-- Don't do this in res/raw/keep.xml: -->
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@raw/*,@drawable/*,@string/*" />
- เหตุใดจึงส่งผลเสียต่อประสิทธิภาพ: อักขระไวด์การ์ดแบบครอบคลุมจะเก็บทรัพยากรทุกรายการใน
ประเภทการจับคู่ทั่วทั้งโมดูลและการอ้างอิง ซึ่งจะทำให้การลดขนาดทรัพยากร (
shrink_resources: true) ไม่ได้ผล และทำให้ตาราง APK และตารางที่แมปresources.arscมีขนาดใหญ่ขึ้น - การแก้ไขที่แนะนำ
- ใช้การอ้างอิงทรัพยากรแบบคงที่มากกว่า
keep.xml: หลีกเลี่ยงการใช้วิธีResources.getIdentifierเพื่อค้นหาชุดทรัพยากรที่จำกัด แบบไดนามิก เช่น สตริงการทดสอบที่มีหมายเลขหรือ Drawable ที่มีธีม แต่ให้ใช้คำสั่งswitchในเวลาคอมไพล์หรือแมปค่าคงที่ staticR.id,R.stringหรือR.drawableแทน การอ้างอิงแบบคงที่ช่วยให้ R8 และ AAPT2 ติดตามทรัพยากรที่ใช้งานอยู่ได้อย่างแม่นยำ ลดค่าใช้จ่ายในการค้นหาสตริงรันไทม์ และไม่จำเป็นต้องใช้keep.xmlอีกต่อไป - ระบุชื่อทรัพยากรที่เฉพาะเจาะจง: หากต้องมีการค้นหาแบบไดนามิก เช่น
โดยโปรแกรมอ่านใบอนุญาตของบุคคลที่สาม ให้ระบุตัวระบุทรัพยากรที่แน่นอนใน
tools:keep(เช่นtools:keep="@raw/third_party_licenses") - ลบไฟล์
keep.xmlที่ซ้ำกัน: หากมีการอ้างอิงทรัพยากรที่แสดงในโค้ด (R.raw.foo) หรือ XML (@raw/foo) แบบคงที่อยู่แล้ว เครื่องมือลดขนาดจะเก็บทรัพยากรเหล่านั้นไว้โดยอัตโนมัติ คุณจึงลบres/raw/keep.xmlได้
- ใช้การอ้างอิงทรัพยากรแบบคงที่มากกว่า
ยืนยันและตรวจสอบการเปลี่ยนแปลงกฎ
เมื่อใดก็ตามที่คุณนำกฎการเก็บรักษาออกหรือจำกัดกฎการเก็บรักษาใน proguard.flags หรือ keep.xml
ให้ตรวจสอบว่าโมดูลสร้างได้อย่างถูกต้อง ผ่านการทดสอบหน่วยและการทดสอบเครื่องมือ
และยังคงมีจุดแรกเข้าที่จำเป็นทั้งหมด
สร้างและทดสอบโมดูล
สร้างโมดูลอย่างสะอาดเพื่อยืนยันว่า R8 และ AAPT2 เสร็จสมบูรณ์โดยไม่มี คำเตือนเกี่ยวกับการอ้างอิงที่ขาดหายไป
m <MODULE_NAME>เรียกใช้การทดสอบหน่วยและการทดสอบการวัดคุมสำหรับโมดูลโดยใช้
atestดังนี้atest <TEST_MODULE_NAME>สำหรับแอปของระบบ บริการที่มีสิทธิ์ หรือโมดูลที่ขึ้นอยู่กับฮาร์ดแวร์ ให้เรียกใช้ การทดสอบเครื่องมือและการทดสอบ UI ในอุปกรณ์จริงเป้าหมายหรือในห้อง ทดสอบอุปกรณ์เพื่อใช้เส้นทางการสะท้อนรันไทม์ การเชื่อมโยง IPC และการขยายทรัพยากร
ตรวจสอบความแตกต่างของ DEX และทรัพยากร
เปรียบเทียบ APK หรือ JAR ที่คอมไพล์แล้วก่อนและหลังการเปลี่ยนแปลงกฎเพื่อยืนยันว่า R8 นำโค้ดและทรัพยากรที่ไม่ได้ใช้แล้วออกโดยไม่นำจุดแรกเข้าที่คาดไว้
ใช้
apkanalyzerหรือdexdumpเพื่อตรวจสอบคลาส เมธอด และฟิลด์ที่เก็บไว้ในไฟล์ APK หรือ DEX เอาต์พุตapkanalyzer dex packages $OUT/system/priv-app/<APP_NAME>/<APP_NAME>.apkเมื่อแก้ไข
keep.xmlหรือเปิดใช้shrink_resourcesให้ใช้aapt2 dump resourcesเพื่อยืนยันว่าบิลด์จะลบแหล่งข้อมูลที่ไม่ได้ใช้และ เก็บแหล่งข้อมูลที่จำเป็นไว้aapt2 dump resources $OUT/system/priv-app/<APP_NAME>/<APP_NAME>.apk
วิเคราะห์รัศมีการเก็บรักษาและการแทนที่กฎด้วย R8
คอมไพเลอร์ R8 แบบโอเพนซอร์สมีเครื่องมือวิเคราะห์รัศมีการเก็บรักษา
(ซึ่งแสดงใน Android Studio และ Gradle เป็นเครื่องมือวิเคราะห์การกำหนดค่า R8 ด้วย) ที่วัดผลกระทบที่แน่นอนของกฎการเก็บรักษาทุกข้อในระหว่างการคอมไพล์ Soong ผสานรวมเครื่องมือวิเคราะห์นี้
เข้ากับการสร้างแพลตฟอร์ม Android โดยตรง (กำหนดค่าใน
build/soong/java/dex.go)
หากต้องการวิเคราะห์กฎการเก็บสำหรับโมดูลแพลตฟอร์มหรือทั้งบิลด์ ให้ทำดังนี้
เรียกใช้บิลด์ด้วยตัวแปรสภาพแวดล้อม
R8_DUMP_KEEP_RADIUS=trueดังนี้R8_DUMP_KEEP_RADIUS=true m <MODULE_NAME>เมื่อตั้งค่า
R8_DUMP_KEEP_RADIUS=trueแล้ว Soong จะสั่งให้ R8 บันทึกเมตริกของกฎ keep rule ในไฟล์r8keepradius.pbระดับกลางสำหรับแต่ละโมดูลที่คอมไพล์ ภายใต้out/soong/.intermediates/สำหรับกฎการเก็บรักษาและkeepannoคำอธิบายประกอบแต่ละรายการ R8 จะบันทึกข้อมูลต่อไปนี้- รัศมีการคงอยู่ทันที: คลาส ฟิลด์ และเมธอดที่แน่นอน ซึ่งกฎเก็บไว้ พร้อมกับข้อจำกัดเฉพาะที่บังคับใช้ กับการลดขนาด การเพิ่มประสิทธิภาพ หรือการปกปิด
- การรวมกฎ: กฎการเก็บรักษาหรือคำอธิบายประกอบอื่นๆ ที่เก็บรักษารายการเดียวกันอยู่แล้ว หากกฎที่กำหนดเองถูกแทนที่ด้วยกฎ AAPT2 หรือกฎพื้นฐานส่วนกลางอย่างสมบูรณ์ คุณสามารถลบกฎที่กำหนดเองได้อย่างปลอดภัย
- กฎระดับแพ็กเกจและกฎส่วนกลาง: กฎที่ใช้ไวลด์การ์ดระดับแพ็กเกจแบบกว้าง หรือใช้คำสั่งการกำหนดค่าส่วนกลาง
แปลง
r8keepradius.pbเอาต์พุตเป็นรายงาน HTML แบบอินเทอร์แอกทีฟโดยใช้KeepRadiusHtmlReportGenerator(รวมอยู่ในprebuilts/r8/r8.jar)# Generate an HTML report for a single module INTERMEDIATES=out/soong/.intermediates/packages/apps/<APP_NAME>/<APP_NAME> java -cp prebuilts/r8/r8.jar \ com.android.tools.r8.keepradius.KeepRadiusHtmlReportGenerator \ $INTERMEDIATES/android_common/r8keepradius.pb \ keep_radius_report.html # Scan all built modules under out/soong/.intermediates and generate # per-module HTML reports plus an aggregate keepradius.html summary java -cp prebuilts/r8/r8.jar \ com.android.tools.r8.keepradius.KeepRadiusHtmlReportGenerator \ out/soong/.intermediates \ out/keep_radius_reportsเมื่อระบุไดเรกทอรี
KeepRadiusHtmlReportGeneratorจะเดินผ่านไฟล์ทั้งหมด*keepradius*.pbสร้างรายงาน HTML สำหรับแต่ละโมดูล และ สร้างout/keep_radius_reports/keepradius.htmlสรุปจำนวนรายการที่ใช้งานอยู่ จำนวนรายการที่เก็บไว้ และกฎการเก็บรักษาที่มีรัศมีสูงสุดใน บิลด์ ดูข้อมูลเพิ่มเติมเกี่ยวกับการตีความคะแนนการลดขนาด การเพิ่มประสิทธิภาพ และการปกปิดในรายงานที่สร้างขึ้นได้ที่หัวข้อ ใช้เครื่องมือวิเคราะห์การกำหนดค่า R8
นอกจากนี้ Soong ยังรองรับตัวแปรสภาพแวดล้อมในการวินิจฉัย R8 เพิ่มเติมอีก 2 รายการใน
build/soong/java/dex.go
R8_DUMP_INPUT=true: เขียนr8inputs.zipไปยังไดเรกทอรีกลางของโมดูล ซึ่งมี JAR อินพุตทั้งหมด, JAR ของไลบรารี และการกำหนดค่า ProGuard ที่ผสานแล้ว สำหรับการสร้าง R8 แบบสแตนด์อโลนซ้ำR8_DUMP_PERFETTO_TRACE=true: เขียนr8trace.ptraceไปยังไดเรกทอรีกลางของโมดูล เพื่อตรวจสอบการส่งผ่านการคอมไพล์ R8 ใน Perfetto
ตรวจสอบกฎสำหรับผู้ใช้ห้องสมุด
เมื่อ java_library หรือ android_library ส่งออกกฎไปยังผู้ใช้ปลายทาง (export_proguard_flags_files: true) กฎเหล่านั้นต้องไม่มีฟีเจอร์ส่วนกลางที่เปลี่ยนแปลงหรือปิดใช้การเพิ่มประสิทธิภาพสำหรับแอปที่ใช้
R8 มีเครื่องมือวิเคราะห์กฎการเก็บรักษาแบบโอเพนซอร์ส
(ProcessKeepRules) ซึ่งแสดงในแพลตฟอร์ม Android
build เป็นเครื่องมือโฮสต์ process-keep-rules (กำหนดไว้ใน
prebuilts/r8/Android.bp)
# Build the R8 keep rules validator host binary
m process-keep-rules
# Validate one or more ProGuard configuration files
out/host/linux-x86/bin/process-keep-rules <PROGUARD_FLAGS_PATH>
process-keep-rules เครื่องมือจะแยกวิเคราะห์ไฟล์การกำหนดค่าแต่ละไฟล์และจะล้มเหลวพร้อมการวินิจฉัยไฟล์
และบรรทัดหากพบคำสั่งที่ไม่ได้รับอนุญาตในกฎของไลบรารี
ผู้ใช้ คำสั่งที่ไม่อนุญาต ได้แก่ การเพิ่มประสิทธิภาพทั่วโลก การลดขนาด
หรือการปิดใช้การปกปิด (เช่น -dontoptimize หรือ -dontshrink) การ
บรรจุแพ็กเกจใหม่และการแก้ไขสิทธิ์เข้าถึง การวินิจฉัยหรือการแมป และ-keepattributes ระดับแอป
ตรวจสอบแผนผังแหล่งที่มาด้วย pgaudit.py
หากต้องการตรวจสอบไดเรกทอรีแหล่งที่มาที่ยังไม่ได้สร้างควบคู่ไปกับเครื่องมือวิเคราะห์ขณะสร้างของ R8
แผนผังแพลตฟอร์ม Android จะมีสคริปต์ pgaudit.py อยู่ภายใต้
build/make/core/proguard/tools/ เครื่องมือวิเคราะห์แบบคงที่นี้จะสแกนไฟล์ Android.bp,
proguard.flags และ keep.xml ในที่เก็บเพื่อแจ้งกฎที่ครอบคลุมอยู่แล้ว
โดย AAPT2 หรือค่าพื้นฐานของแพลตฟอร์มทั่วโลก ไวลด์การ์ดแบบกว้าง -dontoptimize
การลบล้าง และกฎการเก็บเฉพาะการทดสอบ
# Audit a single package directory
./build/make/core/proguard/tools/pgaudit.py packages/apps/Provision/
# Scan a subsystem tree and write a structured JSON report
./build/make/core/proguard/tools/pgaudit.py packages/ --json=audit_report.json
ทีมแพลตฟอร์มและ OEM สามารถใช้ pgaudit.py เพื่อการคัดแยกแหล่งที่มาอย่างรวดเร็ว
process-keep-rules เพื่อตรวจสอบกฎของไลบรารีที่ส่งออก และ
R8_DUMP_KEEP_RADIUS=true ร่วมกับ KeepRadiusHtmlReportGenerator เพื่อวัด
รัศมีการคงอยู่ของคลาส ฟิลด์ และเมธอดที่แน่นอนของทุกกฎในการสร้าง