# R8 Optimization: Class Constant Operations

DevFeed: [R8 Optimization: Class Constant Operations](<https://devfeed.tech/articles/r8-optimization-class-constant-operations-20955.md>)

Original publisher: [Read original article](<https://jakewharton.com/r8-optimization-class-constant-operations/>)

Published: 2019-02-27T00:00:00Z

Content type: article

Language: en

Sources: [Jake Wharton](<https://devfeed.tech/sources/jake-wharton.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [Android](<https://devfeed.tech/topics/android.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [Java](<https://devfeed.tech/topics/java.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [java](<https://devfeed.tech/tags/java.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [r8](<https://devfeed.tech/tags/r8.md>)

## AI overview

This article explains how R8 can manipulate class constants at compile time. It compares string-literal and class-based log tags, showing how R8 replaces class-name lookups with constants, removes unnecessary initialization and methods, and deduplicates identical strings so the class-based approach adds no runtime overhead.

## Source excerpt

Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". The previous post in the series showed R8 (and D8) invoking string methods at compile-time when the inputs were all constants. R8 is able to do this because the content of constant strings is available inside the bytecode. That post also claimed that strings are the only non-primitive type that can be manipulated like this at compile-time. There is, however, another object type that can be manipulated at compile-time: classes. Classes are templates for the instances we interact with at runtime. Since bytecode fundamentally exists to hold these templates, some operations on classes can thus be performed at compile time. Log Tags There's an ongoing debate (if you can even call it that) on the best way to define a tag string in a class. Historically there have been two strategies: string literals and calling getSimpleName() on the class. private static final String TAG = "MyClass"; // or private static final String TAG = MyClass.class.getSimpleName(); Let's compare the difference in bytecode by defining both and adding some log messages. class MyClass { private static final String TAG_STRING = "MyClass"; private static final String TAG_CLASS = MyClass.class.getSimpleName(); public static void main(String... args) { Log.d(TAG_STRING, "String tag"); Log.d(TAG_CLASS, "Class tag"); } } Compiling, dexing, and dumping the Dalvik bytecode shows the effect of the choice. [000194] MyClass.<clinit>:()V 0000: const-class v0, LMyClass; 0002: invoke-virtual {v0}, Ljava/lang/Class;.getSimpleName:()Ljava/lang/String; 0005: move-result-object v0 0006: sput-object v0, LMyClass;.TAG_CLASS:Ljava/lang/String; 0008: return-void [000120] MyClass.main:([Ljava/lang/String;)V 0000: const-string v1, "MyClass" 0002: const-string v0, "String tag" 0004: invoke-static {v1, v0}, Landroid/util/L