Ek kural türleri

R8, keep kuralları dışında uygulamanızın optimizasyonunu etkileyen kurallar eklemenize olanak tanır. Bu kuralları, saklama kurallarınızı yönettiğiniz proguard-rules.pro dosyasına ekleyin.

Kurallar aşağıdaki kategorilere ayrılır:

  • Varsayımlar
    • -assumevalues
    • -assumenosideeffects
  • Diğer optimizasyonlar
    • -convertchecknotnull
    • -maximumremovedandroidloglevel

Varsayımlar

Bu kurallar, R8'e çalışma zamanında belirli kod davranışlarıyla ilgili belirli varsayımlarda bulunabileceğini söyler.

optimizasyonu kapsamlı bir şekilde test ettiğinizden emin olun.

-assumevalues

-assumevalues kuralı, R8'e bir alanın değerinin veya bir yöntemin dönüş değerinin her zaman belirli bir sabit olduğunu ya da çalışma zamanında tanımlanmış bir aralıkta yer aldığını bildirir. -assumevalues, derleme zamanında çalışma zamanında belirli değerlere sahip olduğu bilinen işaret değerleri gibi öğeler için tasarlanmıştır.

R8'in standart statik analizi, üyelerin çalışma zamanı değerlerini belirleyemeyebilir. -assumevalues ile R8'e kodu optimize ederken belirtilen değeri veya aralığı varsaymasını söylersiniz. Bu, R8'in agresif optimizasyonlar yapmasına olanak tanır.

-assumevalues söz dizimi, member_specification tutma söz dizimine benzer ancak ek olarak aşağıdaki gibi bir return clause içerir:

<member_specification> return <value> | <range>

<value> ve <range> bağımsız değişkenleri aşağıdaki değerleri ve türleri destekler:

  • Özel değerler: true, false, null, @NonNull
  • Temel değerler: int
  • Statik alan referansları (numaralandırılmış alanlar dahil)

Bir aralık tanımlamak için kapsayıcı min..max biçimini kullanın. Örneğin, aşağıdaki snippet'te CUSTOM_VAL değişkeninin 26 ile 2147483647 arasındaki değerleri kabul ettiği gösterilmektedir:

-assumevalues public class com.example.Foo {
    public static int CUSTOM_VAL return 26..2147483647;
}

Bu kuralı aşağıdaki durumlarda kullanabilirsiniz:

  • Kitaplıklar için: Uygulamalar optimize edildiğinde tüm yerel hata ayıklama kancalarının herkese açık kitaplık kodundan kaldırıldığından emin olun.
  • Uygulamalar için: Hata ayıklama kodu gibi öğeleri yayınlanan bir uygulamadan kaldırmak için. Derleme değişkenlerini ve belirli kaynak kümelerinin veya sabitlerin değişkenlerini kullanmak tercih edilir ancak değişken kaynak kümeleri sizin durumunuzda işe yaramıyorsa ya da kod yollarının tamamen kaldırıldığına dair daha güçlü bir garantiye ihtiyacınız varsa -assumevalues kullanın.

Aşağıdaki örnekte, R8'in bir uygulamanın optimize edilmiş sürümünden hata ayıklama araçlarını kaldırdığı bir sınıf gösterilmektedir:

package com.example;

public class MyConfig {
    // This field is initialized to false but is overwritten by a resource
    // value or other mechanism in the final build process. R8's static analysis
    // might see the initial 'false' but the runtime value is known to be
    // 'true'.
    public static final boolean IS_OPTIMIZED_VERSION = false;
}

// In another class:
public void initFeatures() {
    if (MyConfig.IS_OPTIMIZED_VERSION) {
        System.out.println("Starting optimized features...");
        android.util.Log.d(TAG, "Starting optimized features...");
        initOptimizedService();
    } else {
        android.util.Log.d(TAG, "Starting debug/logging features...");
        initDebugTools();
    }
}

Aşağıdaki kuralda, R8'e değişkenin IS_OPTIMIZED_VERSION her zaman true olarak ayarlanmasının beklendiğinin nasıl söyleneceği gösterilmektedir.

-assumevalues class com.example.MyConfig {
    public static final boolean IS_OPTIMIZED_VERSION return true;
}

-assumenosideeffects

-assumenosideeffects kuralı, R8'e belirtilen üyelerin yan etkisinin olmadığını varsayabileceğini söyler. R8, dönüş değeri olmayan veya sabit bir değer döndüren bu tür yöntemlere yapılan çağrıları tamamen kaldırabilir.

-assumenosideeffects söz dizimi, member_specification tutma söz dizimine benzer.

Aşağıdaki örnekte, DebugLogger sınıfındaki log adlı tüm yöntemlerin yan etkisi olmaması gerektiğini R8'e nasıl söyleyeceğiniz gösterilmektedir. Bu sayede R8, bu yöntemlere yapılan çağrıları kaldırabilir.public static

-assumenosideeffects class com.example.DebugLogger {
    public static void log(...);
}

Diğer optimizasyonlar

Bunlar, varsayılan olarak etkinleştirilmeyen daha gelişmiş optimizasyonlardır. Bu seçenekleri etkinleştirdiğinizde R8'in, varsayılan optimizasyonlara ek olarak kodu talimatlara uygun şekilde optimize etmesine izin vermiş olursunuz.

-convertchecknotnull

Boş değer kontrollerini optimize etmek için -convertchecknotnull kuralını kullanabilirsiniz. Bu, nesne parametresi alan ve nesne boşsa (null) hata veren tüm yöntemler için geçerlidir. Bu, standart bir Kotlin onaylamasına benzer. İstisna türü ve mesajı mutlaka aynı olmasa da koşullu kilitlenme davranışı aynıdır.

Bir -convertchecknotnull kuralı belirli bir yöntemle eşleşirse bu yönteme yapılan her çağrı, ilk bağımsız değişkende getClass() çağrısıyla değiştirilir. getClass() çağrıları, null denetimi yerine geçer ve R8'in, orijinal null denetiminin pahalı dize ayırmaları gibi ekstra bağımsız değişkenlerini kaldırmasına olanak tanır.

-convertchecknotnull söz dizimi aşağıdaki gibidir:

-convertchecknotnull <class_specification> {
   <member_specification>;
}

Örneğin, Preconditions sınıfınızda checkNotNull yöntemi aşağıdaki gibi tanımlanmışsa:

class Preconditions {
    fun <T> checkNotNull(value: T?): T {
        if (value == null) {
            throw NullPointerException()
        } else {
            return value
        }
    }
}

Aşağıdaki kuralı kullanın:

-convertchecknotnull class com.example.package.Preconditions {
  void checkNotNull(java.lang.Object);
}

Kural, ilk bağımsız değişkendeki checkNotNull() ile başlayan tüm aramaları getClass ile başlayan aramalara dönüştürür. Bu örnekte, checkNotNull(bar) çağrısı bar.getClass() ile değiştiriliyor. bar null olsaydı bar.getClass(), NullPointerException atar ve benzer bir null kontrolü etkisi elde ederdi ancak bu daha verimli olurdu.

-maximumremovedandroidloglevel

Bu kural türü, belirli bir günlük düzeyinde veya bu düzeyin altında Android günlük kaydı ifadelerini (ör. Log.w(...) ve Log.isLoggable(...)) kaldırır.

maximumremovedandroidloglevel söz dizimi aşağıdaki gibidir:

-maximumremovedandroidloglevel <log_level> [<class_specification>]

İsteğe bağlı class_specification değerini sağlamazsanız R8, günlük kaldırma işlemini uygulamanın tamamına uygular.

Günlük düzeyleri aşağıdaki gibidir:

Günlük etiketi

Günlük düzeyi

VERBOSE

2

HATA AYIKLA

3

BİLGİ

4

UYARI

5

HATA

6

ASSERT

7

Örneğin, aşağıdaki koda sahipseniz:

class Foo {
  private static final String TAG = "Foo";
  void logSomething() {
    if (Log.isLoggable(TAG, WARNING)) {
      Log.e(TAG, "Won't be logged");
    }
    Log.w(TAG, "Won't be logged");
    Log.e(TAG, "Will be logged");
  }
}

Aşağıdaki kuralı kullanıyorsanız:

# A level of 5 corresponds to a log level of WARNING.
-maximumremovedandroidloglevel 5 class Foo { void logSomething(); }

Optimize edilmiş kod aşağıdaki gibidir:

class Foo {
  private static final String TAG = "Foo";
  void logSomething() {
    Log.e(TAG, "Will be logged");
  }
}

Aynı yöntem için birden fazla maksimum günlük düzeyi sağlarsanız R8, minimum düzeyi kullanır. Örneğin, aşağıdaki kurallar verildiğinde:

-maximumremovedandroidloglevel 7 class ** { void foo(); }
-maximumremovedandroidloglevel 4 class ** { void foo(); }

ise foo() için kaldırılan maksimum günlük düzeyi 4 olur.