# R8 Optimization: Enum Switch Maps

DevFeed: [R8 Optimization: Enum Switch Maps](<https://devfeed.tech/articles/r8-optimization-enum-switch-maps-20958.md>)

Original publisher: [Read original article](<https://jakewharton.com/r8-optimization-enum-switch-maps/>)

Published: 2019-10-16T00:00:00Z

Content type: tutorial

Language: en

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

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

Tags: [android](<https://devfeed.tech/tags/android.md>), [code](<https://devfeed.tech/tags/code.md>), [compiler](<https://devfeed.tech/tags/compiler.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 Java enum switch statements are compiled and how R8 optimizes them. It describes the generated switch-map array that translates enum ordinals into stable branch values, allowing the application to continue working when enum constants are reordered and only part of the code is recompiled.

## 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 on R8 covered enum ordinals which then allowed branch elimination to apply to a switch statement. In that post, the full bytecode for switch on an enum was omitted because there's actually more to the optimization. Let's start with a simple enum and a switch over its contents in two separate source files (this will be important later). enum Greeting { FORMAL, INFORMAL } class Main { static String greetingType(Greeting greeting) { switch (greeting) { case FORMAL: return "formal"; case INFORMAL: return "informal"; default: throw new AssertionError(); } } public static void main(String... args) { System.out.println(greetingType(Greeting.INFORMAL)); } } If we compile and run these files the output is as expected. $ javac Greeting.java Main.java $ java -cp . Main informal The bytecode in the previous post showed that the compiler produces a call to ordinal() which is then used in the switch. But if that was all that the compiler did, re-ordering the constants of Greeting would break the output of Main. enum Greeting { - FORMAL, INFORMAL + INFORMAL, FORMAL } After changing the constant order, we can recompile only Greeting.java and yet the application still produces the correct output. $ javac Greeting.java $ java -cp . Main informal If the bytecode was only relying on the value of ordinal(), this code would have produced "formal". Into The Bytecode To understand how this works we can look at the Java bytecode of greetingType. $ javap -c Main.class class Main { static java.lang.String greetingType(Greeting); Code: 0: getstatic #2 // Field Main$1.$SwitchMap$Greeting:[I 3: aload_0 4: invokevirtual #3 // Method Greeting.ordinal:()I 7: iaload 8: lookupswitch { 1: 36 2: 39 default: 42 } 36: ldc #4 // String formal 38: areturn 39: ldc #5 // String informa