Update kotlin (and related dependencies) to 2.0.21.

This CL:

  * Updates KSP to 2.0.21-1.0.28
  * Updates kotlin-metadata-jvm to 2.0.21
  * Note: due to https://github.com/bazelbuild/rules_kotlin/issues/1176 we can't actually update Kotlin itself to 2.0.21, but somehow that doesn't seem to cause an issue
  * Migrates kotlin-metadata-jvm usages to the new API (the pre-2.0.0 APIs are deprecated).
  * Updates XProcessing and XProcessing Testing jars
  * Adds flags to fall back to Kotlin 1.9 for compiler tests (Working on getting these tests working with K2/KSP2 is in progress).
  * Updated all of our artifact tests to use the same Kotlin and KSP versions.
  * Added `compat_kt_jvm_library` to alias output jars to the expected locations.

Fixes #4525

RELNOTES=Fixes #4525: Update kotlin-jvm-metadata to 2.0.21 to remove dependency on Beta version.
PiperOrigin-RevId: 703516835
diff --git a/WORKSPACE b/WORKSPACE
index 8ba89d2..9795eae 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -147,14 +147,17 @@
 
 load("@io_bazel_rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories", "kotlinc_version")
 
-KOTLIN_VERSION = "1.9.24"
+# TODO: update to Kotlin 2 once rules_kotlin support it.
+#   See https://github.com/bazelbuild/rules_kotlin/issues/1176
+KOTLINC_VERSION = "1.9.24"
 
 # Get from https://github.com/JetBrains/kotlin/releases/
 KOTLINC_RELEASE_SHA = "eb7b68e01029fa67bc8d060ee54c12018f2c60ddc438cf21db14517229aa693b"
 
 kotlin_repositories(
     compiler_release = kotlinc_version(
-        release = KOTLIN_VERSION,
+        release = KOTLINC_VERSION,
+        # Get from https://github.com/JetBrains/kotlin/releases/
         sha256 = KOTLINC_RELEASE_SHA,
     ),
 )
@@ -203,7 +206,9 @@
 
 INCAP_VERSION = "0.2"
 
-KSP_VERSION = KOTLIN_VERSION + "-1.0.20"
+KOTLIN_VERSION = "2.0.21"
+
+KSP_VERSION = KOTLIN_VERSION + "-1.0.28"
 
 MAVEN_VERSION = "3.3.3"
 
@@ -245,6 +250,8 @@
         "com.google.code.findbugs:jsr305:3.0.1",
         "com.google.devtools.ksp:symbol-processing:%s" % KSP_VERSION,
         "com.google.devtools.ksp:symbol-processing-api:%s" % KSP_VERSION,
+        "com.google.devtools.ksp:symbol-processing-common-deps:%s" % KSP_VERSION,
+        "com.google.devtools.ksp:symbol-processing-aa-embeddable:%s" % KSP_VERSION,
         "com.google.errorprone:error_prone_annotation:%s" % ERROR_PRONE_VERSION,
         "com.google.errorprone:error_prone_annotations:%s" % ERROR_PRONE_VERSION,
         "com.google.errorprone:error_prone_check_api:%s" % ERROR_PRONE_VERSION,
@@ -290,8 +297,8 @@
         "org.jetbrains.kotlin:kotlin-annotation-processing-embeddable:%s" % KOTLIN_VERSION,
         "org.jetbrains.kotlin:kotlin-compiler-embeddable:%s" % KOTLIN_VERSION,
         "org.jetbrains.kotlin:kotlin-daemon-embeddable:%s" % KOTLIN_VERSION,
+        "org.jetbrains.kotlin:kotlin-metadata-jvm:%s" % KOTLIN_VERSION,
         "org.jetbrains.kotlin:kotlin-stdlib:%s" % KOTLIN_VERSION,
-        "org.jetbrains.kotlin:kotlin-metadata-jvm:2.0.0-Beta5",
         "org.jspecify:jspecify:1.0.0",
         "org.mockito:mockito-core:2.28.2",
         "org.pantsbuild:jarjar:1.7.2",
diff --git a/java/dagger/hilt/android/plugin/build.gradle b/java/dagger/hilt/android/plugin/build.gradle
index 8627290..e40d4ed 100644
--- a/java/dagger/hilt/android/plugin/build.gradle
+++ b/java/dagger/hilt/android/plugin/build.gradle
@@ -1,8 +1,8 @@
 buildscript {
   ext {
-    kotlin_version = "1.9.24"
+    kotlin_version = "2.0.21"
     agp_version = System.getenv('AGP_VERSION') ?: "8.1.1"
-    ksp_version = "$kotlin_version-1.0.20"
+    ksp_version = "$kotlin_version-1.0.28"
     pluginArtifactId = 'hilt-android-gradle-plugin'
     pluginId = 'com.google.dagger.hilt.android'
   }
diff --git a/java/dagger/hilt/android/testing/compile/HiltCompilerTests.java b/java/dagger/hilt/android/testing/compile/HiltCompilerTests.java
index e9c2b9a..39e90a9 100644
--- a/java/dagger/hilt/android/testing/compile/HiltCompilerTests.java
+++ b/java/dagger/hilt/android/testing/compile/HiltCompilerTests.java
@@ -70,6 +70,14 @@
 
 /** {@link Compiler} instances for testing Android Hilt. */
 public final class HiltCompilerTests {
+  private static final ImmutableList<String> DEFAULT_JAVAC_OPTIONS = ImmutableList.of();
+
+  private static final ImmutableList<String> DEFAULT_KOTLINC_OPTIONS =
+      ImmutableList.of(
+          "-api-version=1.9",
+          "-language-version=1.9",
+          "-P", "plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true");
+
   /** Returns the {@link XProcessingEnv.Backend} for the given {@link CompilationResultSubject}. */
   public static XProcessingEnv.Backend backend(CompilationResultSubject subject) {
     return CompilerTests.backend(subject);
@@ -161,9 +169,8 @@
                 sources,
                 /* classpath= */ ImmutableList.of(CompilerTests.compilerDepsJar()),
                 /* inheritClasspath= */ false,
-                /* javacArguments= */ ImmutableList.of(),
-                /* kotlincArguments= */ ImmutableList.of(
-                    ),
+                /* javacArguments= */ DEFAULT_JAVAC_OPTIONS,
+                /* kotlincArguments= */ DEFAULT_KOTLINC_OPTIONS,
                 /* kaptProcessors= */ ImmutableList.<Processor>builder()
                     .addAll(defaultProcessors())
                     .addAll(additionalProcessors)
@@ -275,10 +282,12 @@
           sources().asList(),
           /* classpath= */ ImmutableList.of(CompilerTests.compilerDepsJar()),
           /* options= */ processorOptions(),
-          /* javacArguments= */ javacArguments().asList(),
-          /* kotlincArguments= */ ImmutableList.of(
-              "-P",
-              "plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true"),
+          /* javacArguments= */
+          ImmutableList.<String>builder()
+              .addAll(DEFAULT_JAVAC_OPTIONS)
+              .addAll(javacArguments())
+              .build(),
+          /* kotlincArguments= */ DEFAULT_KOTLINC_OPTIONS,
           /* config= */ HiltProcessingEnvConfigs.CONFIGS,
           /* javacProcessors= */ ImmutableList.<Processor>builder()
               .addAll(mergeProcessors(defaultProcessors(), additionalJavacProcessors()))
diff --git a/java/dagger/hilt/processor/internal/kotlin/BUILD b/java/dagger/hilt/processor/internal/kotlin/BUILD
index 5fe9052..32343ab 100644
--- a/java/dagger/hilt/processor/internal/kotlin/BUILD
+++ b/java/dagger/hilt/processor/internal/kotlin/BUILD
@@ -15,13 +15,16 @@
 # Description:
 #   Sources related to Kotlin metadata.
 
-load("@rules_java//java:defs.bzl", "java_library")
+load("//tools:bazel_compat.bzl", "compat_kt_jvm_library")
 
 package(default_visibility = ["//:src"])
 
-java_library(
+compat_kt_jvm_library(
     name = "kotlin",
-    srcs = glob(["*.java"]),
+    srcs = glob([
+        "*.java",
+        "*.kt",
+    ]),
     deps = [
         "//:dagger_with_compiler",
         "//java/dagger/hilt/processor/internal:classnames",
diff --git a/java/dagger/hilt/processor/internal/kotlin/ClassMetadata.kt b/java/dagger/hilt/processor/internal/kotlin/ClassMetadata.kt
new file mode 100644
index 0000000..d8ec6bd
--- /dev/null
+++ b/java/dagger/hilt/processor/internal/kotlin/ClassMetadata.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.processor.internal.kotlin
+
+import androidx.room.compiler.processing.XAnnotation
+import androidx.room.compiler.processing.XFieldElement
+import androidx.room.compiler.processing.XMethodElement
+import androidx.room.compiler.processing.XTypeElement
+import kotlin.Metadata
+import kotlin.metadata.declaresDefaultValue
+import kotlin.metadata.KmClass
+import kotlin.metadata.KmConstructor
+import kotlin.metadata.KmFunction
+import kotlin.metadata.KmProperty
+import kotlin.metadata.KmValueParameter
+import kotlin.metadata.jvm.KotlinClassMetadata
+import kotlin.metadata.jvm.fieldSignature
+import kotlin.metadata.jvm.getterSignature
+import kotlin.metadata.jvm.signature
+import kotlin.metadata.jvm.syntheticMethodForAnnotations
+
+/** Container classes for kotlin metadata types. */
+class ClassMetadata private constructor(private val kmClass: KmClass) {
+  val functionsBySignature = buildList<FunctionMetadata> {
+    addAll(kmClass.constructors.map { ConstructorMetadata(it) })
+    addAll(kmClass.functions.map { MethodMetadata(it) })
+  }.associateBy { it.signature }
+
+  val propertiesBySignature =
+      kmClass.properties
+          .filter { it.fieldSignature != null }
+          .map { PropertyMetadata(it) }
+          .associateBy { it.fieldSignature }
+
+  fun constructors(): List<FunctionMetadata> =
+      functionsBySignature.values.filterIsInstance<ConstructorMetadata>()
+
+  companion object {
+    /** Parse Kotlin class metadata from a given type element. */
+    @JvmStatic
+    fun of(typeElement: XTypeElement): ClassMetadata {
+      val metadataAnnotation = checkNotNull(typeElement.getAnnotation(Metadata::class)).value
+      return when (val classMetadata = KotlinClassMetadata.readStrict(metadataAnnotation)) {
+        is KotlinClassMetadata.Class -> ClassMetadata(classMetadata.kmClass)
+        else -> error("Unsupported metadata type: ${classMetadata}")
+      }
+    }
+  }
+}
+
+class ConstructorMetadata(private val kmConstructor: KmConstructor) : FunctionMetadata {
+  override val name = "<init>"
+  override val signature = kmConstructor.signature!!.toString()
+  override val parameters = kmConstructor.valueParameters.map { ParameterMetadata(it) }
+}
+
+class MethodMetadata(private val kmFunction: KmFunction) : FunctionMetadata {
+  override val name = kmFunction.name
+  override val signature = kmFunction.signature!!.toString()
+  override val parameters = kmFunction.valueParameters.map { ParameterMetadata(it) }
+}
+
+interface FunctionMetadata {
+  val name: String
+  val signature: String
+  val parameters: List<ParameterMetadata>
+}
+
+class PropertyMetadata(private val kmProperty: KmProperty) {
+  val name = kmProperty.name
+
+  /** Returns the JVM field descriptor of the backing field of this property. */
+  val fieldSignature = kmProperty.fieldSignature?.toString()
+
+  val getterSignature = kmProperty.getterSignature?.toString()
+
+  /** Returns JVM method descriptor of the synthetic method for property annotations. */
+  val methodForAnnotationsSignature = kmProperty.syntheticMethodForAnnotations?.toString()
+}
+
+class ParameterMetadata(private val kmValueParameter: KmValueParameter) {
+  val name = kmValueParameter.name
+
+  fun declaresDefaultValue() = kmValueParameter.declaresDefaultValue
+}
+
diff --git a/java/dagger/hilt/processor/internal/kotlin/KotlinMetadata.java b/java/dagger/hilt/processor/internal/kotlin/KotlinMetadata.java
index 67b2177..47edf6e 100644
--- a/java/dagger/hilt/processor/internal/kotlin/KotlinMetadata.java
+++ b/java/dagger/hilt/processor/internal/kotlin/KotlinMetadata.java
@@ -17,37 +17,20 @@
 package dagger.hilt.processor.internal.kotlin;
 
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
-import static kotlin.metadata.Flag.ValueParameter.DECLARES_DEFAULT_VALUE;
 
-import androidx.room.compiler.processing.XAnnotation;
 import androidx.room.compiler.processing.XFieldElement;
 import androidx.room.compiler.processing.XMethodElement;
 import androidx.room.compiler.processing.XTypeElement;
 import com.google.auto.value.AutoValue;
 import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import dagger.hilt.processor.internal.ClassNames;
 import dagger.internal.codegen.extension.DaggerCollectors;
 import dagger.internal.codegen.xprocessing.XElements;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Function;
 import javax.annotation.Nullable;
-import kotlin.Metadata;
-import kotlin.metadata.Flag;
-import kotlin.metadata.KmClass;
-import kotlin.metadata.KmConstructor;
-import kotlin.metadata.KmFunction;
-import kotlin.metadata.KmProperty;
-import kotlin.metadata.jvm.JvmExtensionsKt;
-import kotlin.metadata.jvm.JvmFieldSignature;
-import kotlin.metadata.jvm.JvmMetadataUtil;
-import kotlin.metadata.jvm.JvmMethodSignature;
-import kotlin.metadata.jvm.KotlinClassMetadata;
 
 /** Data class of a TypeElement and its Kotlin metadata. */
 @AutoValue
@@ -79,8 +62,8 @@
   @Memoized
   boolean containsConstructorWithDefaultParam() {
     return classMetadata().constructors().stream()
-        .flatMap(constructor -> constructor.parameters().stream())
-        .anyMatch(parameter -> parameter.flags(DECLARES_DEFAULT_VALUE));
+        .flatMap(constructor -> constructor.getParameters().stream())
+        .anyMatch(parameter -> parameter.declaresDefaultValue());
   }
 
   /** Gets the synthetic method for annotations of a given field element. */
@@ -102,8 +85,7 @@
   }
 
   private Optional<MethodForAnnotations> getAnnotationMethodUncached(XFieldElement fieldElement) {
-    return findProperty(fieldElement)
-        .methodForAnnotationsSignature()
+    return Optional.ofNullable(findProperty(fieldElement).getMethodForAnnotationsSignature())
         .map(
             signature ->
                 Optional.ofNullable(methodDescriptors().get(signature))
@@ -120,20 +102,19 @@
   }
 
   private Optional<XMethodElement> getPropertyGetterUncached(XFieldElement fieldElement) {
-    return findProperty(fieldElement)
-        .getterSignature()
+    return Optional.ofNullable(findProperty(fieldElement).getGetterSignature())
         .flatMap(signature -> Optional.ofNullable(methodDescriptors().get(signature)));
   }
 
   private PropertyMetadata findProperty(XFieldElement field) {
     String fieldDescriptor = field.getJvmDescriptor();
-    if (classMetadata().propertiesByFieldSignature().containsKey(fieldDescriptor)) {
-      return classMetadata().propertiesByFieldSignature().get(fieldDescriptor);
+    if (classMetadata().getPropertiesBySignature().containsKey(fieldDescriptor)) {
+      return classMetadata().getPropertiesBySignature().get(fieldDescriptor);
     } else {
       // Fallback to finding property by name, see: https://youtrack.jetbrains.com/issue/KT-35124
       final String propertyName = getPropertyNameFromField(field);
-      return classMetadata().propertiesByFieldSignature().values().stream()
-          .filter(property -> propertyName.contentEquals(property.name()))
+      return classMetadata().getPropertiesBySignature().values().stream()
+          .filter(property -> propertyName.contentEquals(property.getName())) // SUPPRESS_GET_NAME_CHECK
           .collect(DaggerCollectors.onlyElement());
     }
   }
@@ -149,204 +130,7 @@
 
   /** Parse Kotlin class metadata from a given type element. */
   static KotlinMetadata from(XTypeElement typeElement) {
-    return new AutoValue_KotlinMetadata(typeElement, ClassMetadata.create(metadataOf(typeElement)));
-  }
-
-  private static KotlinClassMetadata.Class metadataOf(XTypeElement typeElement) {
-    XAnnotation annotation = typeElement.getAnnotation(ClassNames.KOTLIN_METADATA);
-    Metadata metadataAnnotation =
-        JvmMetadataUtil.Metadata(
-            annotation.getAsInt("k"),
-            annotation.getAsIntList("mv").stream().mapToInt(Integer::intValue).toArray(),
-            annotation.getAsStringList("d1").toArray(new String[0]),
-            annotation.getAsStringList("d2").toArray(new String[0]),
-            annotation.getAsString("xs"),
-            getOptionalStringValue(annotation, "pn").orElse(null),
-            getOptionalIntValue(annotation, "xi").orElse(null));
-    KotlinClassMetadata metadata = KotlinClassMetadata.read(metadataAnnotation);
-    if (metadata == null) {
-      // Can happen if Kotlin < 1.0 or if metadata version is not supported, i.e.
-      // kotlinx-metadata-jvm is outdated.
-      throw new IllegalStateException(
-          "Unable to read Kotlin metadata due to unsupported metadata version.");
-    }
-    if (metadata instanceof KotlinClassMetadata.Class) {
-      // TODO(danysantiago): If when we need other types of metadata then move to right method.
-      return (KotlinClassMetadata.Class) metadata;
-    } else {
-      throw new IllegalStateException("Unsupported metadata type: " + metadata);
-    }
-  }
-
-  @AutoValue
-  abstract static class ClassMetadata extends BaseMetadata {
-    abstract Optional<String> companionObjectName();
-
-    abstract ImmutableSet<FunctionMetadata> constructors();
-
-    abstract ImmutableMap<String, FunctionMetadata> functionsBySignature();
-
-    abstract ImmutableMap<String, PropertyMetadata> propertiesByFieldSignature();
-
-    static ClassMetadata create(KotlinClassMetadata.Class metadata) {
-      KmClass kmClass = metadata.toKmClass();
-      ClassMetadata.Builder builder = ClassMetadata.builder(kmClass.getFlags(), kmClass.getName());
-      builder.companionObjectName(Optional.ofNullable(kmClass.getCompanionObject()));
-      kmClass.getConstructors().forEach(it -> builder.addConstructor(FunctionMetadata.create(it)));
-      kmClass.getFunctions().forEach(it -> builder.addFunction(FunctionMetadata.create(it)));
-      kmClass.getProperties().forEach(it -> builder.addProperty(PropertyMetadata.create(it)));
-      return builder.build();
-    }
-
-    private static Builder builder(int flags, String name) {
-      return new AutoValue_KotlinMetadata_ClassMetadata.Builder().flags(flags).name(name);
-    }
-
-    @AutoValue.Builder
-    abstract static class Builder implements BaseMetadata.Builder<Builder> {
-      abstract Builder companionObjectName(Optional<String> companionObjectName);
-
-      abstract ImmutableSet.Builder<FunctionMetadata> constructorsBuilder();
-
-      abstract ImmutableMap.Builder<String, FunctionMetadata> functionsBySignatureBuilder();
-
-      abstract ImmutableMap.Builder<String, PropertyMetadata> propertiesByFieldSignatureBuilder();
-
-      Builder addConstructor(FunctionMetadata constructor) {
-        constructorsBuilder().add(constructor);
-        functionsBySignatureBuilder().put(constructor.signature(), constructor);
-        return this;
-      }
-
-      Builder addFunction(FunctionMetadata function) {
-        functionsBySignatureBuilder().put(function.signature(), function);
-        return this;
-      }
-
-      Builder addProperty(PropertyMetadata property) {
-        if (property.fieldSignature().isPresent()) {
-          propertiesByFieldSignatureBuilder().put(property.fieldSignature().get(), property);
-        }
-        return this;
-      }
-
-      abstract ClassMetadata build();
-    }
-  }
-
-  @AutoValue
-  abstract static class FunctionMetadata extends BaseMetadata {
-    abstract String signature();
-
-    abstract ImmutableList<ValueParameterMetadata> parameters();
-
-    static FunctionMetadata create(KmConstructor metadata) {
-      FunctionMetadata.Builder builder = FunctionMetadata.builder(metadata.getFlags(), "<init>");
-      metadata
-          .getValueParameters()
-          .forEach(
-              it ->
-                  builder.addParameter(ValueParameterMetadata.create(it.getFlags(), it.getName())));
-      builder.signature(Objects.requireNonNull(JvmExtensionsKt.getSignature(metadata)).asString());
-      return builder.build();
-    }
-
-    static FunctionMetadata create(KmFunction metadata) {
-      FunctionMetadata.Builder builder =
-          FunctionMetadata.builder(metadata.getFlags(), metadata.getName());
-      metadata
-          .getValueParameters()
-          .forEach(
-              it ->
-                  builder.addParameter(ValueParameterMetadata.create(it.getFlags(), it.getName())));
-      builder.signature(Objects.requireNonNull(JvmExtensionsKt.getSignature(metadata)).asString());
-      return builder.build();
-    }
-
-    private static Builder builder(int flags, String name) {
-      return new AutoValue_KotlinMetadata_FunctionMetadata.Builder().flags(flags).name(name);
-    }
-
-    @AutoValue.Builder
-    abstract static class Builder implements BaseMetadata.Builder<Builder> {
-      abstract Builder signature(String signature);
-
-      abstract ImmutableList.Builder<ValueParameterMetadata> parametersBuilder();
-
-      Builder addParameter(ValueParameterMetadata parameter) {
-        parametersBuilder().add(parameter);
-        return this;
-      }
-
-      abstract FunctionMetadata build();
-    }
-  }
-
-  @AutoValue
-  abstract static class PropertyMetadata extends BaseMetadata {
-    /** Returns the JVM field descriptor of the backing field of this property. */
-    abstract Optional<String> fieldSignature();
-
-    abstract Optional<String> getterSignature();
-
-    /** Returns JVM method descriptor of the synthetic method for property annotations. */
-    abstract Optional<String> methodForAnnotationsSignature();
-
-    static PropertyMetadata create(KmProperty metadata) {
-      PropertyMetadata.Builder builder =
-          PropertyMetadata.builder(metadata.getFlags(), metadata.getName());
-      builder.fieldSignature(
-          Optional.ofNullable(JvmExtensionsKt.getFieldSignature(metadata))
-              .map(JvmFieldSignature::asString));
-      builder.getterSignature(
-          Optional.ofNullable(JvmExtensionsKt.getGetterSignature(metadata))
-              .map(JvmMethodSignature::asString));
-      builder.methodForAnnotationsSignature(
-          Optional.ofNullable(JvmExtensionsKt.getSyntheticMethodForAnnotations(metadata))
-              .map(JvmMethodSignature::asString));
-      return builder.build();
-    }
-
-    private static Builder builder(int flags, String name) {
-      return new AutoValue_KotlinMetadata_PropertyMetadata.Builder().flags(flags).name(name);
-    }
-
-    @AutoValue.Builder
-    interface Builder extends BaseMetadata.Builder<Builder> {
-      Builder fieldSignature(Optional<String> signature);
-
-      Builder getterSignature(Optional<String> signature);
-
-      Builder methodForAnnotationsSignature(Optional<String> signature);
-
-      PropertyMetadata build();
-    }
-  }
-
-  @AutoValue
-  abstract static class ValueParameterMetadata extends BaseMetadata {
-    private static ValueParameterMetadata create(int flags, String name) {
-      return new AutoValue_KotlinMetadata_ValueParameterMetadata(flags, name);
-    }
-  }
-
-  abstract static class BaseMetadata {
-    /** Returns the Kotlin metadata flags for this property. */
-    abstract int flags();
-
-    /** returns {@code true} if the given flag (e.g. {@link Flag.IS_PRIVATE}) applies. */
-    boolean flags(Flag flag) {
-      return flag.invoke(flags());
-    }
-
-    /** Returns the simple name of this property. */
-    abstract String name();
-
-    interface Builder<BuilderT> {
-      BuilderT flags(int flags);
-
-      BuilderT name(String name);
-    }
+    return new AutoValue_KotlinMetadata(typeElement, ClassMetadata.of(typeElement));
   }
 
   @AutoValue
@@ -360,21 +144,4 @@
     @Nullable
     abstract XMethodElement method();
   }
-
-  private static Optional<Integer> getOptionalIntValue(XAnnotation annotation, String valueName) {
-    return isValuePresent(annotation, valueName)
-        ? Optional.of(annotation.getAsInt(valueName))
-        : Optional.empty();
-  }
-
-  private static Optional<String> getOptionalStringValue(XAnnotation annotation, String valueName) {
-    return isValuePresent(annotation, valueName)
-        ? Optional.of(annotation.getAsString(valueName))
-        : Optional.empty();
-  }
-
-  private static boolean isValuePresent(XAnnotation annotation, String valueName) {
-    return annotation.getAnnotationValues().stream()
-        .anyMatch(member -> member.getName().equals(valueName));
-  }
 }
diff --git a/java/dagger/internal/codegen/kotlin/BUILD b/java/dagger/internal/codegen/kotlin/BUILD
index 41b82ab..ed750cd 100644
--- a/java/dagger/internal/codegen/kotlin/BUILD
+++ b/java/dagger/internal/codegen/kotlin/BUILD
@@ -15,13 +15,16 @@
 # Description:
 #   Sources related to Kotlin metadata.
 
-load("@rules_java//java:defs.bzl", "java_library")
+load("//tools:bazel_compat.bzl", "compat_kt_jvm_library")
 
 package(default_visibility = ["//:src"])
 
-java_library(
+compat_kt_jvm_library(
     name = "kotlin",
-    srcs = glob(["*.java"]),
+    srcs = glob([
+        "*.java",
+        "*.kt",
+    ]),
     plugins = ["//java/dagger/internal/codegen/bootstrap"],
     tags = ["maven:merged"],
     deps = [
diff --git a/java/dagger/internal/codegen/kotlin/ClassMetadata.kt b/java/dagger/internal/codegen/kotlin/ClassMetadata.kt
new file mode 100644
index 0000000..737057b
--- /dev/null
+++ b/java/dagger/internal/codegen/kotlin/ClassMetadata.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen.kotlin
+
+import androidx.room.compiler.processing.XAnnotation
+import androidx.room.compiler.processing.XFieldElement
+import androidx.room.compiler.processing.XMethodElement
+import androidx.room.compiler.processing.XTypeElement
+import kotlin.Metadata
+import kotlin.metadata.KmClass
+import kotlin.metadata.KmConstructor
+import kotlin.metadata.KmFunction
+import kotlin.metadata.KmProperty
+import kotlin.metadata.KmValueParameter
+import kotlin.metadata.jvm.KotlinClassMetadata
+import kotlin.metadata.jvm.signature
+import kotlin.metadata.jvm.fieldSignature
+import kotlin.metadata.jvm.getterSignature
+import kotlin.metadata.jvm.syntheticMethodForAnnotations
+
+/** Container classes for kotlin metadata types. */
+class ClassMetadata private constructor(private val kmClass: KmClass) {
+  val functionsBySignature = buildList<FunctionMetadata> {
+    addAll(kmClass.constructors.map { ConstructorMetadata(it) })
+    addAll(kmClass.functions.map { MethodMetadata(it) })
+  }.associateBy { it.signature }
+
+  val propertiesBySignature =
+      kmClass.properties
+          .filter { it.fieldSignature != null }
+          .map { PropertyMetadata(it) }
+          .associateBy { it.fieldSignature }
+
+  companion object {
+    /** Parse Kotlin class metadata from a given type element. */
+    @JvmStatic
+    fun of(typeElement: XTypeElement): ClassMetadata {
+      val metadataAnnotation = checkNotNull(typeElement.getAnnotation(Metadata::class)).value
+      return when (val classMetadata = KotlinClassMetadata.readStrict(metadataAnnotation)) {
+        is KotlinClassMetadata.Class -> ClassMetadata(classMetadata.kmClass)
+        else -> error("Unsupported metadata type: ${classMetadata}")
+      }
+    }
+  }
+}
+
+class ConstructorMetadata(private val kmConstructor: KmConstructor) : FunctionMetadata {
+  override val name = "<init>"
+  override val signature = kmConstructor.signature!!.toString()
+  override val parameters = kmConstructor.valueParameters.map { ParameterMetadata(it) }
+}
+
+class MethodMetadata(private val kmFunction: KmFunction) : FunctionMetadata {
+  override val name = kmFunction.name
+  override val signature = kmFunction.signature!!.toString()
+  override val parameters = kmFunction.valueParameters.map { ParameterMetadata(it) }
+}
+
+interface FunctionMetadata {
+  val name: String
+  val signature: String
+  val parameters: List<ParameterMetadata>
+}
+
+class PropertyMetadata(private val kmProperty: KmProperty) {
+  val name = kmProperty.name
+
+  /** Returns the JVM field descriptor of the backing field of this property. */
+  val fieldSignature = kmProperty.fieldSignature?.toString()
+
+  val getterSignature = kmProperty.getterSignature?.toString()
+
+  /** Returns JVM method descriptor of the synthetic method for property annotations. */
+  val methodForAnnotationsSignature = kmProperty.syntheticMethodForAnnotations?.toString()
+}
+
+class ParameterMetadata(private val kmValueParameter: KmValueParameter) {
+  val name = kmValueParameter.name
+}
diff --git a/java/dagger/internal/codegen/kotlin/KotlinMetadata.java b/java/dagger/internal/codegen/kotlin/KotlinMetadata.java
index ef8f9a0..b06fd72 100644
--- a/java/dagger/internal/codegen/kotlin/KotlinMetadata.java
+++ b/java/dagger/internal/codegen/kotlin/KotlinMetadata.java
@@ -19,35 +19,18 @@
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
 
-import androidx.room.compiler.processing.XAnnotation;
 import androidx.room.compiler.processing.XFieldElement;
 import androidx.room.compiler.processing.XMethodElement;
 import androidx.room.compiler.processing.XTypeElement;
 import com.google.auto.value.AutoValue;
 import com.google.auto.value.extension.memoized.Memoized;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
 import dagger.internal.codegen.extension.DaggerCollectors;
-import dagger.internal.codegen.javapoet.TypeNames;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Function;
 import javax.annotation.Nullable;
-import kotlin.Metadata;
-import kotlin.metadata.Flag;
-import kotlin.metadata.KmClass;
-import kotlin.metadata.KmConstructor;
-import kotlin.metadata.KmFunction;
-import kotlin.metadata.KmProperty;
-import kotlin.metadata.jvm.JvmExtensionsKt;
-import kotlin.metadata.jvm.JvmFieldSignature;
-import kotlin.metadata.jvm.JvmMetadataUtil;
-import kotlin.metadata.jvm.JvmMethodSignature;
-import kotlin.metadata.jvm.KotlinClassMetadata;
 
 /** Data class of a TypeElement and its Kotlin metadata. */
 @AutoValue
@@ -107,8 +90,7 @@
   }
 
   private Optional<MethodForAnnotations> getAnnotationMethodUncached(XFieldElement fieldElement) {
-    return findProperty(fieldElement)
-        .methodForAnnotationsSignature()
+    return Optional.ofNullable(findProperty(fieldElement).getMethodForAnnotationsSignature())
         .map(
             signature ->
                 Optional.ofNullable(methodDescriptors().get(signature))
@@ -125,20 +107,19 @@
   }
 
   private Optional<XMethodElement> getPropertyGetterUncached(XFieldElement fieldElement) {
-    return findProperty(fieldElement)
-        .getterSignature()
+    return Optional.ofNullable(findProperty(fieldElement).getGetterSignature())
         .flatMap(signature -> Optional.ofNullable(methodDescriptors().get(signature)));
   }
 
   private PropertyMetadata findProperty(XFieldElement field) {
     String fieldDescriptor = field.getJvmDescriptor();
-    if (classMetadata().propertiesByFieldSignature().containsKey(fieldDescriptor)) {
-      return classMetadata().propertiesByFieldSignature().get(fieldDescriptor);
+    if (classMetadata().getPropertiesBySignature().containsKey(fieldDescriptor)) {
+      return classMetadata().getPropertiesBySignature().get(fieldDescriptor);
     } else {
       // Fallback to finding property by name, see: https://youtrack.jetbrains.com/issue/KT-35124
       final String propertyName = getPropertyNameFromField(field);
-      return classMetadata().propertiesByFieldSignature().values().stream()
-          .filter(property -> propertyName.contentEquals(property.name()))
+      return classMetadata().getPropertiesBySignature().values().stream()
+          .filter(property -> propertyName.contentEquals(property.getName())) // SUPPRESS_GET_NAME_CHECK
           .collect(DaggerCollectors.onlyElement());
     }
   }
@@ -154,217 +135,7 @@
 
   /** Parse Kotlin class metadata from a given type element. */
   static KotlinMetadata from(XTypeElement typeElement) {
-    return new AutoValue_KotlinMetadata(typeElement, ClassMetadata.create(metadataOf(typeElement)));
-  }
-
-  private static KotlinClassMetadata.Class metadataOf(XTypeElement typeElement) {
-    XAnnotation annotationMirror = typeElement.getAnnotation(TypeNames.KOTLIN_METADATA);
-    Preconditions.checkNotNull(annotationMirror);
-    Metadata metadataAnnotation =
-        JvmMetadataUtil.Metadata(
-            annotationMirror.getAsInt("k"),
-            annotationMirror.getAsIntList("mv").stream().mapToInt(Integer::intValue).toArray(),
-            annotationMirror.getAsStringList("d1").toArray(new String[0]),
-            annotationMirror.getAsStringList("d2").toArray(new String[0]),
-            annotationMirror.getAsString("xs"),
-            annotationMirror.getAnnotationValue("pn").hasStringValue()
-                ? annotationMirror.getAsString("pn")
-                : null,
-            annotationMirror.getAnnotationValue("xi").hasIntValue()
-                ? annotationMirror.getAsInt("xi")
-                : null);
-    KotlinClassMetadata metadata = KotlinClassMetadata.read(metadataAnnotation);
-    if (metadata == null) {
-      // Can happen if Kotlin < 1.0 or if metadata version is not supported, i.e.
-      // kotlinx-metadata-jvm is outdated.
-      throw new IllegalStateException(
-          "Unable to read Kotlin metadata due to unsupported metadata version.");
-    }
-    if (metadata instanceof KotlinClassMetadata.Class) {
-      // TODO(danysantiago): If when we need other types of metadata then move to right method.
-      return (KotlinClassMetadata.Class) metadata;
-    } else {
-      throw new IllegalStateException("Unsupported metadata type: " + metadata);
-    }
-  }
-
-  @AutoValue
-  abstract static class ClassMetadata extends BaseMetadata {
-    abstract Optional<String> companionObjectName();
-
-    abstract ImmutableSet<FunctionMetadata> constructors();
-
-    abstract ImmutableMap<String, FunctionMetadata> functionsBySignature();
-
-    abstract ImmutableMap<String, PropertyMetadata> propertiesByFieldSignature();
-
-    static ClassMetadata create(KotlinClassMetadata.Class metadata) {
-      KmClass kmClass = metadata.toKmClass();
-      ClassMetadata.Builder builder =
-          ClassMetadata.builder(
-              kmClass.getFlags(), kmClass.getName()); // // SUPPRESS_GET_NAME_CHECK
-      builder.companionObjectName(Optional.ofNullable(kmClass.getCompanionObject()));
-      kmClass.getConstructors().forEach(it -> builder.addConstructor(FunctionMetadata.create(it)));
-      kmClass.getFunctions().forEach(it -> builder.addFunction(FunctionMetadata.create(it)));
-      kmClass.getProperties().forEach(it -> builder.addProperty(PropertyMetadata.create(it)));
-      return builder.build();
-    }
-
-    private static Builder builder(int flags, String name) {
-      return new AutoValue_KotlinMetadata_ClassMetadata.Builder().flags(flags).name(name);
-    }
-
-    @AutoValue.Builder
-    abstract static class Builder implements BaseMetadata.Builder<Builder> {
-      abstract Builder companionObjectName(Optional<String> companionObjectName);
-
-      abstract ImmutableSet.Builder<FunctionMetadata> constructorsBuilder();
-
-      abstract ImmutableMap.Builder<String, FunctionMetadata> functionsBySignatureBuilder();
-
-      abstract ImmutableMap.Builder<String, PropertyMetadata> propertiesByFieldSignatureBuilder();
-
-      Builder addConstructor(FunctionMetadata constructor) {
-        constructorsBuilder().add(constructor);
-        functionsBySignatureBuilder().put(constructor.signature(), constructor);
-        return this;
-      }
-
-      Builder addFunction(FunctionMetadata function) {
-        functionsBySignatureBuilder().put(function.signature(), function);
-        return this;
-      }
-
-      Builder addProperty(PropertyMetadata property) {
-        if (property.fieldSignature().isPresent()) {
-          propertiesByFieldSignatureBuilder().put(property.fieldSignature().get(), property);
-        }
-        return this;
-      }
-
-      abstract ClassMetadata build();
-    }
-  }
-
-  @AutoValue
-  abstract static class FunctionMetadata extends BaseMetadata {
-    abstract String signature();
-
-    abstract ImmutableList<ValueParameterMetadata> parameters();
-
-    static FunctionMetadata create(KmConstructor metadata) {
-      FunctionMetadata.Builder builder = FunctionMetadata.builder(metadata.getFlags(), "<init>");
-      metadata
-          .getValueParameters()
-          .forEach(
-              it ->
-                  builder.addParameter(
-                      ValueParameterMetadata.create(
-                          it.getFlags(), it.getName()))); // SUPPRESS_GET_NAME_CHECK
-      builder.signature(Objects.requireNonNull(JvmExtensionsKt.getSignature(metadata)).asString());
-      return builder.build();
-    }
-
-    static FunctionMetadata create(KmFunction metadata) {
-      FunctionMetadata.Builder builder =
-          FunctionMetadata.builder(
-              metadata.getFlags(), metadata.getName()); // SUPPRESS_GET_NAME_CHECK
-      metadata
-          .getValueParameters()
-          .forEach(
-              it ->
-                  builder.addParameter(
-                      ValueParameterMetadata.create(
-                          it.getFlags(), it.getName()))); // SUPPRESS_GET_NAME_CHECK
-      builder.signature(Objects.requireNonNull(JvmExtensionsKt.getSignature(metadata)).asString());
-      return builder.build();
-    }
-
-    private static Builder builder(int flags, String name) {
-      return new AutoValue_KotlinMetadata_FunctionMetadata.Builder().flags(flags).name(name);
-    }
-
-    @AutoValue.Builder
-    abstract static class Builder implements BaseMetadata.Builder<Builder> {
-      abstract Builder signature(String signature);
-
-      abstract ImmutableList.Builder<ValueParameterMetadata> parametersBuilder();
-
-      Builder addParameter(ValueParameterMetadata parameter) {
-        parametersBuilder().add(parameter);
-        return this;
-      }
-
-      abstract FunctionMetadata build();
-    }
-  }
-
-  @AutoValue
-  abstract static class PropertyMetadata extends BaseMetadata {
-    /** Returns the JVM field descriptor of the backing field of this property. */
-    abstract Optional<String> fieldSignature();
-
-    abstract Optional<String> getterSignature();
-
-    /** Returns JVM method descriptor of the synthetic method for property annotations. */
-    abstract Optional<String> methodForAnnotationsSignature();
-
-    static PropertyMetadata create(KmProperty metadata) {
-      PropertyMetadata.Builder builder =
-          PropertyMetadata.builder(
-              metadata.getFlags(), metadata.getName()); // SUPPRESS_GET_NAME_CHECK
-      builder.fieldSignature(
-          Optional.ofNullable(JvmExtensionsKt.getFieldSignature(metadata))
-              .map(JvmFieldSignature::asString));
-      builder.getterSignature(
-          Optional.ofNullable(JvmExtensionsKt.getGetterSignature(metadata))
-              .map(JvmMethodSignature::asString));
-      builder.methodForAnnotationsSignature(
-          Optional.ofNullable(JvmExtensionsKt.getSyntheticMethodForAnnotations(metadata))
-              .map(JvmMethodSignature::asString));
-      return builder.build();
-    }
-
-    private static Builder builder(int flags, String name) {
-      return new AutoValue_KotlinMetadata_PropertyMetadata.Builder().flags(flags).name(name);
-    }
-
-    @AutoValue.Builder
-    interface Builder extends BaseMetadata.Builder<Builder> {
-      Builder fieldSignature(Optional<String> signature);
-
-      Builder getterSignature(Optional<String> signature);
-
-      Builder methodForAnnotationsSignature(Optional<String> signature);
-
-      PropertyMetadata build();
-    }
-  }
-
-  @AutoValue
-  abstract static class ValueParameterMetadata extends BaseMetadata {
-    private static ValueParameterMetadata create(int flags, String name) {
-      return new AutoValue_KotlinMetadata_ValueParameterMetadata(flags, name);
-    }
-  }
-
-  abstract static class BaseMetadata {
-    /** Returns the Kotlin metadata flags for this property. */
-    abstract int flags();
-
-    /** returns {@code true} if the given flag (e.g. {@link Flag.IS_PRIVATE}) applies. */
-    boolean flags(Flag flag) {
-      return flag.invoke(flags());
-    }
-
-    /** Returns the simple name of this property. */
-    abstract String name();
-
-    interface Builder<BuilderT> {
-      BuilderT flags(int flags);
-
-      BuilderT name(String name);
-    }
+    return new AutoValue_KotlinMetadata(typeElement, ClassMetadata.of(typeElement));
   }
 
   @AutoValue
diff --git a/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java b/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java
index 991b81a..9f80b3b 100644
--- a/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java
+++ b/java/dagger/internal/codegen/kotlin/KotlinMetadataUtil.java
@@ -29,7 +29,6 @@
 import com.google.common.collect.ImmutableSet;
 import com.squareup.javapoet.ClassName;
 import dagger.internal.codegen.javapoet.TypeNames;
-import dagger.internal.codegen.kotlin.KotlinMetadata.FunctionMetadata;
 import java.util.Optional;
 import javax.inject.Inject;
 
@@ -86,7 +85,12 @@
   public ImmutableMap<String, String> getAllMethodNamesBySignature(XTypeElement element) {
     checkState(
         hasMetadata(element), "Can not call getAllMethodNamesBySignature for non-Kotlin class");
-    return metadataFactory.create(element).classMetadata().functionsBySignature().values().stream()
-        .collect(toImmutableMap(FunctionMetadata::signature, FunctionMetadata::name));
+    return metadataFactory.create(element)
+        .classMetadata()
+        .getFunctionsBySignature().values().stream()
+        .collect(
+            toImmutableMap(
+                FunctionMetadata::getSignature,
+                FunctionMetadata::getName)); // SUPPRESS_GET_NAME_CHECK
   }
 }
diff --git a/java/dagger/internal/codegen/xprocessing/BUILD b/java/dagger/internal/codegen/xprocessing/BUILD
index 4b549ed..f03b2f9 100644
--- a/java/dagger/internal/codegen/xprocessing/BUILD
+++ b/java/dagger/internal/codegen/xprocessing/BUILD
@@ -64,6 +64,8 @@
     exports = [
         ":xprocessing-testing-lib",
         "@maven//:com_google_devtools_ksp_symbol_processing",
+        "@maven//:com_google_devtools_ksp_symbol_processing_aa_embeddable",
+        "@maven//:com_google_devtools_ksp_symbol_processing_common_deps",
         "@maven//:org_jetbrains_kotlin_kotlin_annotation_processing_embeddable",
         "@maven//:org_jetbrains_kotlin_kotlin_compiler_embeddable",
         "@maven//:org_jetbrains_kotlin_kotlin_daemon_embeddable",
diff --git a/java/dagger/internal/codegen/xprocessing/xprocessing-testing.jar b/java/dagger/internal/codegen/xprocessing/xprocessing-testing.jar
index 4d0d7fd..880787c 100644
--- a/java/dagger/internal/codegen/xprocessing/xprocessing-testing.jar
+++ b/java/dagger/internal/codegen/xprocessing/xprocessing-testing.jar
Binary files differ
diff --git a/java/dagger/internal/codegen/xprocessing/xprocessing.jar b/java/dagger/internal/codegen/xprocessing/xprocessing.jar
index 7c041d6..c19640f 100644
--- a/java/dagger/internal/codegen/xprocessing/xprocessing.jar
+++ b/java/dagger/internal/codegen/xprocessing/xprocessing.jar
Binary files differ
diff --git a/java/dagger/testing/compile/CompilerTests.java b/java/dagger/testing/compile/CompilerTests.java
index 2567f52..39d22cb 100644
--- a/java/dagger/testing/compile/CompilerTests.java
+++ b/java/dagger/testing/compile/CompilerTests.java
@@ -68,6 +68,14 @@
       ImmutableMap.of(
           "dagger.experimentalDaggerErrorMessages", "enabled");
 
+  private static final ImmutableList<String> DEFAULT_JAVAC_OPTIONS = ImmutableList.of();
+
+  private static final ImmutableList<String> DEFAULT_KOTLINC_OPTIONS =
+      ImmutableList.of(
+          "-api-version=1.9",
+          "-language-version=1.9",
+          "-P", "plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true");
+
   /** Returns the {@link XProcessingEnv.Backend} for the given {@link CompilationResultSubject}. */
   public static XProcessingEnv.Backend backend(CompilationResultSubject subject) {
     // TODO(bcorso): Create a more official API for this in XProcessing testing.
@@ -136,9 +144,8 @@
           sources(),
           /* classpath= */ ImmutableList.of(),
           processorOptions(),
-          /* javacArguments= */ ImmutableList.of(),
-          /* kotlincArguments= */ ImmutableList.of(
-              ),
+          /* javacArguments= */ DEFAULT_JAVAC_OPTIONS,
+          /* kotlincArguments= */ DEFAULT_KOTLINC_OPTIONS,
           /* config= */ PROCESSING_ENV_CONFIG,
           invocation -> {
             onInvocation.accept(invocation);
@@ -229,10 +236,8 @@
           sources().asList(),
           /* classpath= */ ImmutableList.of(),
           processorOptions(),
-          /* javacArguments= */ ImmutableList.of(),
-          /* kotlincArguments= */ ImmutableList.of(
-              "-P",
-              "plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true"),
+          /* javacArguments= */ DEFAULT_JAVAC_OPTIONS,
+          /* kotlincArguments= */ DEFAULT_KOTLINC_OPTIONS,
           /* config= */ PROCESSING_ENV_CONFIG,
           /* javacProcessors= */ mergeProcessors(
               ImmutableList.of(
@@ -315,9 +320,8 @@
                 sources,
                 /* classpath= */ ImmutableList.of(compilerDepsJar()),
                 /* inheritClasspath= */ false,
-                /* javacArguments= */ ImmutableList.of(),
-                /* kotlincArguments= */ ImmutableList.of(
-                    ),
+                /* javacArguments= */ DEFAULT_JAVAC_OPTIONS,
+                /* kotlincArguments= */ DEFAULT_KOTLINC_OPTIONS,
                 /* kaptProcessors= */ ImmutableList.of(new ComponentProcessor()),
                 /* symbolProcessorProviders= */ ImmutableList.of(),
                 /* processorOptions= */ processorOptions));
diff --git a/javatests/artifacts/dagger-android-ksp/build.gradle b/javatests/artifacts/dagger-android-ksp/build.gradle
index c438e41..f675791 100644
--- a/javatests/artifacts/dagger-android-ksp/build.gradle
+++ b/javatests/artifacts/dagger-android-ksp/build.gradle
@@ -17,8 +17,8 @@
 buildscript {
     ext {
         agp_version = "8.1.1"
-        kotlin_version = "1.9.24"
-        ksp_version = "$kotlin_version-1.0.20"
+        kotlin_version = "2.0.21"
+        ksp_version = "$kotlin_version-1.0.28"
     }
     repositories {
         google()
diff --git a/javatests/artifacts/dagger-ksp/build.gradle b/javatests/artifacts/dagger-ksp/build.gradle
index 1864e00..63b0341 100644
--- a/javatests/artifacts/dagger-ksp/build.gradle
+++ b/javatests/artifacts/dagger-ksp/build.gradle
@@ -17,8 +17,8 @@
 buildscript {
   ext {
     dagger_version = "LOCAL-SNAPSHOT"
-    kotlin_version = "1.9.24"
-    ksp_version = "$kotlin_version-1.0.20"
+    kotlin_version = "2.0.21"
+    ksp_version = "$kotlin_version-1.0.28"
     junit_version = "4.13"
     truth_version = "1.0.1"
   }
diff --git a/javatests/artifacts/dagger/build.gradle b/javatests/artifacts/dagger/build.gradle
index db2b9c0..6c72ef0 100644
--- a/javatests/artifacts/dagger/build.gradle
+++ b/javatests/artifacts/dagger/build.gradle
@@ -17,8 +17,8 @@
 buildscript {
   ext {
     dagger_version = "LOCAL-SNAPSHOT"
-    kotlin_version = "1.9.24"
-    ksp_version = "$kotlin_version-1.0.20"
+    kotlin_version = "2.0.21"
+    ksp_version = "$kotlin_version-1.0.28"
     junit_version = "4.13"
     truth_version = "1.0.1"
   }
diff --git a/javatests/artifacts/dagger/lazyclasskey/build.gradle b/javatests/artifacts/dagger/lazyclasskey/build.gradle
index 9fdb342..16982d4 100644
--- a/javatests/artifacts/dagger/lazyclasskey/build.gradle
+++ b/javatests/artifacts/dagger/lazyclasskey/build.gradle
@@ -18,7 +18,7 @@
     ext {
         dagger_version = 'LOCAL-SNAPSHOT'
         agp_version = "8.1.1"
-        kotlin_version = '1.9.24'
+        kotlin_version = '2.0.21'
     }
     repositories {
         google()
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/build.gradle b/javatests/artifacts/hilt-android/lazyclasskey/build.gradle
index d284e27..53ced2c 100644
--- a/javatests/artifacts/hilt-android/lazyclasskey/build.gradle
+++ b/javatests/artifacts/hilt-android/lazyclasskey/build.gradle
@@ -18,7 +18,7 @@
     ext {
         hilt_version = 'LOCAL-SNAPSHOT'
         agp_version = "8.1.1"
-        kotlin_version = '1.9.24'
+        kotlin_version = '2.0.21'
     }
     repositories {
         google()
diff --git a/javatests/artifacts/hilt-android/simple/build.gradle b/javatests/artifacts/hilt-android/simple/build.gradle
index 376aca0..3dfb1b9 100644
--- a/javatests/artifacts/hilt-android/simple/build.gradle
+++ b/javatests/artifacts/hilt-android/simple/build.gradle
@@ -17,7 +17,7 @@
 buildscript {
     ext {
         dagger_version = 'LOCAL-SNAPSHOT'
-        kotlin_version = '1.9.24'
+        kotlin_version = '2.0.21'
         agp_version = System.getenv('AGP_VERSION') ?: "8.1.1"
     }
     repositories {
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/build.gradle
index 4840947..b109613 100644
--- a/javatests/artifacts/hilt-android/simpleKotlin/build.gradle
+++ b/javatests/artifacts/hilt-android/simpleKotlin/build.gradle
@@ -16,8 +16,8 @@
 
 buildscript {
     ext {
-        kotlin_version = '1.9.24'
-        ksp_version = "$kotlin_version-1.0.20"
+        kotlin_version = '2.0.21'
+        ksp_version = "$kotlin_version-1.0.28"
         agp_version = System.getenv('AGP_VERSION') ?: "8.1.1"
     }
     repositories {
diff --git a/javatests/artifacts/hilt-android/viewmodel/build.gradle b/javatests/artifacts/hilt-android/viewmodel/build.gradle
index 13c72dc..cb70181 100644
--- a/javatests/artifacts/hilt-android/viewmodel/build.gradle
+++ b/javatests/artifacts/hilt-android/viewmodel/build.gradle
@@ -18,7 +18,7 @@
     ext {
         hilt_version = 'LOCAL-SNAPSHOT'
         agp_version = "8.1.1"
-        kotlin_version = '1.9.24'
+        kotlin_version = '2.0.21'
     }
     repositories {
         google()
diff --git a/javatests/dagger/internal/codegen/DaggerSuperficialValidationTest.java b/javatests/dagger/internal/codegen/DaggerSuperficialValidationTest.java
index dc3dfe2..dffe701 100644
--- a/javatests/dagger/internal/codegen/DaggerSuperficialValidationTest.java
+++ b/javatests/dagger/internal/codegen/DaggerSuperficialValidationTest.java
@@ -475,18 +475,23 @@
                   () -> superficialValidation.validateElement(testClassElement));
           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
-          assertThat(exception)
-              .hasMessageThat()
-              .contains(
-                  String.format(
-                      NEW_LINES.join(
-                          "Validation trace:",
-                          "  => element (CLASS): test.Outer.TestClass",
-                          "  => annotation type: test.Outer.TestAnnotation",
-                          "  => annotation: @test.Outer.TestAnnotation(classes={<%1$s>})",
-                          "  => annotation value (TYPE_ARRAY): classes={<%1$s>}",
-                          "  => annotation value (TYPE): classes=<%1$s>"),
-                      isJavac ? "error" : "Error"));
+          String expectedMessage =
+              String.format(
+                  NEW_LINES.join(
+                      "Validation trace:",
+                      "  => element (CLASS): test.Outer.TestClass",
+                      "  => annotation type: test.Outer.TestAnnotation",
+                      "  => annotation: @test.Outer.TestAnnotation(classes={<%1$s>})",
+                      "  => annotation value (TYPE_ARRAY): classes={<%1$s>}",
+                      "  => annotation value (TYPE): classes=<%1$s>"),
+                  isJavac ? "error" : "ERROR TYPE: MissingType");
+          if (!isJavac) {
+            expectedMessage =
+                NEW_LINES.join(
+                    expectedMessage,
+                    "  => type (ERROR annotation value type): error.NonExistentClass");
+          }
+          assertThat(exception).hasMessageThat().contains(expectedMessage);
         });
   }
 
@@ -533,20 +538,25 @@
                   () -> superficialValidation.validateElement(parameter));
           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
-          assertThat(exception)
-              .hasMessageThat()
-              .contains(
-                  String.format(
-                      NEW_LINES.join(
-                          "Validation trace:",
-                          "  => element (CLASS): test.Outer.TestClass",
-                          "  => element (CONSTRUCTOR): TestClass(java.lang.String)",
-                          "  => element (PARAMETER): strParam",
-                          "  => annotation type: test.Outer.TestAnnotation",
-                          "  => annotation: @test.Outer.TestAnnotation(classes={<%1$s>})",
-                          "  => annotation value (TYPE_ARRAY): classes={<%1$s>}",
-                          "  => annotation value (TYPE): classes=<%1$s>"),
-                      isJavac ? "error" : "Error"));
+          String expectedMessage =
+              String.format(
+                  NEW_LINES.join(
+                      "Validation trace:",
+                      "  => element (CLASS): test.Outer.TestClass",
+                      "  => element (CONSTRUCTOR): TestClass(java.lang.String)",
+                      "  => element (PARAMETER): strParam",
+                      "  => annotation type: test.Outer.TestAnnotation",
+                      "  => annotation: @test.Outer.TestAnnotation(classes={<%1$s>})",
+                      "  => annotation value (TYPE_ARRAY): classes={<%1$s>}",
+                      "  => annotation value (TYPE): classes=<%1$s>"),
+                  isJavac ? "error" : "ERROR TYPE: MissingType");
+          if (!isJavac) {
+            expectedMessage =
+                NEW_LINES.join(
+                    expectedMessage,
+                    "  => type (ERROR annotation value type): error.NonExistentClass");
+          }
+          assertThat(exception).hasMessageThat().contains(expectedMessage);
         });
   }
 
diff --git a/javatests/dagger/internal/codegen/XTypesStripTypeNameTest.java b/javatests/dagger/internal/codegen/XTypesStripTypeNameTest.java
index 8a97b47..8c23102 100644
--- a/javatests/dagger/internal/codegen/XTypesStripTypeNameTest.java
+++ b/javatests/dagger/internal/codegen/XTypesStripTypeNameTest.java
@@ -16,21 +16,15 @@
 
 package dagger.internal.codegen;
 
-import static androidx.room.compiler.processing.util.ProcessorTestExtKt.runProcessorTest;
 import static com.google.common.truth.Truth.assertThat;
 import static dagger.internal.codegen.extension.DaggerCollectors.onlyElement;
 import static dagger.internal.codegen.xprocessing.XTypes.stripVariances;
 
 import androidx.room.compiler.processing.XMethodElement;
-import androidx.room.compiler.processing.XProcessingEnvConfig;
 import androidx.room.compiler.processing.XTypeElement;
 import androidx.room.compiler.processing.util.Source;
-import androidx.room.compiler.processing.util.XTestInvocation;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.squareup.javapoet.TypeName;
 import dagger.testing.compile.CompilerTests;
-import java.util.function.Function;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -149,54 +143,39 @@
 
   @Test
   public void typeVariableSameVariableName() {
-    runTest(
+    CompilerTests.invocationCompiler(
         CompilerTests.javaSource(
-            "Subject",
-            "interface Subject {",
-            "  <T extends Bar> Foo<T> method1();",
-            "  <T extends Baz> Foo<T> method2();",
-            "",
-            "  interface Foo<T> {}",
-            "  interface Bar {}",
-            "  interface Baz {}",
-            "}"),
-        invocation -> {
-          XTypeElement subject = invocation.getProcessingEnv().requireTypeElement("Subject");
-          TypeName method1ReturnTypeName =
-              getDeclaredMethod(subject, "method1").getReturnType().getTypeName();
-          TypeName method2ReturnTypeName =
-              getDeclaredMethod(subject, "method2").getReturnType().getTypeName();
-          assertThat(method1ReturnTypeName).isEqualTo(method2ReturnTypeName);
-          return null;
-        });
+              "Subject",
+              "interface Subject {",
+              "  <T extends Bar> Foo<T> method1();",
+              "  <T extends Baz> Foo<T> method2();",
+              "",
+              "  interface Foo<T> {}",
+              "  interface Bar {}",
+              "  interface Baz {}",
+              "}"))
+        .compile(
+            invocation -> {
+              XTypeElement subject = invocation.getProcessingEnv().requireTypeElement("Subject");
+              TypeName method1ReturnTypeName =
+                  getDeclaredMethod(subject, "method1").getReturnType().getTypeName();
+              TypeName method2ReturnTypeName =
+                  getDeclaredMethod(subject, "method2").getReturnType().getTypeName();
+              assertThat(method1ReturnTypeName).isEqualTo(method2ReturnTypeName);
+            });
   }
 
   private static void assertStrippedWildcardTypeNameEquals(Source source, String strippedTypeName) {
-    runTest(
-        source,
-        invocation -> {
-          XTypeElement subject = invocation.getProcessingEnv().requireTypeElement("Subject");
-          TypeName returnTypeName =
-              getDeclaredMethod(subject, "method").getReturnType().getTypeName();
-          assertThat(stripVariances(returnTypeName).toString().replace("Subject.", ""))
-              .isEqualTo(strippedTypeName);
-          return null;
-        });
-  }
-
-  private static void runTest(Source source, Function<XTestInvocation, Void> handler) {
-    runProcessorTest(
-        ImmutableList.of(source),
-        /* classpath= */ ImmutableList.of(),
-        /* options= */ ImmutableMap.of(),
-        /* javacArguments= */ ImmutableList.of(),
-        /* kotlincArguments= */ ImmutableList.of(
-            ),
-        /* config= */ new XProcessingEnvConfig.Builder().build(),
-        /* handler= */ invocation -> {
-          handler.apply(invocation);
-          return null;
-        });
+    CompilerTests.invocationCompiler(source)
+        .compile(
+            invocation -> {
+              XTypeElement subject = invocation.getProcessingEnv().requireTypeElement("Subject");
+              TypeName returnTypeName =
+                  getDeclaredMethod(subject, "method").getReturnType().getTypeName();
+              assertThat(stripVariances(returnTypeName).toString().replace("Subject.", ""))
+                  .isEqualTo(strippedTypeName);
+            }
+        );
   }
 
   private static XMethodElement getDeclaredMethod(XTypeElement typeElement, String jvmName) {
diff --git a/javatests/dagger/internal/codegen/bindinggraphvalidation/BUILD b/javatests/dagger/internal/codegen/bindinggraphvalidation/BUILD
index ce7197a..0a1873c 100644
--- a/javatests/dagger/internal/codegen/bindinggraphvalidation/BUILD
+++ b/javatests/dagger/internal/codegen/bindinggraphvalidation/BUILD
@@ -25,6 +25,7 @@
     srcs = glob(["*.java"]),
     functional = False,
     javacopts = DOCLINT_HTML_AND_SYNTAX,
+    shard_count = 3,
     deps = [
         "//java/dagger/internal/codegen/bindinggraphvalidation",
         "//java/dagger/internal/codegen/xprocessing",
diff --git a/tools/bazel_compat.bzl b/tools/bazel_compat.bzl
index bc8b04a..9660588 100644
--- a/tools/bazel_compat.bzl
+++ b/tools/bazel_compat.bzl
@@ -12,14 +12,18 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"""Macros for building with Bazel.
-"""
+# Description:
+#    Macros for building with Bazel.
 
 load("//third_party/kotlin/build_extensions:rules.bzl", "kt_android_library")
+load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library")
 
 def compat_kt_android_library(name, **kwargs):
     bazel_kt_android_library(name, kwargs)
 
+def compat_kt_jvm_library(name, **kwargs):
+    bazel_kt_jvm_library(name, kwargs)
+
 def bazel_kt_android_library(name, kwargs):
     """A macro that wraps Bazel's kt_android_library.
 
@@ -63,3 +67,24 @@
         name = "lib{}-src.jar".format(name),
         actual = ":{}_internal_kt-sources.jar".format(name),
     )
+
+def bazel_kt_jvm_library(name, kwargs):
+    """A macro that wraps Bazel's kt_jvm_library.
+
+    This macro wraps Bazel's kt_jvm_library to output the jars files
+    in the expected locations (https://github.com/bazelbuild/rules_kotlin/issues/324).
+
+    Args:
+      name: the name of the library.
+      kwargs: Additional arguments of the library.
+    """
+
+    kt_jvm_library(
+        name = name,
+        **kwargs
+    )
+
+    native.alias(
+        name = "lib{}-src.jar".format(name),
+        actual = ":{}-sources.jar".format(name),
+    )