Merge commit '51b015b7c4d252305d76a5c8beddf9e57bc02ef9' into dev-release

Change-Id: Ia1164268c10ecdb2c5f5d26ac86130497dda48d1
diff --git a/src/main/java/com/android/tools/r8/ArchiveClassFileProvider.java b/src/main/java/com/android/tools/r8/ArchiveClassFileProvider.java
index d3ee009..392a4bb 100644
--- a/src/main/java/com/android/tools/r8/ArchiveClassFileProvider.java
+++ b/src/main/java/com/android/tools/r8/ArchiveClassFileProvider.java
@@ -19,6 +19,7 @@
 import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UncheckedIOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
@@ -116,7 +117,7 @@
       if (!Files.exists(archive)) {
         throw new NoSuchFileException(archive.toString());
       } else {
-        throw e;
+        throw new UncheckedIOException(archive.toString(), e);
       }
     }
     lazyDescriptors = new HashSet<>();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 131ec35..178aa89 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -1804,41 +1804,41 @@
 
       // android.os.Build$VERSION_CODES_FULL
       Object[][] versionCodesFull = {
-        {"BASE", 10_000},
-        {"BASE_1_1", 20_000},
-        {"CUPCAKE", 30_000},
-        {"DONUT", 40_000},
-        {"ECLAIR", 50_000},
-        {"ECLAIR_0_1", 60_000},
-        {"ECLAIR_MR1", 70_000},
-        {"FROYO", 80_000},
-        {"GINGERBREAD", 90_000},
-        {"GINGERBREAD_MR1", 100_000},
-        {"HONEYCOMB", 110_000},
-        {"HONEYCOMB_MR1", 120_000},
-        {"HONEYCOMB_MR2", 130_000},
-        {"ICE_CREAM_SANDWICH", 140_000},
-        {"ICE_CREAM_SANDWICH_MR1", 150_000},
-        {"JELLY_BEAN", 160_000},
-        {"JELLY_BEAN_MR1", 170_000},
-        {"JELLY_BEAN_MR2", 180_000},
-        {"KITKAT", 190_000},
-        {"KITKAT_WATCH", 200_000},
-        {"LOLLIPOP", 210_000},
-        {"LOLLIPOP_MR1", 220_000},
-        {"M", 230_000},
-        {"N", 240_000},
-        {"N_MR1", 250_000},
-        {"O", 260_000},
-        {"O_MR1", 270_000},
-        {"P", 280_000},
-        {"Q", 290_000},
-        {"R", 300_000},
-        {"S", 310_000},
-        {"S_V2", 320_000},
-        {"TIRAMISU", 330_000},
-        {"UPSIDE_DOWN_CAKE", 340_000},
-        {"VANILLA_ICE_CREAM", 350_000},
+        {"BASE", 100_000},
+        {"BASE_1_1", 200_000},
+        {"CUPCAKE", 300_000},
+        {"DONUT", 400_000},
+        {"ECLAIR", 500_000},
+        {"ECLAIR_0_1", 600_000},
+        {"ECLAIR_MR1", 700_000},
+        {"FROYO", 800_000},
+        {"GINGERBREAD", 900_000},
+        {"GINGERBREAD_MR1", 1000_000},
+        {"HONEYCOMB", 1100_000},
+        {"HONEYCOMB_MR1", 1200_000},
+        {"HONEYCOMB_MR2", 1300_000},
+        {"ICE_CREAM_SANDWICH", 1400_000},
+        {"ICE_CREAM_SANDWICH_MR1", 1500_000},
+        {"JELLY_BEAN", 1600_000},
+        {"JELLY_BEAN_MR1", 1700_000},
+        {"JELLY_BEAN_MR2", 1800_000},
+        {"KITKAT", 1900_000},
+        {"KITKAT_WATCH", 2000_000},
+        {"LOLLIPOP", 2100_000},
+        {"LOLLIPOP_MR1", 2200_000},
+        {"M", 2300_000},
+        {"N", 2400_000},
+        {"N_MR1", 2500_000},
+        {"O", 2600_000},
+        {"O_MR1", 2700_000},
+        {"P", 2800_000},
+        {"Q", 2900_000},
+        {"R", 3000_000},
+        {"S", 3100_000},
+        {"S_V2", 3200_000},
+        {"TIRAMISU", 3300_000},
+        {"UPSIDE_DOWN_CAKE", 3400_000},
+        {"VANILLA_ICE_CREAM", 3500_000},
       };
       type = factory.createType("Landroid/os/Build$VERSION_CODES_FULL;");
       for (Object[] versionCodeFull : versionCodesFull) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
index 932bf0e..b562fbb 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.optimize;
 
+import static com.android.tools.r8.ir.regalloc.LiveIntervals.NO_REGISTER;
+
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.ir.code.BasicBlock;
@@ -231,13 +233,45 @@
   public static void shareIdenticalBlockSuffix(
       IRCode code, RegisterAllocator allocator, int overhead) {
     Collection<BasicBlock> blocks = code.blocks;
-    BasicBlock normalExit = null;
     List<BasicBlock> normalExits = code.computeNormalExitBlocks();
+    Set<BasicBlock> syntheticNormalExits = Sets.newIdentityHashSet();
     if (normalExits.size() > 1) {
-      normalExit = new BasicBlock(code.metadata());
-      normalExit.getMutablePredecessors().addAll(normalExits);
-      blocks = new ArrayList<>(code.blocks);
-      blocks.add(normalExit);
+      if (code.context().getReturnType().isVoidType()
+          || code.getConversionOptions().isGeneratingClassFiles()) {
+        BasicBlock syntheticNormalExit = new BasicBlock(code.metadata());
+        syntheticNormalExit.getMutablePredecessors().addAll(normalExits);
+        syntheticNormalExits.add(syntheticNormalExit);
+      } else {
+        Int2ReferenceMap<List<BasicBlock>> normalExitPartitioning =
+            new Int2ReferenceOpenHashMap<>();
+        for (BasicBlock block : normalExits) {
+          int returnRegister =
+              block
+                  .exit()
+                  .asReturn()
+                  .returnValue()
+                  .getLiveIntervals()
+                  .getSplitCovering(block.exit().getNumber())
+                  .getRegister();
+          assert returnRegister != NO_REGISTER;
+          List<BasicBlock> blocksWithReturnRegister;
+          if (normalExitPartitioning.containsKey(returnRegister)) {
+            blocksWithReturnRegister = normalExitPartitioning.get(returnRegister);
+          } else {
+            blocksWithReturnRegister = new ArrayList<>();
+            normalExitPartitioning.put(returnRegister, blocksWithReturnRegister);
+          }
+          blocksWithReturnRegister.add(block);
+        }
+        for (List<BasicBlock> blocksWithSameReturnRegister : normalExitPartitioning.values()) {
+          BasicBlock syntheticNormalExit = new BasicBlock(code.metadata());
+          syntheticNormalExit.getMutablePredecessors().addAll(blocksWithSameReturnRegister);
+          syntheticNormalExits.add(syntheticNormalExit);
+        }
+      }
+      blocks = new ArrayList<>(code.getBlocks().size() + syntheticNormalExits.size());
+      blocks.addAll(code.getBlocks());
+      blocks.addAll(syntheticNormalExits);
     }
     do {
       Map<BasicBlock, BasicBlock> newBlocks = new IdentityHashMap<>();
@@ -295,7 +329,7 @@
                   code,
                   commonSuffixSize,
                   predsWithSameLastInstruction,
-                  block == normalExit ? null : block,
+                  syntheticNormalExits.contains(block) ? null : block,
                   allocator);
           newBlocks.put(predsWithSameLastInstruction.get(0), newBlock);
         }
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index bc8b11b..ac612a7 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -367,6 +367,7 @@
     constrainArgumentIntervals();
     insertRangeInvokeMoves();
     ImmutableList<BasicBlock> blocks = computeLivenessInformation();
+    dedupCatchHandlerBlocks();
     timing.end();
     timing.begin("Allocate");
     performAllocation();
@@ -3428,6 +3429,77 @@
     code.blocks.forEach(BasicBlock::clearUserInfo);
   }
 
+  private void dedupCatchHandlerBlocks() {
+    List<BasicBlock> candidateBlocks = new ArrayList<>();
+    for (BasicBlock block : code.getBlocks()) {
+      if (block.hasUniquePredecessor()
+          && block.getUniquePredecessor().hasCatchSuccessor(block)
+          && liveAtEntrySets.get(block).isEmpty()
+          && block.size() <= 2) {
+        candidateBlocks.add(block);
+      }
+    }
+    if (candidateBlocks.isEmpty()) {
+      return;
+    }
+    Set<BasicBlock> removedBlocks = Sets.newIdentityHashSet();
+    for (BasicBlock candidateBlock : candidateBlocks) {
+      assert !removedBlocks.contains(candidateBlock);
+      BasicBlock equivalentBlock = null;
+      for (BasicBlock block : candidateBlocks) {
+        if (block == candidateBlock || removedBlocks.contains(block)) {
+          continue;
+        }
+        if (isEquivalentCatchHandlers(candidateBlock, block)) {
+          equivalentBlock = block;
+          break;
+        }
+      }
+      if (equivalentBlock == null) {
+        continue;
+      }
+      assert !candidateBlock.hasCatchHandlers();
+      removedBlocks.add(candidateBlock);
+      for (BasicBlock tryBlock : candidateBlock.getPredecessors()) {
+        tryBlock.replaceSuccessor(candidateBlock, equivalentBlock);
+        if (!equivalentBlock.getPredecessors().contains(tryBlock)) {
+          equivalentBlock.getMutablePredecessors().add(tryBlock);
+        }
+      }
+      for (BasicBlock successor : candidateBlock.getSuccessors()) {
+        int index = successor.getPredecessors().indexOf(candidateBlock);
+        successor.getMutablePredecessors().remove(index);
+        for (Phi phi : successor.getPhis()) {
+          phi.removeOperand(index);
+        }
+      }
+    }
+    code.removeBlocks(removedBlocks);
+  }
+
+  // TODO(b/153139043): Generalize this. Maybe use BasicBlock subsumption.
+  private boolean isEquivalentCatchHandlers(BasicBlock block, BasicBlock other) {
+    assert liveAtEntrySets.get(block).isEmpty();
+    assert liveAtEntrySets.get(other).isEmpty();
+    if (block.size() != other.size() || block.size() > 2) {
+      return false;
+    }
+    if (block.size() == 2) {
+      if (!block.entry().isMoveException() || !other.entry().isMoveException()) {
+        return false;
+      }
+    }
+    if (block.exit().isGoto()
+        && other.exit().isGoto()
+        && block.getUniqueNormalSuccessor() == other.getUniqueNormalSuccessor()) {
+      return true;
+    }
+    if (block.exit().isReturn() && other.exit().isReturn()) {
+      return true;
+    }
+    return false;
+  }
+
   // Rewrites casts on the form "lhs = (T) rhs" into "(T) rhs" and replaces the uses of lhs by rhs.
   // This transformation helps to ensure that we do not insert unnecessary moves in bridge methods
   // with an invoke-range instruction, since all the arguments to the invoke-range instruction will
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
index 165e520..945616f 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -43,7 +43,6 @@
     private boolean printMapping;
     private Path printMappingFile;
     private Path applyMappingFile;
-    private boolean verbose;
     private String renameSourceFileAttribute;
     private final List<String> keepAttributePatterns = new ArrayList<>();
     private final ProguardClassFilter.Builder keepPackageNamesPatterns =
@@ -183,10 +182,6 @@
       return applyMappingFile != null;
     }
 
-    public void setVerbose(boolean verbose) {
-      this.verbose = verbose;
-    }
-
     public void setRenameSourceFileAttribute(String renameSourceFileAttribute) {
       this.renameSourceFileAttribute = renameSourceFileAttribute;
     }
@@ -335,7 +330,6 @@
               printMapping,
               printMappingFile,
               applyMappingFile,
-              verbose,
               renameSourceFileAttribute,
               ProguardKeepAttributes.fromPatterns(keepAttributePatterns),
               keepPackageNamesPatterns.build(),
@@ -394,7 +388,6 @@
   private final boolean printMapping;
   private final Path printMappingFile;
   private final Path applyMappingFile;
-  private final boolean verbose;
   private final String renameSourceFileAttribute;
   private final ProguardKeepAttributes keepAttributes;
   private final ProguardClassFilter keepPackageNamesPatterns;
@@ -435,7 +428,6 @@
       boolean printMapping,
       Path printMappingFile,
       Path applyMappingFile,
-      boolean verbose,
       String renameSourceFileAttribute,
       ProguardKeepAttributes keepAttributes,
       ProguardClassFilter keepPackageNamesPatterns,
@@ -474,7 +466,6 @@
     this.printMapping = printMapping;
     this.printMappingFile = printMappingFile;
     this.applyMappingFile = applyMappingFile;
-    this.verbose = verbose;
     this.renameSourceFileAttribute = renameSourceFileAttribute;
     this.keepAttributes = keepAttributes;
     this.keepPackageNamesPatterns = keepPackageNamesPatterns;
@@ -581,10 +572,6 @@
     return printUsageFile;
   }
 
-  public boolean isVerbose() {
-    return verbose;
-  }
-
   public String getRenameSourceFileAttribute() {
     return renameSourceFileAttribute;
   }
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index 8c6aa57..95e0fde 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -84,7 +84,8 @@
           "allowruntypeandignoreoptimizationpasses",
           "dontshrinkduringoptimization",
           "convert_proto_enum_to_string",
-          "adaptkotlinmetadata");
+          "adaptkotlinmetadata",
+          "verbose");
 
   private static final List<String> IGNORED_CLASS_DESCRIPTOR_OPTIONS =
       ImmutableList.of("isclassnamestring", "whyarenotsimple");
@@ -364,8 +365,6 @@
         }
       } else if (acceptString("shrinkunusedprotofields")) {
         configurationBuilder.enableProtoShrinking();
-      } else if (acceptString("verbose")) {
-        configurationBuilder.setVerbose(true);
       } else if (acceptString("ignorewarnings")) {
         configurationBuilder.setIgnoreWarnings(true);
       } else if (acceptString("dontwarn")) {
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
index 4740a7c..1165be4 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
+++ b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
@@ -465,7 +465,8 @@
                 Entry entry = entryWrapper.getEntry();
                 int entryId = entryWrapper.getId();
                 recordSingleValueResources(resourceType, entry, entryId);
-                if (resourceType != ResourceType.STYLEABLE || includeStyleables) {
+                if (resourceType != null
+                    && (resourceType != ResourceType.STYLEABLE || includeStyleables)) {
                   this.addResource(
                       resourceType,
                       entryWrapper.getPackageName(),
diff --git a/src/test/examplesJava17/records/RecordBlogTest.java b/src/test/examplesJava17/records/RecordBlogTest.java
index 1128f07..37f1117 100644
--- a/src/test/examplesJava17/records/RecordBlogTest.java
+++ b/src/test/examplesJava17/records/RecordBlogTest.java
@@ -57,7 +57,7 @@
 
   private boolean isCfRuntimeWithNativeRecordSupport() {
     return parameters.isCfRuntime()
-        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK14)
+        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK17)
         && parameters.getApiLevel().equals(AndroidApiLevel.B);
   }
 
diff --git a/src/test/examplesJava17/records/RecordHashCodeManyFieldsTest.java b/src/test/examplesJava17/records/RecordHashCodeManyFieldsTest.java
index 6c2a31b..1cd7313 100644
--- a/src/test/examplesJava17/records/RecordHashCodeManyFieldsTest.java
+++ b/src/test/examplesJava17/records/RecordHashCodeManyFieldsTest.java
@@ -37,7 +37,7 @@
 
   private boolean isCfRuntimeWithNativeRecordSupport() {
     return parameters.isCfRuntime()
-        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK14)
+        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK17)
         && parameters.getApiLevel().equals(AndroidApiLevel.B);
   }
 
diff --git a/src/test/examplesJava17/records/RecordHashCodeTest.java b/src/test/examplesJava17/records/RecordHashCodeTest.java
index b0b0b0e..b5a21f4 100644
--- a/src/test/examplesJava17/records/RecordHashCodeTest.java
+++ b/src/test/examplesJava17/records/RecordHashCodeTest.java
@@ -37,7 +37,7 @@
 
   private boolean isCfRuntimeWithNativeRecordSupport() {
     return parameters.isCfRuntime()
-        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK14)
+        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK17)
         && parameters.getApiLevel().equals(AndroidApiLevel.B);
   }
 
diff --git a/src/test/examplesJava17/records/RecordInterfaceTest.java b/src/test/examplesJava17/records/RecordInterfaceTest.java
index d5144b0..583ccb4 100644
--- a/src/test/examplesJava17/records/RecordInterfaceTest.java
+++ b/src/test/examplesJava17/records/RecordInterfaceTest.java
@@ -48,7 +48,7 @@
 
   private boolean isCfRuntimeWithNativeRecordSupport() {
     return parameters.isCfRuntime()
-        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK14)
+        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK17)
         && parameters.getApiLevel().equals(AndroidApiLevel.B);
   }
 
diff --git a/src/test/examplesJava17/records/RecordInvokeCustomTest.java b/src/test/examplesJava17/records/RecordInvokeCustomTest.java
index ec3956a..55c9d9c 100644
--- a/src/test/examplesJava17/records/RecordInvokeCustomTest.java
+++ b/src/test/examplesJava17/records/RecordInvokeCustomTest.java
@@ -4,18 +4,17 @@
 
 package records;
 
+import com.android.tools.r8.JdkClassFileProvider;
 import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfRuntime;
 import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.desugar.LibraryFilesHelper;
 import com.android.tools.r8.utils.StringUtils;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
-import records.RecordInvokeCustom.Empty;
-import records.RecordInvokeCustom.Person;
 
 @RunWith(Parameterized.class)
 public class RecordInvokeCustomTest extends TestBase {
@@ -83,7 +82,9 @@
             .addKeepMainRule(RecordInvokeCustom.class);
     if (parameters.isCfRuntime()) {
       builder
-          .addLibraryFiles(LibraryFilesHelper.getJdk15LibraryFiles(temp))
+          .addLibraryProvider(
+              JdkClassFileProvider.fromSystemModulesJdk(
+                  CfRuntime.getCheckedInJdk17().getJavaHome()))
           .compile()
           .inspect(RecordTestUtils::assertRecordsAreRecords)
           .run(parameters.getRuntime(), RecordInvokeCustom.class)
diff --git a/src/test/examplesJava17/records/SimpleRecordTest.java b/src/test/examplesJava17/records/SimpleRecordTest.java
index d7c8131..cfedd02 100644
--- a/src/test/examplesJava17/records/SimpleRecordTest.java
+++ b/src/test/examplesJava17/records/SimpleRecordTest.java
@@ -47,7 +47,7 @@
 
   private boolean isCfRuntimeWithNativeRecordSupport() {
     return parameters.isCfRuntime()
-        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK14)
+        && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK17)
         && parameters.getApiLevel().equals(AndroidApiLevel.B);
   }
 
diff --git a/src/test/java/com/android/tools/r8/androidresources/SyntheticResourceTypeTest.java b/src/test/java/com/android/tools/r8/androidresources/SyntheticResourceTypeTest.java
new file mode 100644
index 0000000..39f81a6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/androidresources/SyntheticResourceTypeTest.java
@@ -0,0 +1,88 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.androidresources;
+
+import com.android.aapt.Resources.ResourceTable;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class SyntheticResourceTypeTest extends TestBase {
+
+  @Parameter(0)
+  public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection parameters() {
+    return getTestParameters().withDefaultDexRuntime().withAllApiLevels().build();
+  }
+
+  public static AndroidTestResource getTestResources(TemporaryFolder temp) throws Exception {
+    return new AndroidTestResourceBuilder()
+        .withSimpleManifestAndAppNameString()
+        .addRClassInitializeWithDefaultValues(R.drawable.class)
+        .build(temp)
+        .mangleResourceTable(
+            resourceTable -> {
+              // We are adding a synthetic type that we can't easily get aapt2 to generate.
+              // Explicitly build the entry using the resource table builder.
+              ResourceTable.Builder resourceTableBuilder = resourceTable.toBuilder();
+              resourceTableBuilder
+                  .getPackageBuilderList()
+                  .get(0)
+                  .addTypeBuilder()
+                  .setName("macro")
+                  .addEntryBuilder()
+                  .setName("macro_name")
+                  .addConfigValueBuilder()
+                  .getValueBuilder()
+                  .getItemBuilder()
+                  .getStrBuilder()
+                  .setValue("macro_value")
+                  .build();
+              return resourceTableBuilder.build();
+            });
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .setMinApi(parameters)
+        .addProgramClasses(FooBar.class)
+        .addAndroidResources(getTestResources(temp))
+        .addKeepMainRule(FooBar.class)
+        .enableOptimizedShrinking()
+        .compile()
+        .inspectShrunkenResources(
+            resourceTableInspector -> {
+              resourceTableInspector.assertContainsResourceWithName("drawable", "foo");
+              // The synthetic macro entries should not be touched by the resource shrinker.
+              resourceTableInspector.assertContainsResourceWithName("macro", "macro_name");
+              resourceTableInspector.assertDoesNotContainResourceWithName("drawable", "bar");
+            });
+  }
+
+  public static class FooBar {
+    public static void main(String[] args) {
+      System.out.println(R.drawable.foo);
+    }
+  }
+
+  public static class R {
+    public static class drawable {
+      public static int foo;
+      public static int bar;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/AndroidOsBuildVersionCodesFullBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/AndroidOsBuildVersionCodesFullBackportTest.java
index 1c9e1a0..c5ca271 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/AndroidOsBuildVersionCodesFullBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/AndroidOsBuildVersionCodesFullBackportTest.java
@@ -13,9 +13,13 @@
 import com.android.tools.r8.transformers.ClassFileTransformer;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.lang.reflect.Field;
+import org.junit.Assert;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
@@ -85,85 +89,153 @@
         .transform();
   }
 
+  @Test
+  public void checkVersionCodesFullInAndroidJar() throws Exception {
+    ClassSubject versionCodesFullClass =
+        new CodeInspector(parameters.getDefaultAndroidJar())
+            .clazz("android.os.Build$VERSION_CODES_FULL");
+    Assert.assertFalse(versionCodesFullClass.isPresent());
+    // Update test when fully testing Android Baklava.
+    Assert.assertFalse(parameters.getApiLevel().equals(AndroidApiLevel.BAKLAVA));
+    if (parameters.getApiLevel().equals(AndroidApiLevel.V)) {
+      versionCodesFullClass =
+          new CodeInspector(ToolHelper.getAndroidJar(AndroidApiLevel.BAKLAVA))
+              .clazz("android.os.Build$VERSION_CODES_FULL");
+      Assert.assertTrue(versionCodesFullClass.isPresent());
+      // Update test when more version codes full are added.
+      Assert.assertEquals(35, versionCodesFullClass.allFields().size());
+      // Copied from BackportedMethodRewriter.
+      Object[][] versionCodesFull = {
+        {"BASE", 100_000},
+        {"BASE_1_1", 200_000},
+        {"CUPCAKE", 300_000},
+        {"DONUT", 400_000},
+        {"ECLAIR", 500_000},
+        {"ECLAIR_0_1", 600_000},
+        {"ECLAIR_MR1", 700_000},
+        {"FROYO", 800_000},
+        {"GINGERBREAD", 900_000},
+        {"GINGERBREAD_MR1", 1000_000},
+        {"HONEYCOMB", 1100_000},
+        {"HONEYCOMB_MR1", 1200_000},
+        {"HONEYCOMB_MR2", 1300_000},
+        {"ICE_CREAM_SANDWICH", 1400_000},
+        {"ICE_CREAM_SANDWICH_MR1", 1500_000},
+        {"JELLY_BEAN", 1600_000},
+        {"JELLY_BEAN_MR1", 1700_000},
+        {"JELLY_BEAN_MR2", 1800_000},
+        {"KITKAT", 1900_000},
+        {"KITKAT_WATCH", 2000_000},
+        {"LOLLIPOP", 2100_000},
+        {"LOLLIPOP_MR1", 2200_000},
+        {"M", 2300_000},
+        {"N", 2400_000},
+        {"N_MR1", 2500_000},
+        {"O", 2600_000},
+        {"O_MR1", 2700_000},
+        {"P", 2800_000},
+        {"Q", 2900_000},
+        {"R", 3000_000},
+        {"S", 3100_000},
+        {"S_V2", 3200_000},
+        {"TIRAMISU", 3300_000},
+        {"UPSIDE_DOWN_CAKE", 3400_000},
+        {"VANILLA_ICE_CREAM", 3500_000},
+      };
+      for (Object[] versionCodeFull : versionCodesFull) {
+        Assert.assertEquals(
+            ((Integer) versionCodeFull[1]).intValue(),
+            versionCodesFullClass
+                .field("int", (String) versionCodeFull[0])
+                .getField()
+                .getStaticValue()
+                .asDexValueInt()
+                .value);
+      }
+    }
+  }
+
   // android.os.Build$VERSION_CODES_FULL for building TestRunner and for runtime classpath.
-  // Fields are not final to insure that the static gets are not inlined by javac for the test code.
+  // Fields are not final to ensure that the static gets are not inlined by javac for the test code
+  // and the field values are not relevant, as desugaring will replace them with the proper
+  // constants.
   public static class /*android.os.Build$*/ VERSION_CODES_FULL {
 
-    public static /* final */ int BASE = 10_000;
-    public static /* final */ int BASE_1_1 = 20_000;
-    public static /* final */ int CUPCAKE = 30_000;
-    public static /* final */ int DONUT = 40_000;
-    public static /* final */ int ECLAIR = 50_000;
-    public static /* final */ int ECLAIR_0_1 = 60_000;
-    public static /* final */ int ECLAIR_MR1 = 70_000;
-    public static /* final */ int FROYO = 80_000;
-    public static /* final */ int GINGERBREAD = 90_000;
-    public static /* final */ int GINGERBREAD_MR1 = 100_000;
-    public static /* final */ int HONEYCOMB = 110_000;
-    public static /* final */ int HONEYCOMB_MR1 = 120_000;
-    public static /* final */ int HONEYCOMB_MR2 = 130_000;
-    public static /* final */ int ICE_CREAM_SANDWICH = 140_000;
-    public static /* final */ int ICE_CREAM_SANDWICH_MR1 = 150_000;
-    public static /* final */ int JELLY_BEAN = 160_000;
-    public static /* final */ int JELLY_BEAN_MR1 = 170_000;
-    public static /* final */ int JELLY_BEAN_MR2 = 180_000;
-    public static /* final */ int KITKAT = 190_000;
-    public static /* final */ int KITKAT_WATCH = 200_000;
-    public static /* final */ int LOLLIPOP = 210_000;
-    public static /* final */ int LOLLIPOP_MR1 = 220_000;
-    public static /* final */ int M = 230_000;
-    public static /* final */ int N = 240_000;
-    public static /* final */ int N_MR1 = 250_000;
-    public static /* final */ int O = 260_000;
-    public static /* final */ int O_MR1 = 270_000;
-    public static /* final */ int P = 280_000;
-    public static /* final */ int Q = 290_000;
-    public static /* final */ int R = 300_000;
-    public static /* final */ int S = 310_000;
-    public static /* final */ int S_V2 = 320_000;
-    public static /* final */ int TIRAMISU = 330_000;
-    public static /* final */ int UPSIDE_DOWN_CAKE = 340_000;
-    public static /* final */ int VANILLA_ICE_CREAM = 350_000;
+    public static /* final */ int BASE = -1;
+    public static /* final */ int BASE_1_1 = -1;
+    public static /* final */ int CUPCAKE = -1;
+    public static /* final */ int DONUT = -1;
+    public static /* final */ int ECLAIR = -1;
+    public static /* final */ int ECLAIR_0_1 = -1;
+    public static /* final */ int ECLAIR_MR1 = -1;
+    public static /* final */ int FROYO = -1;
+    public static /* final */ int GINGERBREAD = -1;
+    public static /* final */ int GINGERBREAD_MR1 = -1;
+    public static /* final */ int HONEYCOMB = -1;
+    public static /* final */ int HONEYCOMB_MR1 = -1;
+    public static /* final */ int HONEYCOMB_MR2 = -1;
+    public static /* final */ int ICE_CREAM_SANDWICH = -1;
+    public static /* final */ int ICE_CREAM_SANDWICH_MR1 = -1;
+    public static /* final */ int JELLY_BEAN = -1;
+    public static /* final */ int JELLY_BEAN_MR1 = -1;
+    public static /* final */ int JELLY_BEAN_MR2 = -1;
+    public static /* final */ int KITKAT = -1;
+    public static /* final */ int KITKAT_WATCH = -1;
+    public static /* final */ int LOLLIPOP = -1;
+    public static /* final */ int LOLLIPOP_MR1 = -1;
+    public static /* final */ int M = -1;
+    public static /* final */ int N = -1;
+    public static /* final */ int N_MR1 = -1;
+    public static /* final */ int O = -1;
+    public static /* final */ int O_MR1 = -1;
+    public static /* final */ int P = -1;
+    public static /* final */ int Q = -1;
+    public static /* final */ int R = -1;
+    public static /* final */ int S = -1;
+    public static /* final */ int S_V2 = -1;
+    public static /* final */ int TIRAMISU = -1;
+    public static /* final */ int UPSIDE_DOWN_CAKE = -1;
+    public static /* final */ int VANILLA_ICE_CREAM = -1;
   }
 
   public static class TestRunner extends MiniAssert {
 
     public static void main(String[] args) throws Exception {
-      assertEquals(10_000, VERSION_CODES_FULL.BASE);
-      assertEquals(20_000, VERSION_CODES_FULL.BASE_1_1);
-      assertEquals(30_000, VERSION_CODES_FULL.CUPCAKE);
-      assertEquals(40_000, VERSION_CODES_FULL.DONUT);
-      assertEquals(50_000, VERSION_CODES_FULL.ECLAIR);
-      assertEquals(60_000, VERSION_CODES_FULL.ECLAIR_0_1);
-      assertEquals(70_000, VERSION_CODES_FULL.ECLAIR_MR1);
-      assertEquals(80_000, VERSION_CODES_FULL.FROYO);
-      assertEquals(90_000, VERSION_CODES_FULL.GINGERBREAD);
-      assertEquals(100_000, VERSION_CODES_FULL.GINGERBREAD_MR1);
-      assertEquals(110_000, VERSION_CODES_FULL.HONEYCOMB);
-      assertEquals(120_000, VERSION_CODES_FULL.HONEYCOMB_MR1);
-      assertEquals(130_000, VERSION_CODES_FULL.HONEYCOMB_MR2);
-      assertEquals(140_000, VERSION_CODES_FULL.ICE_CREAM_SANDWICH);
-      assertEquals(150_000, VERSION_CODES_FULL.ICE_CREAM_SANDWICH_MR1);
-      assertEquals(160_000, VERSION_CODES_FULL.JELLY_BEAN);
-      assertEquals(170_000, VERSION_CODES_FULL.JELLY_BEAN_MR1);
-      assertEquals(180_000, VERSION_CODES_FULL.JELLY_BEAN_MR2);
-      assertEquals(190_000, VERSION_CODES_FULL.KITKAT);
-      assertEquals(200_000, VERSION_CODES_FULL.KITKAT_WATCH);
-      assertEquals(210_000, VERSION_CODES_FULL.LOLLIPOP);
-      assertEquals(220_000, VERSION_CODES_FULL.LOLLIPOP_MR1);
-      assertEquals(230_000, VERSION_CODES_FULL.M);
-      assertEquals(240_000, VERSION_CODES_FULL.N);
-      assertEquals(250_000, VERSION_CODES_FULL.N_MR1);
-      assertEquals(260_000, VERSION_CODES_FULL.O);
-      assertEquals(270_000, VERSION_CODES_FULL.O_MR1);
-      assertEquals(280_000, VERSION_CODES_FULL.P);
-      assertEquals(290_000, VERSION_CODES_FULL.Q);
-      assertEquals(300_000, VERSION_CODES_FULL.R);
-      assertEquals(310_000, VERSION_CODES_FULL.S);
-      assertEquals(320_000, VERSION_CODES_FULL.S_V2);
-      assertEquals(330_000, VERSION_CODES_FULL.TIRAMISU);
-      assertEquals(340_000, VERSION_CODES_FULL.UPSIDE_DOWN_CAKE);
-      assertEquals(350_000, VERSION_CODES_FULL.VANILLA_ICE_CREAM);
+      assertEquals(100_000, VERSION_CODES_FULL.BASE);
+      assertEquals(200_000, VERSION_CODES_FULL.BASE_1_1);
+      assertEquals(300_000, VERSION_CODES_FULL.CUPCAKE);
+      assertEquals(400_000, VERSION_CODES_FULL.DONUT);
+      assertEquals(500_000, VERSION_CODES_FULL.ECLAIR);
+      assertEquals(600_000, VERSION_CODES_FULL.ECLAIR_0_1);
+      assertEquals(700_000, VERSION_CODES_FULL.ECLAIR_MR1);
+      assertEquals(800_000, VERSION_CODES_FULL.FROYO);
+      assertEquals(900_000, VERSION_CODES_FULL.GINGERBREAD);
+      assertEquals(1000_000, VERSION_CODES_FULL.GINGERBREAD_MR1);
+      assertEquals(1100_000, VERSION_CODES_FULL.HONEYCOMB);
+      assertEquals(1200_000, VERSION_CODES_FULL.HONEYCOMB_MR1);
+      assertEquals(1300_000, VERSION_CODES_FULL.HONEYCOMB_MR2);
+      assertEquals(1400_000, VERSION_CODES_FULL.ICE_CREAM_SANDWICH);
+      assertEquals(1500_000, VERSION_CODES_FULL.ICE_CREAM_SANDWICH_MR1);
+      assertEquals(1600_000, VERSION_CODES_FULL.JELLY_BEAN);
+      assertEquals(1700_000, VERSION_CODES_FULL.JELLY_BEAN_MR1);
+      assertEquals(1800_000, VERSION_CODES_FULL.JELLY_BEAN_MR2);
+      assertEquals(1900_000, VERSION_CODES_FULL.KITKAT);
+      assertEquals(2000_000, VERSION_CODES_FULL.KITKAT_WATCH);
+      assertEquals(2100_000, VERSION_CODES_FULL.LOLLIPOP);
+      assertEquals(2200_000, VERSION_CODES_FULL.LOLLIPOP_MR1);
+      assertEquals(2300_000, VERSION_CODES_FULL.M);
+      assertEquals(2400_000, VERSION_CODES_FULL.N);
+      assertEquals(2500_000, VERSION_CODES_FULL.N_MR1);
+      assertEquals(2600_000, VERSION_CODES_FULL.O);
+      assertEquals(2700_000, VERSION_CODES_FULL.O_MR1);
+      assertEquals(2800_000, VERSION_CODES_FULL.P);
+      assertEquals(2900_000, VERSION_CODES_FULL.Q);
+      assertEquals(3000_000, VERSION_CODES_FULL.R);
+      assertEquals(3100_000, VERSION_CODES_FULL.S);
+      assertEquals(3200_000, VERSION_CODES_FULL.S_V2);
+      assertEquals(3300_000, VERSION_CODES_FULL.TIRAMISU);
+      assertEquals(3400_000, VERSION_CODES_FULL.UPSIDE_DOWN_CAKE);
+      assertEquals(3500_000, VERSION_CODES_FULL.VANILLA_ICE_CREAM);
     }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/CatchHandlerCoalescingAfterSplitReturnRewriterTest.java b/src/test/java/com/android/tools/r8/ir/optimize/CatchHandlerCoalescingAfterSplitReturnRewriterTest.java
index 6ea9c73..fa241ae 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/CatchHandlerCoalescingAfterSplitReturnRewriterTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/CatchHandlerCoalescingAfterSplitReturnRewriterTest.java
@@ -51,8 +51,7 @@
               assertThat(testMethodSubject, isPresent());
 
               DexCode code = testMethodSubject.getMethod().getCode().asDexCode();
-              // TODO(b/384848525): Should be 1.
-              assertEquals(forceSplitReturnRewriter ? 2 : 1, code.getTries().length);
+              assertEquals(1, code.getTries().length);
             });
   }
 
@@ -63,6 +62,7 @@
         doStuff();
         doStuff();
       } catch (Exception e) {
+        System.out.println(e);
         return e;
       }
       return null;
diff --git a/src/test/java/com/android/tools/r8/rewrite/JavaScriptScriptEngineTest.java b/src/test/java/com/android/tools/r8/rewrite/JavaScriptScriptEngineTest.java
index 241c2f3..4af8c94 100644
--- a/src/test/java/com/android/tools/r8/rewrite/JavaScriptScriptEngineTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/JavaScriptScriptEngineTest.java
@@ -85,7 +85,7 @@
         .run(parameters.getRuntime(), TestClass.class)
         .applyIf(
             // No default JS engine starting from JDK-14 where Nashorn was removed, see b/227162584.
-            parameters.isCfRuntime() && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK14),
+            parameters.isCfRuntime() && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK17),
             r -> r.assertFailureWithErrorThatThrows(NullPointerException.class),
             r ->
                 r.assertSuccessWithOutput(
diff --git a/src/test/java/com/android/tools/r8/rewrite/ScriptEngineTest.java b/src/test/java/com/android/tools/r8/rewrite/ScriptEngineTest.java
index a8e80aa..6865487 100644
--- a/src/test/java/com/android/tools/r8/rewrite/ScriptEngineTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/ScriptEngineTest.java
@@ -115,7 +115,7 @@
           parameters.isCfRuntime()
               // No default JS engine starting from JDK-14 where Nashorn was removed,
               // see b/227162584.
-              ? (parameters.isCfRuntime() && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK14)
+              ? (parameters.isCfRuntime() && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK17)
                   ? StringUtils.lines("MyEngine1", "MyEngine2")
                   : StringUtils.lines("MyEngine1", "MyEngine2", "Oracle Nashorn"))
               : StringUtils.lines("Mozilla Rhino", "MyEngine1", "MyEngine2"));
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index c94ce9c..ad664d3 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -1058,8 +1058,6 @@
         new ProguardConfigurationParser(new DexItemFactory(), reporter);
     parser.parse(Paths.get(VERBOSE));
     verifyParserEndsCleanly();
-    ProguardConfiguration config = parser.getConfig();
-    assertTrue(config.isVerbose());
   }
 
   @Test
diff --git a/src/test/testbase/java/com/android/tools/r8/TestRuntime.java b/src/test/testbase/java/com/android/tools/r8/TestRuntime.java
index f14cec1..889f7a3 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestRuntime.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestRuntime.java
@@ -35,11 +35,6 @@
     JDK9("jdk9", 53),
     JDK10("jdk10", 54),
     JDK11("jdk11", 55),
-    JDK12("jdk12", 56),
-    JDK13("jdk13", 57),
-    JDK14("jdk14", 58),
-    JDK15("jdk15", 59),
-    JDK16("jdk16", 60),
     JDK17("jdk17", 61),
     JDK18("jdk18", 62),
     JDK20("jdk20", 64),
diff --git a/src/test/testbase/java/com/android/tools/r8/androidresources/AndroidResourceTestingUtils.java b/src/test/testbase/java/com/android/tools/r8/androidresources/AndroidResourceTestingUtils.java
index 92e0618..d55db2f 100644
--- a/src/test/testbase/java/com/android/tools/r8/androidresources/AndroidResourceTestingUtils.java
+++ b/src/test/testbase/java/com/android/tools/r8/androidresources/AndroidResourceTestingUtils.java
@@ -32,6 +32,7 @@
 import java.lang.reflect.Field;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -42,6 +43,7 @@
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.TreeSet;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
@@ -175,7 +177,7 @@
 
   public static class AndroidTestResource {
     private final AndroidTestRClass rClass;
-    private final Path resourceZip;
+    private Path resourceZip;
     private final List<String> additionalKeepRuleFiles;
 
     AndroidTestResource(
@@ -185,6 +187,28 @@
       this.additionalKeepRuleFiles = additionalRawXmlFiles;
     }
 
+    public AndroidTestResource mangleResourceTable(Function<ResourceTable, ResourceTable> mapper)
+        throws IOException {
+      Path newName = Paths.get(resourceZip.toString() + ".mangled.ap_");
+      ZipUtils.map(
+          resourceZip,
+          newName,
+          (zipEntry, bytes) -> {
+            if (zipEntry.getName().equals("resources.pb")) {
+              try {
+                ResourceTable resourceTable = ResourceTable.parseFrom(bytes);
+                ResourceTable converted = mapper.apply(resourceTable);
+                return converted.toByteArray();
+              } catch (InvalidProtocolBufferException e) {
+                throw new RuntimeException(e);
+              }
+            }
+            return bytes;
+          });
+      resourceZip = newName;
+      return this;
+    }
+
     public AndroidTestRClass getRClass() {
       return rClass;
     }
diff --git a/src/test/testbase/java/com/android/tools/r8/desugar/LibraryFilesHelper.java b/src/test/testbase/java/com/android/tools/r8/desugar/LibraryFilesHelper.java
index 0a605cb..a618531 100644
--- a/src/test/testbase/java/com/android/tools/r8/desugar/LibraryFilesHelper.java
+++ b/src/test/testbase/java/com/android/tools/r8/desugar/LibraryFilesHelper.java
@@ -39,48 +39,6 @@
     return getJdk9LibraryFiles(temp);
   }
 
-  public static Path[] getJdk15LibraryFiles(TemporaryFolder temp) throws Exception {
-    // TODO(b/270105162): We should be able to run this on windows.
-    Assume.assumeFalse(ToolHelper.isWindows());
-    // TODO(b/169645628): Add JDK-15 runtime jar instead. As a temporary solution we use the jdk 8
-    //   runtime with additional stubs.
-    Path generatedJar = temp.newFolder().toPath().resolve("stubs.jar");
-    ZipBuilder builder = ZipBuilder.builder(generatedJar);
-    addRecord(builder);
-    addRecordComponent(builder);
-    addObjectsMethod(builder);
-    addTypeDescriptor(builder);
-    builder.build();
-    return ObjectArrays.concat(getJdk9LibraryFiles(temp), new Path[] {generatedJar}, Path.class);
-  }
-
-  // Generates a class file for:
-  // <pre>
-  // public class ObjectMethods {}
-  // </pre>
-  private static void addObjectsMethod(ZipBuilder builder) throws Exception {
-    addClassToZipBuilder(
-        builder, ACC_PUBLIC, "java/lang/runtime/ObjectMethods", ConsumerUtils.emptyConsumer());
-  }
-
-  // Generates a class file for:
-  // <pre>
-  // public interface TypeDescriptor {
-  //   String descriptorString();
-  // }
-  // </pre>
-  private static void addTypeDescriptor(ZipBuilder builder) throws Exception {
-    addClassToZipBuilder(
-        builder,
-        ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT,
-        "java/lang/invoke/TypeDescriptor",
-        methodAdder ->
-            methodAdder.add(
-                ACC_PUBLIC | ACC_ABSTRACT,
-                "descriptorString",
-                methodDescriptor(false, String.class)));
-  }
-
   // Generates a class file for:
   // <pre>
   // public class StringConcatFactory {}
@@ -101,45 +59,6 @@
 
   // Generates a class file for:
   // <pre>
-  // public abstract class Record {
-  //   protected Record() {}
-  //
-  //   public abstract boolean equals(Object obj);
-  //
-  //   public abstract int hashCode();
-  //
-  //   public abstract String toString();
-  // }
-  // </pre>
-  private static void addRecord(ZipBuilder builder) throws Exception {
-    addClassToZipBuilder(
-        builder,
-        ACC_PUBLIC | ACC_ABSTRACT,
-        "java/lang/Record",
-        methodAdder -> {
-          methodAdder.add(ACC_PROTECTED, "<init>", "()V");
-          methodAdder.add(
-              ACC_PUBLIC | ACC_ABSTRACT,
-              "equals",
-              methodDescriptor(false, Object.class, boolean.class));
-          methodAdder.add(
-              ACC_PUBLIC | ACC_ABSTRACT, "hashCode", methodDescriptor(false, int.class));
-          methodAdder.add(
-              ACC_PUBLIC | ACC_ABSTRACT, "toString", methodDescriptor(false, String.class));
-        });
-  }
-
-  // Generates a class file for:
-  // <pre>
-  // public class RecordComponent {}
-  // </pre>
-  private static void addRecordComponent(ZipBuilder builder) throws Exception {
-    addClassToZipBuilder(
-        builder, ACC_PUBLIC, "java/lang/reflect/RecordComponent", ConsumerUtils.emptyConsumer());
-  }
-
-  // Generates a class file for:
-  // <pre>
   // public interface Supplier {
   //   Object get();
   // }
diff --git a/tools/jdk.py b/tools/jdk.py
index d795230..86f2c3a 100755
--- a/tools/jdk.py
+++ b/tools/jdk.py
@@ -10,8 +10,7 @@
 
 JDK_DIR = os.path.join(defines.THIRD_PARTY, 'openjdk')
 
-ALL_JDKS = ['openjdk-9.0.4', 'jdk-11', 'jdk-15', 'jdk-16', 'jdk-17',
-            'jdk-18', 'jdk-21', 'jdk-23']
+ALL_JDKS = ['openjdk-9.0.4', 'jdk-11', 'jdk-17', 'jdk-21', 'jdk-23']
 
 
 def GetJdkHome():