VarHandle desugar: Add support for getVolatile

Bug: b/247076137
Change-Id: I57d19949199a3d07189ef8a2e6d8143eea826ed9
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 2899662..01ec8f1 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -362,6 +362,7 @@
   public final DexString getString = createString("get");
   public final DexString setString = createString("set");
   public final DexString compareAndSetString = createString("compareAndSet");
+  public final DexString getVolatileString = createString("getVolatile");
 
   // Method names used on MethodHandles.
   public final DexString lookupString = createString("lookup");
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java
index bd38568..0342bb7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java
@@ -290,7 +290,7 @@
       if (name.equals(factory.compareAndSetString)) {
         assert arity == 3 || arity == 4;
         return computeDesugarSignaturePolymorphicMethod(invoke, arity - 2);
-      } else if (name.equals(factory.getString)) {
+      } else if (name.equals(factory.getString) || name.equals(factory.getVolatileString)) {
         assert arity == 1 || arity == 2;
         return computeDesugarSignaturePolymorphicMethod(invoke, arity);
       } else if (name.equals(factory.setString)) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java
index fafdf98..29fd7b9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaringMethods.java
@@ -113,6 +113,18 @@
                 .setAccessFlags(FieldAccessFlags.createPublicFinalSynthetic())
                 .disableAndroidApiLevelCheck()
                 .build()));
+    DexMethod getVolatileArrayLong =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.longType, factory.createType(factory.createString("[J")), factory.intType),
+            factory.createString("getVolatile"));
+    DexMethod getVolatileArrayInt =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.intType, factory.createType(factory.createString("[I")), factory.intType),
+            factory.createString("getVolatile"));
     DexMethod toIntIfPossible =
         factory.createMethod(
             builder.getType(),
@@ -186,6 +198,11 @@
             builder.getType(),
             factory.createProto(factory.longType, factory.objectType),
             factory.createString("get"));
+    DexMethod getVolatileInt =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(factory.intType, factory.objectType),
+            factory.createString("getVolatile"));
     DexMethod compareAndSetArrayLong =
         factory.createMethod(
             builder.getType(),
@@ -204,11 +221,29 @@
                 factory.objectType,
                 factory.createType(factory.createString("Ljava/lang/Class;"))),
             factory.createString("get"));
+    DexMethod getVolatileLong =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(factory.longType, factory.objectType),
+            factory.createString("getVolatile"));
+    DexMethod getVolatileArray =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(factory.objectType, factory.objectType, factory.intType),
+            factory.createString("getVolatile"));
     DexMethod get =
         factory.createMethod(
             builder.getType(),
             factory.createProto(factory.objectType, factory.objectType),
             factory.createString("get"));
+    DexMethod getVolatileInBox =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.objectType,
+                factory.objectType,
+                factory.createType(factory.createString("Ljava/lang/Class;"))),
+            factory.createString("getVolatile"));
     DexMethod compareAndSetArrayInt =
         factory.createMethod(
             builder.getType(),
@@ -239,6 +274,11 @@
                 factory.createType(factory.createString("Ljava/lang/String;")),
                 factory.createType(factory.createString("Ljava/lang/Class;"))),
             factory.createString("<init>"));
+    DexMethod getVolatile =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(factory.objectType, factory.objectType),
+            factory.createString("getVolatile"));
     DexMethod arrayRequiringNativeSupport =
         factory.createMethod(
             builder.getType(),
@@ -301,6 +341,15 @@
             builder.getType(),
             factory.createProto(factory.objectType, factory.objectType, factory.intType),
             factory.createString("get"));
+    DexMethod getVolatileArrayInBox =
+        factory.createMethod(
+            builder.getType(),
+            factory.createProto(
+                factory.objectType,
+                factory.objectType,
+                factory.intType,
+                factory.createType(factory.createString("Ljava/lang/Class;"))),
+            factory.createString("getVolatile"));
     builder.setDirectMethods(
         ImmutableList.of(
             DexEncodedMethod.syntheticBuilder()
@@ -322,6 +371,22 @@
     builder.setVirtualMethods(
         ImmutableList.of(
             DexEncodedMethod.syntheticBuilder()
+                .setMethod(getVolatileArrayLong)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getVolatileArrayLong(factory, getVolatileArrayLong))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(getVolatileArrayInt)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getVolatileArrayInt(factory, getVolatileArrayInt))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
                 .setMethod(toIntIfPossible)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
@@ -412,6 +477,14 @@
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
+                .setMethod(getVolatileInt)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getVolatileInt(factory, getVolatileInt))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
                 .setMethod(compareAndSetArrayLong)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
@@ -428,6 +501,22 @@
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
+                .setMethod(getVolatileLong)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getVolatileLong(factory, getVolatileLong))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(getVolatileArray)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getVolatileArray(factory, getVolatileArray))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
                 .setMethod(get)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
@@ -436,6 +525,14 @@
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
+                .setMethod(getVolatileInBox)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getVolatileInBox(factory, getVolatileInBox))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
                 .setMethod(compareAndSetArrayInt)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
@@ -452,6 +549,14 @@
                 .disableAndroidApiLevelCheck()
                 .build(),
             DexEncodedMethod.syntheticBuilder()
+                .setMethod(getVolatile)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getVolatile(factory, getVolatile))
+                .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
                 .setMethod(arrayRequiringNativeSupport)
                 .setAccessFlags(
                     MethodAccessFlags.fromSharedAccessFlags(
@@ -532,6 +637,14 @@
                         Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
                 .setCode(DesugarVarHandle_getArray(factory, getArray))
                 .disableAndroidApiLevelCheck()
+                .build(),
+            DexEncodedMethod.syntheticBuilder()
+                .setMethod(getVolatileArrayInBox)
+                .setAccessFlags(
+                    MethodAccessFlags.fromSharedAccessFlags(
+                        Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC, false))
+                .setCode(DesugarVarHandle_getVolatileArrayInBox(factory, getVolatileArrayInBox))
+                .disableAndroidApiLevelCheck()
                 .build()));
   }
 
@@ -3670,6 +3783,1227 @@
         ImmutableList.of());
   }
 
+  public static CfCode DesugarVarHandle_getVolatile(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        4,
+        2,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label2),
+            label1,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getIntVolatile")),
+                false),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.createType("Ljava/lang/Integer;"), factory.intType),
+                    factory.createString("valueOf")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label4),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.longType),
+                    factory.createString("getLongVolatile")),
+                false),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.createType("Ljava/lang/Long;"), factory.longType),
+                    factory.createString("valueOf")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label4,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.longType),
+                    factory.createString("getObjectVolatile")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label5),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getVolatileArray(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    CfLabel label6 = new CfLabel();
+    CfLabel label7 = new CfLabel();
+    CfLabel label8 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        6,
+        5,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("recv"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isArray")),
+                false),
+            new CfIf(If.Type.EQ, ValueType.INT, label1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("recv"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.classType),
+                    factory.createString("getClass")),
+                false),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label2),
+            label1,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType()
+                    })),
+            new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/UnsupportedOperationException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfLoad(ValueType.INT, 2),
+            new CfNumberConversion(NumericType.INT, NumericType.LONG),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("arrayIndexScale"))),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfStore(ValueType.LONG, 3),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label5),
+            label4,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.LONG, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getIntVolatile")),
+                false),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.createType("Ljava/lang/Integer;"), factory.intType),
+                    factory.createString("valueOf")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label5,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label7),
+            label6,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.LONG, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.longType),
+                    factory.createString("getLongVolatile")),
+                false),
+            new CfNumberConversion(NumericType.LONG, NumericType.INT),
+            new CfInvoke(
+                184,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.createType("Ljava/lang/Integer;"), factory.intType),
+                    factory.createString("valueOf")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label7,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.LONG, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.longType),
+                    factory.createString("getObjectVolatile")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label8),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getVolatileArrayInBox(
+      DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    CfLabel label6 = new CfLabel();
+    CfLabel label7 = new CfLabel();
+    CfLabel label8 = new CfLabel();
+    CfLabel label9 = new CfLabel();
+    CfLabel label10 = new CfLabel();
+    CfLabel label11 = new CfLabel();
+    CfLabel label12 = new CfLabel();
+    CfLabel label13 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        6,
+        7,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("recv"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.classType,
+                    factory.createProto(factory.booleanType),
+                    factory.createString("isArray")),
+                false),
+            new CfIf(If.Type.EQ, ValueType.INT, label1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("recv"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.objectType,
+                    factory.createProto(factory.classType),
+                    factory.createString("getClass")),
+                false),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label2),
+            label1,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/UnsupportedOperationException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfLoad(ValueType.INT, 2),
+            new CfNumberConversion(NumericType.INT, NumericType.LONG),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("arrayIndexScale"))),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfStore(ValueType.LONG, 4),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label5),
+            label4,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.LONG, 4),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getIntVolatile")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.intType, factory.classType),
+                    factory.createString("boxIntIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label5,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label7),
+            label6,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.LONG, 4),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.longType),
+                    factory.createString("getLongVolatile")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.longType, factory.classType),
+                    factory.createString("boxLongIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label7,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.longType(),
+                      FrameType.longHighType()
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.LONG, 4),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.longType),
+                    factory.createString("getObjectVolatile")),
+                false),
+            new CfStore(ValueType.OBJECT, 6),
+            label8,
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfInstanceOf(factory.createType("Ljava/lang/Integer;")),
+            new CfIf(If.Type.EQ, ValueType.INT, label10),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfConstClass(factory.createType("Ljava/lang/Integer;")),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label10),
+            label9,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfCheckCast(factory.createType("Ljava/lang/Integer;")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.createProto(factory.intType),
+                    factory.createString("intValue")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.intType, factory.classType),
+                    factory.createString("boxIntIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label10,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfInstanceOf(factory.createType("Ljava/lang/Long;")),
+            new CfIf(If.Type.EQ, ValueType.INT, label12),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfConstClass(factory.createType("Ljava/lang/Long;")),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label12),
+            label11,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfCheckCast(factory.createType("Ljava/lang/Long;")),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.createProto(factory.longType),
+                    factory.createString("longValue")),
+                false),
+            new CfLoad(ValueType.OBJECT, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.longType, factory.classType),
+                    factory.createString("boxLongIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label12,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2, 3, 4, 5, 6},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.intType(),
+                      FrameType.initializedNonNullReference(factory.classType),
+                      FrameType.longType(),
+                      FrameType.longHighType(),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 6),
+            new CfReturn(ValueType.OBJECT),
+            label13),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getVolatileArrayInt(
+      DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        6,
+        5,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("recv"))),
+            new CfConstClass(factory.intArrayType),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label2),
+            label1,
+            new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/UnsupportedOperationException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.intArrayType),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfLoad(ValueType.INT, 2),
+            new CfNumberConversion(NumericType.INT, NumericType.LONG),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("arrayIndexScale"))),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfStore(ValueType.LONG, 3),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.LONG, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getIntVolatile")),
+                false),
+            new CfReturn(ValueType.INT),
+            label4),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getVolatileArrayLong(
+      DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        6,
+        5,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("recv"))),
+            new CfConstClass(factory.longArrayType),
+            new CfIfCmp(If.Type.EQ, ValueType.OBJECT, label2),
+            label1,
+            new CfNew(factory.createType("Ljava/lang/UnsupportedOperationException;")),
+            new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+            new CfInvoke(
+                183,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/UnsupportedOperationException;"),
+                    factory.createProto(factory.voidType),
+                    factory.createString("<init>")),
+                false),
+            new CfThrow(),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.longArrayType),
+                      FrameType.intType()
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfLoad(ValueType.INT, 2),
+            new CfNumberConversion(NumericType.INT, NumericType.LONG),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("arrayIndexScale"))),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Mul, NumericType.LONG),
+            new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.LONG),
+            new CfStore(ValueType.LONG, 3),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.LONG, 3),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.longType),
+                    factory.createString("getLongVolatile")),
+                false),
+            new CfReturn(ValueType.LONG),
+            label4),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getVolatileInBox(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        5,
+        3,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label2),
+            label1,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getIntVolatile")),
+                false),
+            new CfLoad(ValueType.OBJECT, 2),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.intType, factory.classType),
+                    factory.createString("boxIntIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label4),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.longType),
+                    factory.createString("getLongVolatile")),
+                false),
+            new CfLoad(ValueType.OBJECT, 2),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.objectType, factory.longType, factory.classType),
+                    factory.createString("boxLongIfPossible")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label4,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1, 2},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType),
+                      FrameType.initializedNonNullReference(factory.classType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.longType),
+                    factory.createString("getObjectVolatile")),
+                false),
+            new CfReturn(ValueType.OBJECT),
+            label5),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getVolatileInt(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        5,
+        2,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label2),
+            label1,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getIntVolatile")),
+                false),
+            new CfReturn(ValueType.INT),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label4),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.createType("Ljava/lang/RuntimeException;")),
+                    factory.createString("desugarWrongMethodTypeException")),
+                false),
+            new CfThrow(),
+            label4,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.longType),
+                    factory.createString("getObjectVolatile")),
+                false),
+            new CfConstNumber(1, ValueType.INT),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.booleanType),
+                    factory.createString("toIntIfPossible")),
+                false),
+            new CfReturn(ValueType.INT),
+            label5),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
+  public static CfCode DesugarVarHandle_getVolatileLong(DexItemFactory factory, DexMethod method) {
+    CfLabel label0 = new CfLabel();
+    CfLabel label1 = new CfLabel();
+    CfLabel label2 = new CfLabel();
+    CfLabel label3 = new CfLabel();
+    CfLabel label4 = new CfLabel();
+    CfLabel label5 = new CfLabel();
+    return new CfCode(
+        method.holder,
+        5,
+        2,
+        ImmutableList.of(
+            label0,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Long;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label2),
+            label1,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.longType),
+                    factory.createString("getLongVolatile")),
+                false),
+            new CfReturn(ValueType.LONG),
+            label2,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.classType,
+                    factory.createString("type"))),
+            new CfStaticFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/Integer;"),
+                    factory.classType,
+                    factory.createString("TYPE"))),
+            new CfIfCmp(If.Type.NE, ValueType.OBJECT, label4),
+            label3,
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.intType, factory.objectType, factory.longType),
+                    factory.createString("getIntVolatile")),
+                false),
+            new CfNumberConversion(NumericType.INT, NumericType.LONG),
+            new CfReturn(ValueType.LONG),
+            label4,
+            new CfFrame(
+                new Int2ObjectAVLTreeMap<>(
+                    new int[] {0, 1},
+                    new FrameType[] {
+                      FrameType.initializedNonNullReference(
+                          factory.createType("Ljava/lang/invoke/VarHandle;")),
+                      FrameType.initializedNonNullReference(factory.objectType)
+                    })),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createString("U"))),
+            new CfLoad(ValueType.OBJECT, 1),
+            new CfLoad(ValueType.OBJECT, 0),
+            new CfInstanceFieldRead(
+                factory.createField(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.longType,
+                    factory.createString("offset"))),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Lsun/misc/Unsafe;"),
+                    factory.createProto(factory.objectType, factory.objectType, factory.longType),
+                    factory.createString("getObjectVolatile")),
+                false),
+            new CfConstNumber(1, ValueType.INT),
+            new CfInvoke(
+                182,
+                factory.createMethod(
+                    factory.createType("Ljava/lang/invoke/VarHandle;"),
+                    factory.createProto(factory.longType, factory.objectType, factory.booleanType),
+                    factory.createString("toLongIfPossible")),
+                false),
+            new CfReturn(ValueType.LONG),
+            label5),
+        ImmutableList.of(),
+        ImmutableList.of());
+  }
+
   public static CfCode DesugarVarHandle_set(DexItemFactory factory, DexMethod method) {
     CfLabel label0 = new CfLabel();
     CfLabel label1 = new CfLabel();
diff --git a/src/test/examplesJava9/varhandle/ArrayOfInt.java b/src/test/examplesJava9/varhandle/ArrayOfInt.java
index c63f79d..f3eaf8a 100644
--- a/src/test/examplesJava9/varhandle/ArrayOfInt.java
+++ b/src/test/examplesJava9/varhandle/ArrayOfInt.java
@@ -98,6 +98,88 @@
     }
   }
 
+  public static void testGetVolatile() {
+    System.out.println("testGetVolatile");
+    VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(int[].class);
+    int[] array = new int[2];
+
+    arrayVarHandle.set(array, 0, 1);
+    arrayVarHandle.set(array, 1, 2);
+
+    System.out.println(arrayVarHandle.getVolatile(array, 0));
+    System.out.println(arrayVarHandle.getVolatile(array, 1));
+    System.out.println((Object) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((Object) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((int) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((int) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((long) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((long) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((float) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((float) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((double) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((double) arrayVarHandle.getVolatile(array, 1));
+    try {
+      System.out.println((boolean) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((boolean) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
   public static void testSet() {
     System.out.println("testSet");
 
@@ -273,6 +355,7 @@
 
   public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
     testGet();
+    testGetVolatile();
     testSet();
     testArrayVarHandleForNonSingleDimension();
   }
diff --git a/src/test/examplesJava9/varhandle/ArrayOfLong.java b/src/test/examplesJava9/varhandle/ArrayOfLong.java
index c909319..bd6a735 100644
--- a/src/test/examplesJava9/varhandle/ArrayOfLong.java
+++ b/src/test/examplesJava9/varhandle/ArrayOfLong.java
@@ -108,6 +108,98 @@
     }
   }
 
+  public static void testGetVolatile() {
+    System.out.println("testGetVolatile");
+    VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(long[].class);
+    long[] array = new long[2];
+
+    arrayVarHandle.set(array, 0, 1L);
+    arrayVarHandle.set(array, 1, 2L);
+
+    System.out.println(arrayVarHandle.getVolatile(array, 0));
+    System.out.println(arrayVarHandle.getVolatile(array, 1));
+    System.out.println((Object) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((Object) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((long) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((long) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((float) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((float) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((double) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((double) arrayVarHandle.getVolatile(array, 1));
+    try {
+      System.out.println((boolean) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((boolean) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((int) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((int) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
   public static void testSet() {
     System.out.println("testSet");
 
@@ -260,6 +352,7 @@
 
   public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
     testGet();
+    testGetVolatile();
     testSet();
     testArrayVarHandleForNonSingleDimension();
   }
diff --git a/src/test/examplesJava9/varhandle/ArrayOfObject.java b/src/test/examplesJava9/varhandle/ArrayOfObject.java
index ab9a6bd..508b740 100644
--- a/src/test/examplesJava9/varhandle/ArrayOfObject.java
+++ b/src/test/examplesJava9/varhandle/ArrayOfObject.java
@@ -166,6 +166,143 @@
     }
   }
 
+  public static void unsupportedGetVolatileConversion(VarHandle arrayVarHandle, Object[] array) {
+    try {
+      System.out.println((boolean) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((boolean) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
+  public static void testGetVolatile() {
+    System.out.println("testGetVolatile");
+    VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(Object[].class);
+    Object[] array = new Object[2];
+
+    arrayVarHandle.set(array, 0, 1);
+    arrayVarHandle.set(array, 1, 2);
+
+    System.out.println(arrayVarHandle.getVolatile(array, 0));
+    System.out.println(arrayVarHandle.getVolatile(array, 1));
+    System.out.println((Object) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((Object) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((int) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((int) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((long) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((long) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((float) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((float) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((double) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((double) arrayVarHandle.getVolatile(array, 1));
+    unsupportedGetVolatileConversion(arrayVarHandle, array);
+
+    arrayVarHandle.set(array, 0, 3L);
+    arrayVarHandle.set(array, 1, 4L);
+
+    System.out.println(arrayVarHandle.getVolatile(array, 0));
+    System.out.println(arrayVarHandle.getVolatile(array, 1));
+    System.out.println((Object) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((Object) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((long) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((long) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((float) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((float) arrayVarHandle.getVolatile(array, 1));
+    System.out.println((double) arrayVarHandle.getVolatile(array, 0));
+    System.out.println((double) arrayVarHandle.getVolatile(array, 1));
+    unsupportedGetVolatileConversion(arrayVarHandle, array);
+    try {
+      System.out.println((int) arrayVarHandle.getVolatile(array, 0));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((int) arrayVarHandle.getVolatile(array, 1));
+      System.out.println("Unexpected success");
+    } catch (ClassCastException e) {
+      // The reference implementation throws ClassCastException.
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
   public static void testSet() {
     System.out.println("testSet");
 
@@ -366,6 +503,7 @@
 
   public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
     testGet();
+    testGetVolatile();
     testSet();
     testCompareAndSet();
     testArrayVarHandleForNonSingleDimension();
diff --git a/src/test/examplesJava9/varhandle/InstanceIntField.java b/src/test/examplesJava9/varhandle/InstanceIntField.java
index aeadbcc..3b4edfb 100644
--- a/src/test/examplesJava9/varhandle/InstanceIntField.java
+++ b/src/test/examplesJava9/varhandle/InstanceIntField.java
@@ -62,6 +62,50 @@
     }
   }
 
+  public static void testGetVolatile(VarHandle varHandle) {
+    System.out.println("testGetVolatile");
+
+    InstanceIntField instance = new InstanceIntField();
+    varHandle.set(instance, 1);
+
+    System.out.println(varHandle.getVolatile(instance));
+    System.out.println((Object) varHandle.getVolatile(instance));
+    System.out.println((int) varHandle.getVolatile(instance));
+    System.out.println((long) varHandle.getVolatile(instance));
+    System.out.println((float) varHandle.getVolatile(instance));
+    System.out.println((double) varHandle.getVolatile(instance));
+    try {
+      System.out.println((boolean) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
   public static void testSet(VarHandle varHandle) {
     System.out.println("testSet");
 
@@ -262,6 +306,7 @@
     VarHandle varHandle =
         MethodHandles.lookup().findVarHandle(InstanceIntField.class, "field", int.class);
     testGet(varHandle);
+    testGetVolatile(varHandle);
     testSet(varHandle);
     testCompareAndSet(varHandle);
   }
diff --git a/src/test/examplesJava9/varhandle/InstanceLongField.java b/src/test/examplesJava9/varhandle/InstanceLongField.java
index b23e692..484ed87 100644
--- a/src/test/examplesJava9/varhandle/InstanceLongField.java
+++ b/src/test/examplesJava9/varhandle/InstanceLongField.java
@@ -67,6 +67,55 @@
     }
   }
 
+  public static void testGetVolatile(VarHandle varHandle) {
+    System.out.println("testGetVolatile");
+
+    InstanceLongField instance = new InstanceLongField();
+    varHandle.set(instance, 1);
+
+    System.out.println(varHandle.getVolatile(instance));
+    System.out.println((Object) varHandle.getVolatile(instance));
+    System.out.println((long) varHandle.getVolatile(instance));
+    System.out.println((float) varHandle.getVolatile(instance));
+    System.out.println((double) varHandle.getVolatile(instance));
+    try {
+      System.out.println((boolean) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((byte) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((short) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((char) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((int) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+    try {
+      System.out.println((String) varHandle.getVolatile(instance));
+      System.out.println("Unexpected success");
+    } catch (RuntimeException e) {
+      checkJavaLangInvokeWrongMethodTypeException(e);
+    }
+  }
+
   public static void testSet(VarHandle varHandle) {
     System.out.println("testSet");
 
@@ -237,6 +286,7 @@
     VarHandle varHandle =
         MethodHandles.lookup().findVarHandle(InstanceLongField.class, "field", long.class);
     testGet(varHandle);
+    testGetVolatile(varHandle);
     testSet(varHandle);
     testCompareAndSet(varHandle);
   }
diff --git a/src/test/examplesJava9/varhandle/InstanceObjectField.java b/src/test/examplesJava9/varhandle/InstanceObjectField.java
index c951ed8..bd17d04 100644
--- a/src/test/examplesJava9/varhandle/InstanceObjectField.java
+++ b/src/test/examplesJava9/varhandle/InstanceObjectField.java
@@ -24,8 +24,8 @@
     }
   }
 
-  public static void testSet(VarHandle varHandle) {
-    System.out.println("testSet");
+  public static void testSetGet(VarHandle varHandle) {
+    System.out.println("testSetGet");
 
     InstanceObjectField instance = new InstanceObjectField();
 
@@ -161,6 +161,143 @@
     }
   }
 
+  public static void testSetGetVolatile(VarHandle varHandle) {
+    System.out.println("testSetGetVolatile");
+
+    InstanceObjectField instance = new InstanceObjectField();
+
+    System.out.println(varHandle.getVolatile(instance));
+    A a1 = new A(1);
+    varHandle.set(instance, a1);
+    System.out.println(varHandle.getVolatile(instance));
+    System.out.println(varHandle.getVolatile(instance) == a1);
+    A a2 = new A(2);
+    varHandle.set(instance, a2);
+    System.out.println(varHandle.getVolatile(instance));
+    System.out.println(varHandle.getVolatile(instance) == a2);
+
+    Object o;
+    {
+      int i;
+      varHandle.set(instance, 1);
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((int) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Integer);
+      i = (int) varHandle.getVolatile(instance);
+      System.out.println(i == 1);
+      varHandle.set(instance, Integer.valueOf(2));
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((int) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Integer);
+      i = (int) varHandle.getVolatile(instance);
+      System.out.println(i == 2);
+    }
+    {
+      long l;
+      varHandle.set(instance, 3L);
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((long) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Long);
+      l = (long) varHandle.getVolatile(instance);
+      System.out.println(l == 3L);
+      varHandle.set(instance, Long.valueOf(4L));
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((long) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Long);
+      l = (long) varHandle.getVolatile(instance);
+      System.out.println(l == 4L);
+    }
+    {
+      byte b;
+      varHandle.set(instance, (byte) 5);
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((byte) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Byte);
+      b = (byte) varHandle.getVolatile(instance);
+      System.out.println(b == (byte) 5);
+      varHandle.set(instance, Byte.valueOf((byte) 6));
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((byte) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Byte);
+      b = (byte) varHandle.getVolatile(instance);
+      System.out.println(b == 6);
+    }
+    {
+      short s;
+      varHandle.set(instance, (short) 7);
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((short) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Short);
+      s = (short) varHandle.getVolatile(instance);
+      System.out.println(s == (short) 7);
+      varHandle.set(instance, Short.valueOf((short) 8));
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((short) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Short);
+      s = (short) varHandle.getVolatile(instance);
+      System.out.println(s == 8);
+    }
+    {
+      float f;
+      varHandle.set(instance, (float) 9.0f);
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((float) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Float);
+      f = (float) varHandle.getVolatile(instance);
+      System.out.println(f == (float) 9.0f);
+      varHandle.set(instance, Float.valueOf(10.0f));
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((float) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Float);
+      f = (float) varHandle.getVolatile(instance);
+      System.out.println(f == 10.0f);
+    }
+    {
+      double d;
+      varHandle.set(instance, (double) 11.0);
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((double) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Double);
+      d = (double) varHandle.getVolatile(instance);
+      System.out.println(d == (double) 11.0);
+      varHandle.set(instance, Double.valueOf(12.0));
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((double) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Double);
+      d = (double) varHandle.getVolatile(instance);
+      System.out.println(d == 12.0);
+    }
+    {
+      char c;
+      varHandle.set(instance, 'A');
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((char) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Character);
+      c = (char) varHandle.getVolatile(instance);
+      System.out.println(c == 'A');
+      varHandle.set(instance, Character.valueOf('B'));
+      System.out.println(varHandle.getVolatile(instance));
+      System.out.println((char) varHandle.getVolatile(instance));
+      o = varHandle.getVolatile(instance);
+      System.out.println(o instanceof Character);
+      c = (char) varHandle.getVolatile(instance);
+      System.out.println(c == 'B');
+    }
+  }
+
   public static void testCompareAndSet(VarHandle varHandle) {
     System.out.println("testCompareAndSet");
 
@@ -271,7 +408,8 @@
   public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
     VarHandle varHandle =
         MethodHandles.lookup().findVarHandle(InstanceObjectField.class, "field", Object.class);
-    testSet(varHandle);
+    testSetGet(varHandle);
+    testSetGetVolatile(varHandle);
     testCompareAndSet(varHandle);
     testReturnValueClassCastException(varHandle);
   }
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfIntTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfIntTest.java
index db63206..42815bc 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfIntTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfIntTest.java
@@ -29,6 +29,19 @@
           "2.0",
           "1.0",
           "2.0",
+          "testGetVolatile",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1.0",
+          "2.0",
+          "1.0",
+          "2.0",
           "testSet",
           "1",
           "0",
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfLongTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfLongTest.java
index 3867f1c..84ad4f4 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfLongTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfLongTest.java
@@ -27,6 +27,17 @@
           "2.0",
           "1.0",
           "2.0",
+          "testGetVolatile",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1.0",
+          "2.0",
+          "1.0",
+          "2.0",
           "testSet",
           "1",
           "0",
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfObjectTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfObjectTest.java
index 72439ec..e274fa0 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfObjectTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringArrayOfObjectTest.java
@@ -39,6 +39,29 @@
           "4.0",
           "3.0",
           "4.0",
+          "testGetVolatile",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1",
+          "2",
+          "1.0",
+          "2.0",
+          "1.0",
+          "2.0",
+          "3",
+          "4",
+          "3",
+          "4",
+          "3",
+          "4",
+          "3.0",
+          "4.0",
+          "3.0",
+          "4.0",
           "testSet",
           "5",
           "5",
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java
index 9de4722..fc84aaa 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceIntFieldTest.java
@@ -23,6 +23,13 @@
           "1",
           "1.0",
           "1.0",
+          "testGetVolatile",
+          "1",
+          "1",
+          "1",
+          "1",
+          "1.0",
+          "1.0",
           "testSet",
           "0",
           "1",
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceLongFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceLongFieldTest.java
index 5d98458..a471568 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceLongFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceLongFieldTest.java
@@ -22,6 +22,12 @@
           "1",
           "1.0",
           "1.0",
+          "testGetVolatile",
+          "1",
+          "1",
+          "1",
+          "1.0",
+          "1.0",
           "testSet",
           "0",
           "1",
diff --git a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java
index 6e76df9..4491944 100644
--- a/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java
+++ b/src/test/java/com/android/tools/r8/cf/varhandle/VarHandleDesugaringInstanceObjectFieldTest.java
@@ -16,7 +16,69 @@
 
   private static final String EXPECTED_OUTPUT =
       StringUtils.lines(
-          "testSet",
+          "testSetGet",
+          "null",
+          "A(1)",
+          "true",
+          "A(2)",
+          "true",
+          "1",
+          "1",
+          "true",
+          "true",
+          "2",
+          "2",
+          "true",
+          "true",
+          "3",
+          "3",
+          "true",
+          "true",
+          "4",
+          "4",
+          "true",
+          "true",
+          "5",
+          "5",
+          "true",
+          "true",
+          "6",
+          "6",
+          "true",
+          "true",
+          "7",
+          "7",
+          "true",
+          "true",
+          "8",
+          "8",
+          "true",
+          "true",
+          "9.0",
+          "9.0",
+          "true",
+          "true",
+          "10.0",
+          "10.0",
+          "true",
+          "true",
+          "11.0",
+          "11.0",
+          "true",
+          "true",
+          "12.0",
+          "12.0",
+          "true",
+          "true",
+          "A",
+          "A",
+          "true",
+          "true",
+          "B",
+          "B",
+          "true",
+          "true",
+          "testSetGetVolatile",
           "null",
           "A(1)",
           "true",
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java
index f352e1a..8a66a75 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/DesugarVarHandle.java
@@ -57,6 +57,14 @@
       throw new RuntimeException("Stub called.");
     }
 
+    public long getLongVolatile(Object obj, long offset) {
+      throw new RuntimeException("Stub called.");
+    }
+
+    public Object getObjectVolatile(Object obj, long offset) {
+      throw new RuntimeException("Stub called.");
+    }
+
     public int arrayBaseOffset(Class<?> clazz) {
       throw new RuntimeException("Stub called.");
     }
@@ -250,6 +258,47 @@
     }
   }
 
+  // getVolatile variants.
+  Object getVolatile(Object ct1) {
+    if (type == int.class) {
+      return U.getIntVolatile(ct1, offset);
+    }
+    if (type == long.class) {
+      return U.getLongVolatile(ct1, offset);
+    }
+    return U.getObjectVolatile(ct1, offset);
+  }
+
+  Object getVolatileInBox(Object ct1, Class<?> expectedBox) {
+    if (type == int.class) {
+      return boxIntIfPossible(U.getIntVolatile(ct1, offset), expectedBox);
+    }
+    if (type == long.class) {
+      return boxLongIfPossible(U.getLongVolatile(ct1, offset), expectedBox);
+    }
+    return U.getObjectVolatile(ct1, offset);
+  }
+
+  int getVolatileInt(Object ct1) {
+    if (type == int.class) {
+      return U.getIntVolatile(ct1, offset);
+    } else if (type == long.class) {
+      throw desugarWrongMethodTypeException();
+    } else {
+      return toIntIfPossible(U.getObjectVolatile(ct1, offset), true);
+    }
+  }
+
+  long getVolatileLong(Object ct1) {
+    if (type == long.class) {
+      return U.getLongVolatile(ct1, offset);
+    } else if (type == int.class) {
+      return U.getIntVolatile(ct1, offset);
+    } else {
+      return toLongIfPossible(U.getObjectVolatile(ct1, offset), true);
+    }
+  }
+
   boolean compareAndSet(Object ct1, Object expectedValue, Object newValue) {
     if (type == int.class) {
       return U.compareAndSwapInt(
@@ -331,7 +380,59 @@
     return U.getLong(ct1, elementOffset);
   }
 
-  // get array variants.
+  // getVolatile array variants.
+  Object getVolatileArray(Object ct1, int ct2) {
+    if (!recv.isArray() || recv != ct1.getClass()) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    if (type == int.class) {
+      return U.getIntVolatile(ct1, elementOffset);
+    } else if (type == long.class) {
+      return (int) U.getLongVolatile(ct1, elementOffset);
+    } else {
+      return U.getObjectVolatile(ct1, elementOffset);
+    }
+  }
+
+  Object getVolatileArrayInBox(Object ct1, int ct2, Class<?> expectedBox) {
+    if (!recv.isArray() || recv != ct1.getClass()) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    if (type == int.class) {
+      return boxIntIfPossible(U.getIntVolatile(ct1, elementOffset), expectedBox);
+    } else if (type == long.class) {
+      return boxLongIfPossible(U.getLongVolatile(ct1, elementOffset), expectedBox);
+    } else {
+      Object value = U.getObjectVolatile(ct1, elementOffset);
+      if (value instanceof Integer && expectedBox != Integer.class) {
+        return boxIntIfPossible(((Integer) value).intValue(), expectedBox);
+      }
+      if (value instanceof Long && expectedBox != Long.class) {
+        return boxLongIfPossible(((Long) value).longValue(), expectedBox);
+      }
+      return value;
+    }
+  }
+
+  int getVolatileArrayInt(int[] ct1, int ct2) {
+    if (recv != int[].class) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    return U.getIntVolatile(ct1, elementOffset);
+  }
+
+  long getVolatileArrayLong(long[] ct1, int ct2) {
+    if (recv != long[].class) {
+      throw new UnsupportedOperationException();
+    }
+    long elementOffset = offset + ((long) ct2) * arrayIndexScale;
+    return U.getLongVolatile(ct1, elementOffset);
+  }
+
+  // set array variants.
   void setArray(Object ct1, int ct2, Object newValue) {
     if (!recv.isArray() || recv != ct1.getClass()) {
       throw new UnsupportedOperationException();
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/GenerateVarHandleMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/GenerateVarHandleMethods.java
index 638b3e9..3fb1d92 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/varhandle/GenerateVarHandleMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/varhandle/GenerateVarHandleMethods.java
@@ -229,7 +229,7 @@
   private static String mapMethodName(String name) {
     Set<String> postfixes =
         ImmutableSet.of("InBox", "Int", "Long", "Array", "ArrayInBox", "ArrayInt", "ArrayLong");
-    for (String prefix : ImmutableList.of("get", "set", "compareAndSet")) {
+    for (String prefix : ImmutableList.of("get", "set", "compareAndSet", "getVolatile")) {
       if (name.startsWith(prefix)) {
         String postfix = name.substring(prefix.length());
         if (postfixes.contains(postfix)) {