Rozwiązywanie problemów z optymalizacją za pomocą reguł

Oprócz ogólnych reguł przechowywania, dodatkowych typów reguł przechowywaniaopcji globalnych możesz używać określonych reguł do rozwiązywania problemów z optymalizacją.

-checkdiscard

Reguła -checkdiscard pozwala sprawdzić, czy R8 odrzucił klasę lub jej element, które miały zostać usunięte. Jeśli określona klasa lub element nie zostaną odrzucone, kompilacja się nie powiedzie.

Składnia elementu -checkdiscard jest taka:


-checkdiscard <class_specification>

W tym przykładzie kompilacja nie powiedzie się, jeśli zachowane zostanie pole userId lub metoda setLabel() z klasy com.example.models.User:

-checkdiscard class com.example.models.User{
  private java.lang.String userId;
  public void setLabel(java.lang.String);
}

Kod klasy może nadal być obecny w aplikacji, jeśli jej metody zostały wstawione w inne klasy. Aby mieć pewność, że kod został całkowicie usunięty, a nie tylko wstawiony, dodaj odpowiednią regułę, która uniemożliwia R8 przeprowadzanie optymalizacji w klasie docelowej, łącząc -checkdiscard z regułą -keep,allowshrinking. Uniemożliwia to optymalizacje takie jak łączenie klas i wstawianie kodu. Jeśli reguła -checkdiscard zostanie spełniona, żadne treści z pasujących klas nie będą znajdować się w zoptymalizowanej aplikacji.

Ten przykład pokazuje, jak to zrobić:

# Either keep or remove the class, don't rename or otherwise optimize it
-keep,allowshrinking class com.example.foo { *; }

# Verify that the class and all of its fields and methods are removed.
-checkdiscard class com.example.foo

-whyareyoukeeping

Użyj reguły -whyareyoukeeping, aby dowiedzieć się, dlaczego R8 zachował w kompilacji aplikacji konkretną klasę, pole lub metodę. Element może być przechowywany z wielu powodów, ale ta reguła podaje tylko ten, który wyjaśnia najkrótszą ścieżkę do elementu z przechowywanego elementu. Jeśli usuniesz tę ścieżkę z kodu, produkt może nadal być zachowany, ale z innego powodu.

Możliwe przyczyny:

  • Reguła zachowywania: reguła zachowywania może pochodzić z aplikacji, używanej biblioteki lub reguł wygenerowanych przez AAPT (Android Asset Packaging Tool).

  • Odwołania przechodnie z zachowanego kodu lub zasobów: jeśli R8 zachowuje kod lub XML (np. układy), wszystko, do czego statycznie się odwołuje, jest zachowywane.

Składnia:


-whyareyoukeeping <class_specification>

Na przykład:

-whyareyoukeeping class com.example.foo.MainActivity {
  private void setLabel(...);
}

Dane wyjściowe są drukowane w konsoli.

Jeśli nie masz reguły, która zachowuje setLabel(), wynik to:

com.example.foo.MainActivity
|- is referenced in keep rule:
|  /app/build/intermediates/aapt_proguard_file/release/processReleaseResources/aapt_rules.txt:4:1
Nothing is keeping void com.example.foo.MainActivity.setLabel()

Jeśli masz regułę przechowywania kierowaną na setLabel(), dane wyjściowe będą podobne do tych:

com.example.foo.MainActivity
|- is referenced in keep rule:
| /app/proguard-rules.pro:23:1
void com.example.foo.MainActivity.setLabel()
|- is referenced in keep rule:
|  /app/proguard-rules.pro:23:1