การกำหนดค่าบริการ ART

ก่อนที่คุณจะเริ่มต้น โปรดดูภาพรวมระดับสูงของ บริการ ART

ตั้งแต่ Android 14 เป็นต้นไป การรวบรวม AOT บนอุปกรณ์สำหรับแอป (หรือที่เรียกว่า dexopt) จะได้รับการจัดการโดย ART Service ART Service เป็นส่วนหนึ่งของโมดูล ART และคุณสามารถปรับแต่งได้ผ่านคุณสมบัติของระบบและ API

คุณสมบัติของระบบ

ART Service รองรับ ตัวเลือก dex2oat ที่เกี่ยวข้องทั้งหมด

นอกจากนี้ ART Service ยังรองรับคุณสมบัติของระบบดังต่อไปนี้:

pm.dexopt.<เหตุผล>

นี่คือชุดของคุณสมบัติของระบบที่กำหนดตัวกรองคอมไพเลอร์เริ่มต้นสำหรับ เหตุผลในการคอมไพล์ ที่กำหนดไว้ล่วงหน้าทั้งหมดที่อธิบายไว้ใน สถานการณ์ Dexopt

สำหรับข้อมูลเพิ่มเติม โปรดดูที่ ตัวกรองคอมไพเลอร์

ค่าเริ่มต้นมาตรฐานคือ:

pm.dexopt.first-boot=verify
pm.dexopt.boot-after-ota=verify
pm.dexopt.boot-after-mainline-update=verify
pm.dexopt.bg-dexopt=speed-profile
pm.dexopt.inactive=verify
pm.dexopt.cmdline=verify

pm.dexopt.shared (ค่าเริ่มต้น: ความเร็ว)

นี่คือตัวกรองคอมไพเลอร์ทางเลือกสำหรับแอปที่แอปอื่นใช้

โดยหลักการแล้ว ART Service จะทำการรวบรวมโปรไฟล์ที่แนะนำ ( speed-profile ) สำหรับแอปทั้งหมดเมื่อเป็นไปได้ โดยทั่วไปจะเป็นระหว่าง dexopt ในเบื้องหลัง อย่างไรก็ตาม มีแอปบางตัวที่แอปอื่นใช้ (ไม่ว่าจะผ่าน <uses-library> หรือโหลดแบบไดนามิกโดยใช้ Context#createPackageContext พร้อมด้วย CONTEXT_INCLUDE_CODE ) แอพดังกล่าวไม่สามารถใช้โปรไฟล์ในเครื่องได้เนื่องจากเหตุผลด้านความเป็นส่วนตัว

สำหรับแอปดังกล่าว หากมีการร้องขอการรวบรวมตามโปรไฟล์ ART Service จะพยายามใช้โปรไฟล์คลาวด์ก่อน หากไม่มีโปรไฟล์คลาวด์ ART Service จะกลับไปใช้ตัวกรองคอมไพลเลอร์ที่ระบุโดย pm.dexopt.shared

หากการคอมไพล์ที่ร้องขอไม่ได้รับการแนะนำโปรไฟล์ คุณสมบัตินี้จะไม่มีผลใดๆ

pm.dexopt.<reason>.concurrency (ค่าเริ่มต้น: 1)

นี่คือจำนวนการเรียกใช้ dex2oat สำหรับเหตุผลในการคอมไพล์ที่กำหนดไว้ล่วงหน้าบางประการ ( first-boot , boot-after-ota , boot-after-mainline-update และ bg-dexopt )

โปรดทราบว่าผลกระทบของตัวเลือกนี้จะรวมกับ ตัวเลือกการใช้ทรัพยากร dex2oat ( dalvik.vm.*dex2oat-threads , dalvik.vm.*dex2oat-cpu-set และโปรไฟล์งาน):

  • dalvik.vm.*dex2oat-threads ควบคุมจำนวนเธรดสำหรับการเรียกใช้ dex2oat แต่ละรายการ ในขณะที่ pm.dexopt.<reason>.concurrency ควบคุมจำนวนการเรียกใช้ dex2oat นั่นคือ จำนวนเธรดที่เกิดขึ้นพร้อมกันสูงสุดคือผลคูณของคุณสมบัติระบบทั้งสอง
  • dalvik.vm.*dex2oat-cpu-set และโปรไฟล์งานจะเชื่อมโยงกับการใช้งาน CPU core เสมอ โดยไม่คำนึงถึงจำนวนเธรดที่เกิดขึ้นพร้อมกันสูงสุด (ตามที่กล่าวไว้ข้างต้น)

การเรียกใช้ dex2oat เพียงครั้งเดียวอาจไม่ได้ใช้คอร์ CPU ทั้งหมดได้อย่างเต็มที่ โดยไม่คำนึงถึง dalvik.vm.*dex2oat-threads ดังนั้น การเพิ่มจำนวนการเรียกใช้ dex2oat ( pm.dexopt.<reason>.concurrency ) สามารถใช้คอร์ CPU ได้ดีขึ้น เพื่อเร่งความคืบหน้าโดยรวมของ dexopt สิ่งนี้มีประโยชน์อย่างยิ่งระหว่างการบู๊ต

อย่างไรก็ตาม การเรียกใช้ dex2oat มากเกินไปอาจทำให้อุปกรณ์หน่วยความจำไม่เพียงพอ แม้ว่าจะสามารถบรรเทาได้ด้วยการตั้งค่า dalvik.vm.dex2oat-swap ให้เป็น true เพื่ออนุญาตให้ใช้ไฟล์สลับได้ การร้องขอมากเกินไปอาจทำให้เกิดการสลับบริบทโดยไม่จำเป็น ดังนั้นควรปรับตัวเลขนี้อย่างระมัดระวังเป็นรายผลิตภัณฑ์

pm.dexopt.downgrade_after_inactive_days (ค่าเริ่มต้น: ไม่ได้ตั้งค่า)

หากตั้งค่าตัวเลือกนี้ ART Service จะเลือกเฉพาะแอปที่ใช้ภายในจำนวนวันที่กำหนดล่าสุดเท่านั้น

นอกจากนี้ หากพื้นที่จัดเก็บใกล้เหลือน้อย ในระหว่าง dexopt พื้นหลัง ART Service จะดาวน์เกรดตัวกรองคอมไพเลอร์ของแอปที่ไม่ได้ใช้งานภายในจำนวนวันล่าสุด เพื่อเพิ่มพื้นที่ว่าง เหตุผลของคอมไพเลอร์สำหรับสิ่งนี้ inactive และตัวกรองของคอมไพเลอร์ถูกกำหนดโดย pm.dexopt.inactive ขีดจำกัดพื้นที่เพื่อทริกเกอร์คุณลักษณะนี้คือขีดจำกัดพื้นที่ต่ำของ Storage Manager (กำหนดค่าได้ผ่านการตั้งค่าส่วนกลาง sys_storage_threshold_percentage และ sys_storage_threshold_max_bytes ค่าเริ่มต้น: 500MB) บวก 500MB

หากคุณปรับแต่งรายการแพ็คเกจผ่าน ArtManagerLocal#setBatchDexoptStartCallback แพ็คเกจในรายการที่ BatchDexoptStartCallback ให้มาสำหรับ bg-dexopt จะไม่ถูกดาวน์เกรด

pm.dexopt.disable_bg_dexopt (ค่าเริ่มต้น: เท็จ)

นี่เป็นเพียงการทดสอบเท่านั้น จะป้องกันไม่ให้ ART Service กำหนดเวลางาน dexopt พื้นหลัง

หากงาน dexopt พื้นหลังถูกกำหนดเวลาไว้แล้ว แต่ยังไม่ได้รัน ตัวเลือกนี้จะไม่มีผลใดๆ นั่นคืองานจะยังคงดำเนินต่อไป

ลำดับคำสั่งที่แนะนำเพื่อป้องกันไม่ให้งาน dexopt พื้นหลังทำงานคือ:

setprop pm.dexopt.disable_bg_dexopt true
pm bg-dexopt-job --disable

บรรทัดแรกป้องกันไม่ให้งาน dexopt พื้นหลังถูกกำหนดเวลา หากยังไม่ได้กำหนดเวลา บรรทัดที่สองจะยกเลิกการกำหนดเวลางาน dexopt พื้นหลัง หากมีกำหนดเวลาไว้แล้ว และจะยกเลิกงาน dexopt พื้นหลังทันทีหากกำลังทำงานอยู่

API บริการ ART

ART Service เปิดเผย Java API สำหรับการปรับแต่ง API ถูกกำหนดไว้ใน ArtManagerLocal ดู Javadoc ใน art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java สำหรับการใช้งาน ( แหล่งที่มาของ Android 14 แหล่งการพัฒนาที่ยังไม่เผยแพร่ )

ArtManagerLocal เป็นซิงเกิลตันที่จัดขึ้นโดย LocalManagerRegistry ฟังก์ชันตัวช่วย com.android.server.pm.DexOptHelper#getArtManagerLocal ช่วยให้คุณได้รับมัน

import static com.android.server.pm.DexOptHelper.getArtManagerLocal;

API ส่วนใหญ่ต้องการอินสแตนซ์ PackageManagerLocal.FilteredSnapshot ซึ่งเก็บข้อมูลของแอปทั้งหมด คุณสามารถรับมันได้โดยการเรียก PackageManagerLocal#withFilteredSnapshot โดยที่ PackageManagerLocal ยังเป็นซิงเกิลตันที่ LocalManagerRegistry ถืออยู่ และสามารถรับได้จาก com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal

import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;

ต่อไปนี้คือกรณีการใช้งานทั่วไปของ API

ทริกเกอร์ dexopt สำหรับแอป

คุณสามารถทริกเกอร์ dexopt สำหรับแอปใดๆ ได้ตลอดเวลาโดยเรียก ArtManagerLocal#dexoptPackage

try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  getArtManagerLocal().dexoptPackage(
      snapshot,
      "com.google.android.calculator",
      new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}

คุณสามารถส่งเหตุผล dexopt ของคุณเองได้ หากคุณทำเช่นนั้น จะต้องตั้งค่าคลาสลำดับความสำคัญและตัวกรองคอมไพเลอร์อย่างชัดเจน

try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  getArtManagerLocal().dexoptPackage(
      snapshot,
      "com.google.android.calculator",
      new DexoptParams.Builder("my-reason")
          .setCompilerFilter("speed-profile")
          .setPriorityClass(ArtFlags.PRIORITY_BACKGROUND)
          .build());
}

ยกเลิก dexopt

หากการดำเนินการเริ่มต้นโดยการเรียก dexoptPackage คุณสามารถส่งสัญญาณการยกเลิกได้ ซึ่งช่วยให้คุณยกเลิกการดำเนินการได้ในบางจุด สิ่งนี้มีประโยชน์เมื่อคุณรัน dexopt แบบอะซิงโครนัส

Executor executor = ...;  // Your asynchronous executor here.
var cancellationSignal = new CancellationSignal();
executor.execute(() -> {
  try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
    getArtManagerLocal().dexoptPackage(
        snapshot,
        "com.google.android.calculator",
        new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build(),
        cancellationSignal);
  }
});

// When you want to cancel the operation.
cancellationSignal.cancel();

คุณยังสามารถยกเลิก dexopt พื้นหลังได้ ซึ่งเริ่มต้นโดย ART Service

getArtManagerLocal().cancelBackgroundDexoptJob();

รับผลลัพธ์ dexopt

หากการดำเนินการเริ่มต้นโดยการเรียก dexoptPackage คุณสามารถรับผลลัพธ์จากค่าที่ส่งคืน

DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  result = getArtManagerLocal().dexoptPackage(...);
}

// Process the result here.
...

ART Service ยังเริ่มต้นการดำเนินการ dexopt เองในหลาย ๆ สถานการณ์ เช่น dexopt ในเบื้องหลัง หากต้องการฟังผลลัพธ์ dexopt ทั้งหมด ไม่ว่าการดำเนินการจะเริ่มต้นโดยการเรียก dexoptPackage หรือโดย ART Service ให้ใช้ ArtManagerLocal#addDexoptDoneCallback

getArtManagerLocal().addDexoptDoneCallback(
    false /* onlyIncludeUpdates */,
    Runnable::run,
    (result) -> {
      // Process the result here.
      ...
    });

อาร์กิวเมนต์แรกกำหนดว่าจะรวมเฉพาะการอัปเดตในผลลัพธ์หรือไม่ หากคุณต้องการฟังแพ็คเกจที่อัพเดตโดย dexopt เท่านั้น ให้ตั้งค่าเป็น true

อาร์กิวเมนต์ที่สองคือตัวดำเนินการของการโทรกลับ หากต้องการดำเนินการโทรกลับบนเธรดเดียวกันกับที่ทำ dexopt ให้ใช้ Runnable::run หากคุณไม่ต้องการให้การโทรกลับบล็อก dexopt ให้ใช้ตัวดำเนินการแบบอะซิงโครนัส

คุณสามารถเพิ่มการโทรกลับหลายครั้งได้ และ ART Service จะดำเนินการทั้งหมดตามลำดับ การโทรกลับทั้งหมดจะยังคงใช้งานได้สำหรับการโทรในอนาคตทั้งหมด เว้นแต่คุณจะลบออก

หากคุณต้องการลบการโทรกลับ ให้เก็บการอ้างอิงของการโทรกลับไว้เมื่อคุณเพิ่ม และใช้ ArtManagerLocal#removeDexoptDoneCallback

DexoptDoneCallback callback = (result) -> {
  // Process the result here.
  ...
};

getArtManagerLocal().addDexoptDoneCallback(
    false /* onlyIncludeUpdates */, Runnable::run, callback);

// When you want to remove it.
getArtManagerLocal().removeDexoptDoneCallback(callback);

ปรับแต่งรายการแพ็กเกจและพารามิเตอร์ dexopt

ART Service จะเริ่มต้นการดำเนินการ dexopt เองระหว่างการบูตและ dexopt ในเบื้องหลัง หากต้องการปรับแต่งรายการแพ็คเกจหรือพารามิเตอร์ dexopt สำหรับการดำเนินการเหล่านั้น ให้ใช้ ArtManagerLocal#setBatchDexoptStartCallback

getArtManagerLocal().setBatchDexoptStartCallback(
    Runnable::run,
    (snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
      switch (reason) {
        case ReasonMapping.REASON_BG_DEXOPT:
          var myPackages = new ArrayList<String>(defaultPackages);
          myPackages.add(...);
          myPackages.remove(...);
          myPackages.sort(...);
          builder.setPackages(myPackages);
          break;
        default:
          // Ignore unknown reasons.
      }
    });

คุณสามารถเพิ่มรายการลงในรายการแพ็คเกจ ลบรายการออกจากรายการ จัดเรียง หรือแม้แต่ใช้รายการที่แตกต่างไปจากเดิมอย่างสิ้นเชิง

การโทรกลับของคุณจะต้องเพิกเฉยต่อเหตุผลที่ไม่ทราบสาเหตุ เนื่องจากอาจมีการเพิ่มเหตุผลเพิ่มเติมในอนาคต

คุณสามารถตั้งค่า BatchDexoptStartCallback ได้มากที่สุดหนึ่งรายการ การโทรกลับจะยังคงใช้งานได้สำหรับการโทรในอนาคตทั้งหมด เว้นแต่คุณจะล้างข้อมูลออก

หากคุณต้องการล้างการโทรกลับ ให้ใช้ ArtManagerLocal#clearBatchDexoptStartCallback

getArtManagerLocal().clearBatchDexoptStartCallback();

ปรับแต่งพารามิเตอร์ของงาน dexopt พื้นหลัง

ตามค่าเริ่มต้น งาน dexopt ในเบื้องหลังจะทำงานวันละครั้งเมื่ออุปกรณ์ไม่ได้ใช้งานและกำลังชาร์จ สิ่งนี้สามารถเปลี่ยนแปลงได้โดยใช้ ArtManagerLocal#setScheduleBackgroundDexoptJobCallback

getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
    Runnable::run,
    builder -> {
      builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
    });

คุณสามารถตั้งค่า ScheduleBackgroundDexoptJobCallback ได้มากที่สุดหนึ่งรายการ การโทรกลับจะยังคงใช้งานได้สำหรับการโทรในอนาคตทั้งหมด เว้นแต่คุณจะล้างข้อมูลออก

หากคุณต้องการล้างการโทรกลับ ให้ใช้ ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback

getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();

ปิดการใช้งาน dexopt ชั่วคราว

การดำเนินการ dexopt ใด ๆ ที่เริ่มต้นโดย ART Service จะทริกเกอร์ BatchDexoptStartCallback คุณสามารถยกเลิกการดำเนินการต่อไปเพื่อปิดใช้งาน dexopt ได้อย่างมีประสิทธิภาพ

หากการดำเนินการที่คุณยกเลิกเป็นแบบ dexopt พื้นหลัง จะเป็นไปตามนโยบายการลองใหม่เริ่มต้น (30 วินาที เอ็กซ์โพเนนเชียล ต่อยอดที่ 5 ชั่วโมง)

// Good example.

var shouldDisableDexopt = new AtomicBoolean(false);

getArtManagerLocal().setBatchDexoptStartCallback(
    Runnable::run,
    (snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
      if (shouldDisableDexopt.get()) {
        cancellationSignal.cancel();
      }
    });

// Disable dexopt.
shouldDisableDexopt.set(true);
getArtManagerLocal().cancelBackgroundDexoptJob();

// Re-enable dexopt.
shouldDisableDexopt.set(false);

คุณสามารถมี BatchDexoptStartCallback ได้มากที่สุดหนึ่งรายการ หากคุณต้องการใช้ BatchDexoptStartCallback เพื่อกำหนดรายการแพ็คเกจหรือพารามิเตอร์ dexopt เองด้วย คุณต้องรวมโค้ดเข้าในการเรียกกลับครั้งเดียว

// Bad example.

// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();

// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();

การดำเนินการ dexopt ที่ดำเนินการกับการติดตั้งแอป ไม่ ได้เริ่มต้นโดย ART Service แต่จะเริ่มต้นโดยตัวจัดการแพ็คเกจผ่านการเรียก dexoptPackage แทน ดังนั้นจึง ไม่ ทริกเกอร์ BatchDexoptStartCallback หากต้องการปิดใช้งาน dexopt ในการติดตั้งแอป ให้ป้องกันไม่ให้ตัวจัดการแพ็คเกจเรียก dexoptPackage

แทนที่ตัวกรองคอมไพเลอร์สำหรับแพ็คเกจบางอย่าง (Android 15 (ทดลอง AOSP)+)

คุณสามารถแทนที่ตัวกรองคอมไพเลอร์สำหรับบางแพ็คเกจได้โดยลงทะเบียนการโทรกลับผ่าน setAdjustCompilerFilterCallback การเรียกกลับจะถูกเรียกเมื่อใดก็ตามที่แพ็คเกจกำลังจะถูก dexopted ไม่ว่า dexopt จะเริ่มต้นโดย ART Service ในระหว่างการบูตและ dexopt พื้นหลังหรือโดยการเรียก dexoptPackage API

หากแพ็คเกจไม่ต้องการการปรับเปลี่ยน การเรียกกลับจะต้องส่งคืน originalCompilerFilter

getArtManagerLocal().setAdjustCompilerFilterCallback(
    Runnable::run,
    (packageName, originalCompilerFilter, reason) -> {
      if (isVeryImportantPackage(packageName)) {
        return "speed-profile";
      }
      return originalCompilerFilter;
    });

คุณสามารถตั้งค่า AdjustCompilerFilterCallback ได้เพียงอันเดียวเท่านั้น ถ้าคุณต้องการใช้ AdjustCompilerFilterCallback เพื่อแทนที่ตัวกรองคอมไพเลอร์สำหรับหลายแพ็คเกจ คุณต้องรวมรหัสเป็นการเรียกกลับครั้งเดียว การโทรกลับจะยังคงใช้งานได้สำหรับการโทรในอนาคตทั้งหมด เว้นแต่คุณจะล้างข้อมูลออก

หากคุณต้องการล้างการโทรกลับ ให้ใช้ ArtManagerLocal#clearAdjustCompilerFilterCallback

getArtManagerLocal().clearAdjustCompilerFilterCallback();

การปรับแต่งอื่นๆ

ART Service ยังรองรับการปรับแต่งอื่นๆ อีกด้วย

ตั้งค่าเกณฑ์การระบายความร้อนสำหรับ dexopt พื้นหลัง

การควบคุมความร้อนของงาน dexopt พื้นหลังจะดำเนินการโดย Job Scheduler งานจะถูกยกเลิกทันทีเมื่ออุณหภูมิถึง THERMAL_STATUS_MODERATE เกณฑ์ของ THERMAL_STATUS_MODERATE สามารถปรับแต่งได้

ตรวจสอบว่า dexopt พื้นหลังกำลังทำงานอยู่หรือไม่

งาน dexopt เบื้องหลังได้รับการจัดการโดย Job Scheduler และรหัสงานคือ 27873780 หากต้องการตรวจสอบว่างานกำลังทำงานอยู่หรือไม่ ให้ใช้ Job Scheduler API

// Good example.

var jobScheduler =
    Objects.requireNonNull(mContext.getSystemService(JobScheduler.class));
int reason = jobScheduler.getPendingJobReason(27873780);

if (reason == PENDING_JOB_REASON_EXECUTING) {
  // Do something when the job is running.
  ...
}
// Bad example.

var backgroundDexoptRunning = new AtomicBoolean(false);

getArtManagerLocal().setBatchDexoptStartCallback(
    Runnable::run,
    (snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
      if (reason.equals(ReasonMapping.REASON_BG_DEXOPT)) {
        backgroundDexoptRunning.set(true);
      }
    });

getArtManagerLocal().addDexoptDoneCallback(
    false /* onlyIncludeUpdates */,
    Runnable::run,
    (result) -> {
      if (result.getReason().equals(ReasonMapping.REASON_BG_DEXOPT)) {
        backgroundDexoptRunning.set(false);
      }
    });

if (backgroundDexoptRunning.get()) {
  // Do something when the job is running.
  ...
}

ระบุโปรไฟล์สำหรับ dexopt

หากต้องการใช้โปรไฟล์เพื่อเป็นแนวทาง dexopt ให้วางไฟล์ .prof หรือไฟล์ .dm ถัดจาก APK

ไฟล์ .prof ต้องเป็นไฟล์โปรไฟล์รูปแบบไบนารี และชื่อไฟล์ต้องเป็นชื่อไฟล์ของ APK + .prof ตัวอย่างเช่น,

base.apk.prof

ชื่อไฟล์ของไฟล์ .dm จะต้องเป็นชื่อไฟล์ของ APK โดยมีนามสกุลแทนที่ด้วย .dm ตัวอย่างเช่น,

base.dm

หากต้องการตรวจสอบว่ามีการใช้โปรไฟล์สำหรับ dexopt ให้รัน dexopt ด้วย speed-profile และตรวจสอบผลลัพธ์

pm art clear-app-profiles <package-name>
pm compile -m speed-profile -f -v <package-name>

บรรทัดแรกจะล้างโปรไฟล์ทั้งหมดที่สร้างโดยรันไทม์ (เช่น ที่อยู่ใน /data/misc/profiles ) หากมี เพื่อให้แน่ใจว่าโปรไฟล์ที่อยู่ถัดจาก APK เป็นโปรไฟล์เดียวที่ ART Service สามารถใช้ได้ บรรทัดที่สองรัน dexopt ด้วย speed-profile และส่งผ่าน -v เพื่อพิมพ์ผลลัพธ์แบบละเอียด

หากมีการใช้โปรไฟล์ คุณจะเห็น actualCompilerFilter=speed-profile ในผลลัพธ์ มิฉะนั้น คุณจะเห็น actualCompilerFilter=verify ตัวอย่างเช่น,

DexContainerFileDexoptResult{dexContainerFile=/data/app/~~QR0fTV0UbDbIP1Su7XzyPg==/com.google.android.gms-LvusF2uARKOtBbcaPHdUtQ==/base.apk, primaryAbi=true, abi=x86_64, actualCompilerFilter=speed-profile, status=PERFORMED, dex2oatWallTimeMillis=4549, dex2oatCpuTimeMillis=14550, sizeBytes=3715344, sizeBeforeBytes=3715344}

สาเหตุทั่วไปที่ ART Service ไม่ใช้โปรไฟล์มีดังต่อไปนี้:

  • โปรไฟล์มีชื่อไฟล์ผิดหรือไม่ได้อยู่ข้าง APK
  • โปรไฟล์อยู่ในรูปแบบที่ไม่ถูกต้อง
  • โปรไฟล์ไม่ตรงกับ APK (เช็คซัมในโปรไฟล์ไม่ตรงกับเช็คซัมของไฟล์ .dex ใน APK)