From 01efed687348d9f53e4a9abd1f7500a6fa0e4aa4 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Fri, 9 Oct 2026 10:38:50 +0200 Subject: [PATCH 01/22] build: Switch to JDK 21 and upgrade Mockito, Robolectric and Error Prone --- .github/workflows/agp-matrix.yml | 2 +- .github/workflows/build.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .../workflows/enforce-license-compliance.yml | 2 +- .github/workflows/format-code.yml | 2 +- .github/workflows/generate-javadocs.yml | 2 +- .../integration-tests-macrobenchmark.yml | 2 +- .github/workflows/integration-tests-size.yml | 2 +- .../integration-tests-ui-critical.yml | 2 +- .github/workflows/integration-tests-ui.yml | 2 +- .github/workflows/release-build.yml | 2 +- .github/workflows/spring-boot-2-matrix.yml | 2 +- .github/workflows/spring-boot-3-matrix.yml | 2 +- .github/workflows/spring-boot-4-matrix.yml | 2 +- .github/workflows/system-tests-backend.yml | 2 +- CONTRIBUTING.md | 2 +- build.gradle.kts | 41 +++++++++++++++++++ gradle/libs.versions.toml | 13 +++--- sentry-android-core/build.gradle.kts | 2 +- .../core/ApplicationNotResponding.java | 2 + .../core/SentryUserFeedbackButton.java | 2 + .../core/performance/AppStartMetrics.java | 2 + .../ApplicationExitIntegrationTestBase.kt | 7 ++-- .../src/test/resources/robolectric.properties | 2 +- sentry-android-fragment/build.gradle.kts | 2 +- sentry-android-navigation/build.gradle.kts | 2 +- sentry-android-navigation3/build.gradle.kts | 2 +- sentry-android-replay/build.gradle.kts | 2 +- sentry-android-sqlite/build.gradle.kts | 2 +- sentry-android-timber/build.gradle.kts | 2 +- .../android/timber/SentryTimberTreeTest.kt | 3 +- sentry-apollo-3/build.gradle.kts | 2 +- sentry-apollo-4/build.gradle.kts | 2 +- sentry-apollo-5/build.gradle.kts | 2 +- sentry-apollo/build.gradle.kts | 2 +- sentry-async-profiler/build.gradle.kts | 2 +- ...AsyncProfilerToSentryProfileConverter.java | 2 +- sentry-compose/build.gradle.kts | 2 +- sentry-graphql-22/build.gradle.kts | 2 +- sentry-graphql-core/build.gradle.kts | 2 +- sentry-graphql/build.gradle.kts | 2 +- sentry-jcache/build.gradle.kts | 2 +- sentry-jdbc/build.gradle.kts | 2 +- .../java/io/sentry/jul/SentryHandler.java | 2 + sentry-kafka/build.gradle.kts | 2 +- .../kafka/SentryKafkaConsumerTracing.java | 2 +- .../io/sentry/kafka/SentryKafkaProducer.java | 6 ++- sentry-ktor-client/build.gradle.kts | 2 +- sentry-launchdarkly-android/build.gradle.kts | 2 +- sentry-launchdarkly-server/build.gradle.kts | 2 +- .../io/sentry/logback/SentryAppender.java | 3 +- sentry-okhttp/build.gradle.kts | 2 +- sentry-openfeature/build.gradle.kts | 2 +- .../OtelContextScopesStorage.java | 2 +- .../SentryOtelThreadLocalStorage.java | 2 + sentry-quartz/build.gradle.kts | 2 +- .../io/sentry/reactor/SentryReactorUtils.java | 4 +- sentry-spotlight/build.gradle.kts | 2 +- sentry-spring-7/build.gradle.kts | 4 +- .../HttpServletRequestSentryUserProvider.java | 5 +-- .../spring7/SentryInitBeanPostProcessor.java | 3 +- .../cache/SentryCacheBeanPostProcessor.java | 4 +- .../spring7/checkin/SentryCheckInAdvice.java | 6 ++- ...SentryCaptureExceptionParameterAdvice.java | 11 +++-- .../graphql/SentryBatchLoaderRegistry.java | 4 +- .../SentryGraphqlBeanPostProcessor.java | 4 +- .../SentryKafkaProducerBeanPostProcessor.java | 4 +- .../kafka/SentryKafkaRecordInterceptor.java | 2 +- .../spring7/tracing/SentrySpanAdvice.java | 6 ++- ...entrySpanClientHttpRequestInterceptor.java | 2 +- .../tracing/SentryTransactionAdvice.java | 8 ++-- .../webflux/SentryWebExceptionHandler.java | 2 +- .../spring/boot4/SentryLog4j2Initializer.java | 3 +- .../SentryOkHttpClientBeanPostProcessor.java | 3 +- .../boot/jakarta/SentryLog4j2Initializer.java | 3 +- .../SentryOkHttpClientBeanPostProcessor.java | 3 +- sentry-spring-jakarta/build.gradle.kts | 2 +- .../HttpServletRequestSentryUserProvider.java | 5 +-- .../jakarta/SentryInitBeanPostProcessor.java | 3 +- .../cache/SentryCacheBeanPostProcessor.java | 4 +- ...SentryCaptureExceptionParameterAdvice.java | 4 +- .../graphql/SentryBatchLoaderRegistry.java | 4 +- .../SentryGraphqlBeanPostProcessor.java | 4 +- .../SentryKafkaProducerBeanPostProcessor.java | 4 +- .../kafka/SentryKafkaRecordInterceptor.java | 2 +- ...entrySpanClientHttpRequestInterceptor.java | 2 +- .../tracing/SentryTransactionAdvice.java | 2 +- sentry-spring/build.gradle.kts | 2 +- .../kafka/SentryKafkaRecordInterceptor.java | 2 +- .../tracing/SentryTransactionAdvice.java | 2 +- sentry-system-test-support/build.gradle.kts | 2 +- sentry-test-support/build.gradle.kts | 2 +- sentry/build.gradle.kts | 5 ++- sentry/src/main/java/io/sentry/Baggage.java | 7 ++++ .../src/main/java/io/sentry/Breadcrumb.java | 4 ++ .../java/io/sentry/CombinedContextsView.java | 2 +- sentry/src/main/java/io/sentry/DateUtils.java | 4 +- .../java/io/sentry/DefaultSpanFactory.java | 2 +- .../main/java/io/sentry/DiagnosticLogger.java | 2 + .../java/io/sentry/DirectoryProcessor.java | 2 +- .../main/java/io/sentry/ExternalOptions.java | 3 +- sentry/src/main/java/io/sentry/Hint.java | 2 +- .../main/java/io/sentry/MonitorContexts.java | 3 ++ .../main/java/io/sentry/ReplayRecording.java | 3 +- .../main/java/io/sentry/SamplingContext.java | 2 +- sentry/src/main/java/io/sentry/Scope.java | 4 +- .../src/main/java/io/sentry/SentryClient.java | 2 +- .../java/io/sentry/SentryEnvelopeItem.java | 5 ++- .../io/sentry/SentryExceptionFactory.java | 3 +- .../main/java/io/sentry/SentryOptions.java | 2 + .../java/io/sentry/SentryThreadFactory.java | 2 + .../src/main/java/io/sentry/SentryTracer.java | 2 +- .../src/main/java/io/sentry/SpanContext.java | 2 + .../io/sentry/SynchronizedCollection.java | 4 ++ .../src/main/java/io/sentry/TraceContext.java | 2 +- .../UncaughtExceptionHandlerIntegration.java | 2 + .../sentry/cache/PersistingScopeObserver.java | 2 + .../ExceptionMechanismException.java | 7 ++++ .../featureflags/FeatureFlagBuffer.java | 5 ++- .../modules/ManifestModulesLoader.java | 2 +- .../main/java/io/sentry/logger/LoggerApi.java | 7 ++-- .../java/io/sentry/metrics/MetricsApi.java | 7 ++-- .../java/io/sentry/protocol/Contexts.java | 5 +++ .../java/io/sentry/rrweb/RRWebEventType.java | 4 ++ .../rrweb/RRWebIncrementalSnapshotEvent.java | 4 ++ .../sentry/rrweb/RRWebInteractionEvent.java | 4 ++ .../main/java/io/sentry/time/Deadline.java | 2 + .../main/java/io/sentry/util/HttpUtils.java | 2 + .../main/java/io/sentry/util/InitUtil.java | 2 + .../sentry/util/JsonSerializationUtils.java | 2 +- .../src/main/java/io/sentry/util/Objects.java | 2 + .../main/java/io/sentry/util/Platform.java | 3 +- .../java/io/sentry/util/UUIDGenerator.java | 2 +- .../util/network/NetworkBodyParser.java | 6 ++- .../sentry/vendor/gson/stream/JsonReader.java | 2 + .../test/java/io/sentry/OutboxSenderTest.kt | 5 ++- .../io/sentry/PreviousSessionFinalizerTest.kt | 3 +- 137 files changed, 291 insertions(+), 160 deletions(-) diff --git a/.github/workflows/agp-matrix.yml b/.github/workflows/agp-matrix.yml index 6b5f27fcd21..38ac14e0d01 100644 --- a/.github/workflows/agp-matrix.yml +++ b/.github/workflows/agp-matrix.yml @@ -36,7 +36,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Setup Gradle uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6ad77331434..955803c7cf3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' # Workaround for https://github.com/gradle/actions/issues/21 to use config cache - name: Cache buildSrc diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c94bcf3efd3..c8ddd2dfeb8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -28,7 +28,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Setup Gradle uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 diff --git a/.github/workflows/enforce-license-compliance.yml b/.github/workflows/enforce-license-compliance.yml index 8d37523888d..3b4726150be 100644 --- a/.github/workflows/enforce-license-compliance.yml +++ b/.github/workflows/enforce-license-compliance.yml @@ -17,7 +17,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/format-code.yml b/.github/workflows/format-code.yml index d236a64b0ce..56972bdbd30 100644 --- a/.github/workflows/format-code.yml +++ b/.github/workflows/format-code.yml @@ -16,7 +16,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Setup Gradle uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 diff --git a/.github/workflows/generate-javadocs.yml b/.github/workflows/generate-javadocs.yml index 7cb5c903ca3..b023883240e 100644 --- a/.github/workflows/generate-javadocs.yml +++ b/.github/workflows/generate-javadocs.yml @@ -17,7 +17,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Setup Gradle uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 diff --git a/.github/workflows/integration-tests-macrobenchmark.yml b/.github/workflows/integration-tests-macrobenchmark.yml index 56dc9f04973..5389f2eb01a 100644 --- a/.github/workflows/integration-tests-macrobenchmark.yml +++ b/.github/workflows/integration-tests-macrobenchmark.yml @@ -26,7 +26,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Setup Gradle uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 diff --git a/.github/workflows/integration-tests-size.yml b/.github/workflows/integration-tests-size.yml index ebdad2a4d9a..49fe70fabae 100644 --- a/.github/workflows/integration-tests-size.yml +++ b/.github/workflows/integration-tests-size.yml @@ -26,7 +26,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: "temurin" - java-version: "17" + java-version: "21" # Workaround for https://github.com/gradle/actions/issues/21 to use config cache - name: Cache buildSrc diff --git a/.github/workflows/integration-tests-ui-critical.yml b/.github/workflows/integration-tests-ui-critical.yml index dce506124d0..821b4230593 100644 --- a/.github/workflows/integration-tests-ui-critical.yml +++ b/.github/workflows/integration-tests-ui-critical.yml @@ -33,7 +33,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Setup Gradle uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 diff --git a/.github/workflows/integration-tests-ui.yml b/.github/workflows/integration-tests-ui.yml index e1f11ac1f8c..cda4e801c8a 100644 --- a/.github/workflows/integration-tests-ui.yml +++ b/.github/workflows/integration-tests-ui.yml @@ -30,7 +30,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Setup Gradle uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index c5038af6f9f..8f07d36d73a 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -23,7 +23,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Setup Gradle uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 diff --git a/.github/workflows/spring-boot-2-matrix.yml b/.github/workflows/spring-boot-2-matrix.yml index 0ad89bd9caa..3617c8ae6ed 100644 --- a/.github/workflows/spring-boot-2-matrix.yml +++ b/.github/workflows/spring-boot-2-matrix.yml @@ -48,7 +48,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' # Workaround for https://github.com/gradle/actions/issues/21 to use config cache - name: Cache buildSrc diff --git a/.github/workflows/spring-boot-3-matrix.yml b/.github/workflows/spring-boot-3-matrix.yml index 8b68a33e658..4f4c0ce7101 100644 --- a/.github/workflows/spring-boot-3-matrix.yml +++ b/.github/workflows/spring-boot-3-matrix.yml @@ -48,7 +48,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' # Workaround for https://github.com/gradle/actions/issues/21 to use config cache - name: Cache buildSrc diff --git a/.github/workflows/spring-boot-4-matrix.yml b/.github/workflows/spring-boot-4-matrix.yml index c353f575cc9..d8f679190ec 100644 --- a/.github/workflows/spring-boot-4-matrix.yml +++ b/.github/workflows/spring-boot-4-matrix.yml @@ -48,7 +48,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' # Workaround for https://github.com/gradle/actions/issues/21 to use config cache - name: Cache buildSrc diff --git a/.github/workflows/system-tests-backend.yml b/.github/workflows/system-tests-backend.yml index f77fd18f821..921b28450eb 100644 --- a/.github/workflows/system-tests-backend.yml +++ b/.github/workflows/system-tests-backend.yml @@ -121,7 +121,7 @@ jobs: uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Setup Gradle uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f4354c72a89..7d4abc716ad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ We suggest opening an issue to discuss bigger changes before investing on a big # Requirements -The project requires you to run JDK 17. +The project requires you to run JDK 21. ## Android diff --git a/build.gradle.kts b/build.gradle.kts index 52e17b1d309..acd50995df0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,6 +29,10 @@ plugins { alias(libs.plugins.sentry) apply false } +check(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)) { + "This build requires JDK 21 or newer, but runs on JDK ${JavaVersion.current()}." +} + buildscript { repositories { google() @@ -112,6 +116,34 @@ allprojects { subprojects { apply { plugin("io.sentry.spotless") } + // Mockito 5 and mockito-kotlin 5+ are built for Java 11. Test code is never published, so it + // compiles for at least Java 11 while the published code keeps its own target. Runs in + // afterEvaluate, as most modules pin the JVM target of all their compile tasks. + afterEvaluate { + tasks.withType().matching { it.name.contains("Test") }.configureEach { + if (JavaVersion.toVersion(targetCompatibility) < JavaVersion.VERSION_11) { + sourceCompatibility = JavaVersion.VERSION_11.toString() + targetCompatibility = JavaVersion.VERSION_11.toString() + } + } + tasks.withType().matching { it.name.contains("Test") }.configureEach { + if (compilerOptions.jvmTarget.get() < org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11) { + compilerOptions.jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11) + } + } + } + + listOf("com.android.library", "com.android.application").forEach { pluginId -> + plugins.withId(pluginId) { + // Robolectric's SDK 37 sandbox (the default, as targetSdk is 37) reflectively writes + // FileDescriptor fields in ApplicationSharedMemory; without this, setup fails with + // "Failed to interact with raw FileDescriptor internals". + tasks.withType().configureEach { + jvmArgs("--add-opens=java.base/java.io=ALL-UNNAMED") + } + } + } + plugins.withId(Config.QualityPlugins.detektPlugin) { configure { buildUponDefaultConfig = true @@ -166,6 +198,15 @@ subprojects { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } + + // Compile against the class library of the target Java version instead of the build + // JDK's, so newer JDK APIs (e.g. List.getFirst()) can't leak into published bytecode. + val javaExtension = the() + tasks.named("compileJava") { + options.release.set( + provider { javaExtension.targetCompatibility.majorVersion.toInt() } + ) + } } // AGP 9 defaults Android modules to Java 11. Pin the published library modules back diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5d79bda786c..aa598b8c35b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -64,7 +64,7 @@ buildconfig = { id = "com.github.gmazzo.buildconfig", version = "5.6.5" } dokka = { id = "org.jetbrains.dokka", version = "2.0.0" } dokka-javadoc = { id = "org.jetbrains.dokka-javadoc", version = "2.0.0" } binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version = "0.13.0" } -errorprone = { id = "net.ltgt.errorprone", version = "3.0.1" } +errorprone = { id = "net.ltgt.errorprone", version = "5.1.1" } gradle-versions = { id = "com.github.ben-manes.versions", version = "0.42.0" } spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } detekt = { id = "io.gitlab.arturbosch.detekt", version = "1.23.8" } @@ -129,7 +129,7 @@ caffeine-jcache = { module = "com.github.ben-manes.caffeine:jcache", version = " coil-compose = { module = "io.coil-kt:coil-compose", version = "2.6.0" } commons-compress = {module = "org.apache.commons:commons-compress", version = "1.28.0"} context-propagation = { module = "io.micrometer:context-propagation", version = "1.1.0" } -errorprone-core = { module = "com.google.errorprone:error_prone_core", version = "2.11.0" } +errorprone-core = { module = "com.google.errorprone:error_prone_core", version = "2.50.0" } feign-core = { module = "io.github.openfeign:feign-core", version.ref = "feign" } feign-gson = { module = "io.github.openfeign:feign-gson", version.ref = "feign" } graphql-java17 = { module = "com.graphql-java:graphql-java", version = "17.3" } @@ -154,7 +154,7 @@ lottie-compose = { module = "com.airbnb.android:lottie-compose", version = "6.7. logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } nopen-annotations = { module = "com.jakewharton.nopen:nopen-annotations", version.ref = "nopen" } nopen-checker = { module = "com.jakewharton.nopen:nopen-checker", version.ref = "nopen" } -nullaway = { module = "com.uber.nullaway:nullaway", version = "0.9.5" } +nullaway = { module = "com.uber.nullaway:nullaway", version = "0.14.2" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } okhttp-bom = { module = "com.squareup.okhttp3:okhttp-bom", version.ref = "okhttp" } openfeature = { module = "dev.openfeature:sdk", version.ref = "openfeature" } @@ -273,15 +273,14 @@ hsqldb = { module = "org.hsqldb:hsqldb", version = "2.6.1" } javafaker = { module = "com.github.javafaker:javafaker", version = "1.0.2" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" } leakcanary-instrumentation = { module = "com.squareup.leakcanary:leakcanary-android-instrumentation", version = "2.14" } -mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version = "4.1.0" } -mockito-kotlin-spring7 = { module = "org.mockito.kotlin:mockito-kotlin", version = "6.0.0" } -mockito-inline = { module = "org.mockito:mockito-inline", version = "4.8.0" } +mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version = "6.4.0" } +mockito-core = { module = "org.mockito:mockito-core", version = "5.24.0" } msgpack = { module = "org.msgpack:msgpack-core", version = "0.9.8" } okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okhttp" } # apollo-runtime 5.x pulls in okhttp 5.x; mockwebserver 4.x is incompatible with that classpath okhttp-mockwebserver5 = { module = "com.squareup.okhttp3:mockwebserver", version = "5.3.0" } okio = { module = "com.squareup.okio:okio", version = "1.13.0" } -roboelectric = { module = "org.robolectric:robolectric", version = "4.15" } +roboelectric = { module = "org.robolectric:robolectric", version = "4.17" } [bundles] androidx-room2 = ["androidx-room-runtime", "androidx-room-ktx"] diff --git a/sentry-android-core/build.gradle.kts b/sentry-android-core/build.gradle.kts index 0d7f16af199..4facf6f4c23 100644 --- a/sentry-android-core/build.gradle.kts +++ b/sentry-android-core/build.gradle.kts @@ -118,7 +118,7 @@ dependencies { testImplementation(libs.awaitility.kotlin) testImplementation(libs.google.truth) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(projects.sentryTestSupport) testImplementation(projects.sentrySpotlight) testImplementation(projects.sentryAndroidFragment) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationNotResponding.java b/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationNotResponding.java index 7b21c2e392c..9d76cdf298b 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationNotResponding.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationNotResponding.java @@ -17,6 +17,8 @@ final class ApplicationNotResponding extends RuntimeException { private static final long serialVersionUID = 252541144579117016L; + // Never serialized. + @SuppressWarnings("serial") private final @Nullable Thread thread; ApplicationNotResponding(final @Nullable String message) { diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java b/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java index f842f18674b..0ae5583253e 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java @@ -13,6 +13,8 @@ /** * @deprecated `SentryUserFeedbackButton` will be removed in the next major version */ +// Constructors call overridable methods; making them final would break the public API. +@SuppressWarnings("this-escape") @Deprecated public class SentryUserFeedbackButton extends Button { diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java b/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java index 82376a75d8b..090ca2d2669 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java @@ -50,6 +50,8 @@ *

This class is also responsible for - determining the app start type (cold, warm) - determining * if the app was launched in foreground */ +// Constructors call overridable methods; making them final would break the public API. +@SuppressWarnings("this-escape") @ApiStatus.Internal public class AppStartMetrics extends ActivityLifecycleCallbacksAdapter { public interface HeadlessAppStartListener { diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt index 82cf1c25c9c..3fd6140f41c 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt @@ -27,6 +27,7 @@ import org.junit.Rule import org.junit.rules.TemporaryFolder import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull +import org.mockito.kotlin.anyVararg import org.mockito.kotlin.argThat import org.mockito.kotlin.atMost import org.mockito.kotlin.check @@ -316,7 +317,7 @@ abstract class ApplicationExitIntegrationTestBase { .log( any(), argThat { startsWith("Timed out waiting to flush previous session to its own file.") }, - any(), + anyVararg(), ) } @@ -337,7 +338,7 @@ abstract class ApplicationExitIntegrationTestBase { .log( any(), argThat { startsWith("Timed out waiting to flush previous session to its own file.") }, - any(), + anyVararg(), ) verify(fixture.scopes).captureEvent(any(), any()) } @@ -354,7 +355,7 @@ abstract class ApplicationExitIntegrationTestBase { .log( any(), argThat { startsWith("Timed out waiting to flush previous session to its own file.") }, - any(), + anyVararg(), ) assertTrue((fixture.options.envelopeDiskCache as EnvelopeCache).waitPreviousSessionFlush()) } diff --git a/sentry-android-core/src/test/resources/robolectric.properties b/sentry-android-core/src/test/resources/robolectric.properties index c216eeab9dc..c0f2ddf599d 100644 --- a/sentry-android-core/src/test/resources/robolectric.properties +++ b/sentry-android-core/src/test/resources/robolectric.properties @@ -1,2 +1,2 @@ -sdk=21 +sdk=23 application=io.sentry.android.core.ApplicationStub diff --git a/sentry-android-fragment/build.gradle.kts b/sentry-android-fragment/build.gradle.kts index e613f1fd5bb..3c7a0404970 100644 --- a/sentry-android-fragment/build.gradle.kts +++ b/sentry-android-fragment/build.gradle.kts @@ -70,7 +70,7 @@ dependencies { testImplementation(libs.androidx.fragment.ktx) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) } tasks.withType().configureEach { diff --git a/sentry-android-navigation/build.gradle.kts b/sentry-android-navigation/build.gradle.kts index 19b9b3c753f..ddc6d6f4161 100644 --- a/sentry-android-navigation/build.gradle.kts +++ b/sentry-android-navigation/build.gradle.kts @@ -71,7 +71,7 @@ dependencies { testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.roboelectric) testImplementation(libs.androidx.core) diff --git a/sentry-android-navigation3/build.gradle.kts b/sentry-android-navigation3/build.gradle.kts index da7ad9f36f4..b9d02bb49d4 100644 --- a/sentry-android-navigation3/build.gradle.kts +++ b/sentry-android-navigation3/build.gradle.kts @@ -67,7 +67,7 @@ dependencies { testImplementation(libs.androidx.test.core) testImplementation(libs.androidx.test.ext.junit) testImplementation(libs.google.truth) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.mockito.kotlin) testImplementation(libs.roboelectric) } diff --git a/sentry-android-replay/build.gradle.kts b/sentry-android-replay/build.gradle.kts index 1318f7767c9..1a92f9a0b36 100644 --- a/sentry-android-replay/build.gradle.kts +++ b/sentry-android-replay/build.gradle.kts @@ -85,7 +85,7 @@ dependencies { testImplementation(libs.awaitility.kotlin) testImplementation(libs.google.truth) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.androidx.compose.ui) testImplementation(libs.androidx.compose.foundation) testImplementation(libs.androidx.compose.foundation.layout) diff --git a/sentry-android-sqlite/build.gradle.kts b/sentry-android-sqlite/build.gradle.kts index fd15526fcbe..38ea832082f 100644 --- a/sentry-android-sqlite/build.gradle.kts +++ b/sentry-android-sqlite/build.gradle.kts @@ -79,7 +79,7 @@ dependencies { testImplementation(libs.androidx.sqlite) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) } tasks.withType().configureEach { diff --git a/sentry-android-timber/build.gradle.kts b/sentry-android-timber/build.gradle.kts index f66c1a8a96b..92f14b37c8c 100644 --- a/sentry-android-timber/build.gradle.kts +++ b/sentry-android-timber/build.gradle.kts @@ -80,7 +80,7 @@ dependencies { testImplementation(libs.kotlin.test.junit) testImplementation(libs.androidx.test.ext.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) } tasks.withType().configureEach { diff --git a/sentry-android-timber/src/test/java/io/sentry/android/timber/SentryTimberTreeTest.kt b/sentry-android-timber/src/test/java/io/sentry/android/timber/SentryTimberTreeTest.kt index 8ef43a9b691..3fd80e495fd 100644 --- a/sentry-android-timber/src/test/java/io/sentry/android/timber/SentryTimberTreeTest.kt +++ b/sentry-android-timber/src/test/java/io/sentry/android/timber/SentryTimberTreeTest.kt @@ -14,6 +14,7 @@ import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertNull import org.mockito.kotlin.any +import org.mockito.kotlin.anyVararg import org.mockito.kotlin.check import org.mockito.kotlin.eq import org.mockito.kotlin.mock @@ -326,7 +327,7 @@ class SentryTimberTreeTest { fun `Tree adds a log if min level is higher`() { val sut = fixture.getSut() sut.e(Throwable("test")) - verify(fixture.logs).log(any(), any(), any(), any()) + verify(fixture.logs).log(any(), any(), any(), anyVararg()) } @Test diff --git a/sentry-apollo-3/build.gradle.kts b/sentry-apollo-3/build.gradle.kts index 357d5224495..9f07593e5f6 100644 --- a/sentry-apollo-3/build.gradle.kts +++ b/sentry-apollo-3/build.gradle.kts @@ -36,7 +36,7 @@ dependencies { testImplementation(libs.kotlin.test.junit) testImplementation(libs.kotlinx.coroutines) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.okhttp.mockwebserver) } diff --git a/sentry-apollo-4/build.gradle.kts b/sentry-apollo-4/build.gradle.kts index 078d26b8ff8..7534347c4e1 100644 --- a/sentry-apollo-4/build.gradle.kts +++ b/sentry-apollo-4/build.gradle.kts @@ -37,7 +37,7 @@ dependencies { testImplementation(libs.kotlinx.coroutines) testImplementation(libs.kotlinx.coroutines.test) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.okhttp.mockwebserver) testImplementation("org.jetbrains.kotlin:kotlin-reflect:2.0.0") } diff --git a/sentry-apollo-5/build.gradle.kts b/sentry-apollo-5/build.gradle.kts index e4cd7dd0345..2f93f36e739 100644 --- a/sentry-apollo-5/build.gradle.kts +++ b/sentry-apollo-5/build.gradle.kts @@ -37,7 +37,7 @@ dependencies { testImplementation(libs.kotlinx.coroutines) testImplementation(libs.kotlinx.coroutines.test) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.okhttp.mockwebserver5) } diff --git a/sentry-apollo/build.gradle.kts b/sentry-apollo/build.gradle.kts index 570214e60b8..8da93b3c77c 100644 --- a/sentry-apollo/build.gradle.kts +++ b/sentry-apollo/build.gradle.kts @@ -37,7 +37,7 @@ dependencies { testImplementation(libs.kotlin.test.junit) testImplementation(libs.kotlinx.coroutines) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.okhttp.mockwebserver) } diff --git a/sentry-async-profiler/build.gradle.kts b/sentry-async-profiler/build.gradle.kts index 17454baa662..976452f94aa 100644 --- a/sentry-async-profiler/build.gradle.kts +++ b/sentry-async-profiler/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { testImplementation(projects.sentryTestSupport) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) } tasks.withType().configureEach { diff --git a/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java b/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java index 718fae422f7..a0ce94c08ec 100644 --- a/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java +++ b/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java @@ -83,7 +83,7 @@ private class ProfileEventVisitor implements EventCollector.Visitor { private final @NotNull JfrReader jfr; private final @NotNull Arguments args; - public ProfileEventVisitor( + ProfileEventVisitor( @NotNull SentryProfile sentryProfile, @NotNull SentryStackTraceFactory stackTraceFactory, @NotNull JfrReader jfr, diff --git a/sentry-compose/build.gradle.kts b/sentry-compose/build.gradle.kts index 394885df1b8..19fce9f95b5 100644 --- a/sentry-compose/build.gradle.kts +++ b/sentry-compose/build.gradle.kts @@ -69,7 +69,7 @@ kotlin { implementation(libs.androidx.test.runner) implementation(libs.google.truth) implementation(libs.kotlin.test.junit) - implementation(libs.mockito.inline) + implementation(libs.mockito.core) implementation(libs.mockito.kotlin) implementation(libs.roboelectric) } diff --git a/sentry-graphql-22/build.gradle.kts b/sentry-graphql-22/build.gradle.kts index 32db28fae8f..ba36db3e40b 100644 --- a/sentry-graphql-22/build.gradle.kts +++ b/sentry-graphql-22/build.gradle.kts @@ -35,7 +35,7 @@ dependencies { testImplementation(libs.graphql.java22) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.okhttp) testImplementation(libs.okhttp.mockwebserver) testImplementation(libs.springboot.starter.graphql) diff --git a/sentry-graphql-core/build.gradle.kts b/sentry-graphql-core/build.gradle.kts index 34f71ab9cfb..5044127fb42 100644 --- a/sentry-graphql-core/build.gradle.kts +++ b/sentry-graphql-core/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { testImplementation(libs.graphql.java17) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.okhttp) testImplementation(libs.okhttp.mockwebserver) testImplementation(libs.springboot.starter.graphql) diff --git a/sentry-graphql/build.gradle.kts b/sentry-graphql/build.gradle.kts index d92dc52c6d7..484c2ed8499 100644 --- a/sentry-graphql/build.gradle.kts +++ b/sentry-graphql/build.gradle.kts @@ -35,7 +35,7 @@ dependencies { testImplementation(libs.graphql.java17) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.okhttp) testImplementation(libs.okhttp.mockwebserver) testImplementation(libs.springboot.starter.graphql) diff --git a/sentry-jcache/build.gradle.kts b/sentry-jcache/build.gradle.kts index b388f35881f..3c8829eaf04 100644 --- a/sentry-jcache/build.gradle.kts +++ b/sentry-jcache/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { testImplementation(kotlin(Config.kotlinStdLib)) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) } tasks.withType().configureEach { diff --git a/sentry-jdbc/build.gradle.kts b/sentry-jdbc/build.gradle.kts index e2a7f573138..425f707083d 100644 --- a/sentry-jdbc/build.gradle.kts +++ b/sentry-jdbc/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { testImplementation(libs.hsqldb) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) } tasks.withType().configureEach { diff --git a/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java b/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java index 4442052dd41..c0eb576ce77 100644 --- a/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java +++ b/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java @@ -40,6 +40,8 @@ import org.slf4j.MDC; /** Logging handler in charge of sending the java.util.logging records to a Sentry server. */ +// Constructors call overridable methods; making them final would break the public API. +@SuppressWarnings("this-escape") @Open public class SentryHandler extends Handler { public static final String MECHANISM_TYPE = "JulSentryHandler"; diff --git a/sentry-kafka/build.gradle.kts b/sentry-kafka/build.gradle.kts index 0d543bad270..94ce4d528c1 100644 --- a/sentry-kafka/build.gradle.kts +++ b/sentry-kafka/build.gradle.kts @@ -30,7 +30,7 @@ dependencies { testImplementation(kotlin(Config.kotlinStdLib)) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.kafka.clients) } diff --git a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java index dbce760de99..a45505f1019 100644 --- a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java +++ b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java @@ -247,7 +247,7 @@ private void finishTransaction( try { final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr); - final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis()); + final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis()); final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000); return latencyMs >= 0 ? latencyMs : null; } catch (NumberFormatException ignored) { diff --git a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java index bcc538e339c..573038d5ee9 100644 --- a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java +++ b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java @@ -114,7 +114,8 @@ static final class SentryProducerHandler implements InvocationHandler { } @Override - @SuppressWarnings("unchecked") + // Proxy equals() is identity-based. + @SuppressWarnings({"unchecked", "ReferenceEquality"}) public @Nullable Object invoke( final @NotNull Object proxy, final @NotNull Method method, final @Nullable Object[] args) throws Throwable { @@ -236,7 +237,8 @@ private void maybeInjectHeaders(final @NotNull Headers headers, final @Nullable headers.remove(SENTRY_ENQUEUED_TIME_HEADER); headers.add( SENTRY_ENQUEUED_TIME_HEADER, - DateUtils.doubleToBigDecimal(DateUtils.millisToSeconds(System.currentTimeMillis())) + DateUtils.doubleToBigDecimal( + DateUtils.millisToSeconds((double) System.currentTimeMillis())) .toString() .getBytes(StandardCharsets.UTF_8)); } catch (Throwable t) { diff --git a/sentry-ktor-client/build.gradle.kts b/sentry-ktor-client/build.gradle.kts index a1eb9150d6f..2d17fc7ce53 100644 --- a/sentry-ktor-client/build.gradle.kts +++ b/sentry-ktor-client/build.gradle.kts @@ -36,7 +36,7 @@ dependencies { testImplementation(projects.sentryTestSupport) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.ktor.client.core) testImplementation(libs.ktor.client.java) testImplementation(libs.okhttp.mockwebserver) diff --git a/sentry-launchdarkly-android/build.gradle.kts b/sentry-launchdarkly-android/build.gradle.kts index ddc982e9d6a..df081b21213 100644 --- a/sentry-launchdarkly-android/build.gradle.kts +++ b/sentry-launchdarkly-android/build.gradle.kts @@ -70,6 +70,6 @@ dependencies { testImplementation(libs.androidx.test.ext.junit) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.launchdarkly.android) } diff --git a/sentry-launchdarkly-server/build.gradle.kts b/sentry-launchdarkly-server/build.gradle.kts index 95aba9faaf5..1e9c074226f 100644 --- a/sentry-launchdarkly-server/build.gradle.kts +++ b/sentry-launchdarkly-server/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { testImplementation(kotlin(Config.kotlinStdLib)) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.launchdarkly.server) } diff --git a/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java b/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java index 722845e2d70..66f61a182e5 100644 --- a/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java +++ b/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java @@ -197,7 +197,8 @@ protected void captureLog(@NotNull ILoggingEvent loggingEvent) { final @NotNull SentryLogParameters params = SentryLogParameters.create(attributes); params.setOrigin("auto.log.logback"); - Sentry.logger().log(sentryLevel, params, formattedMessage, arguments); + Sentry.logger() + .log(sentryLevel, params, formattedMessage, arguments != null ? arguments : new Object[0]); } @SuppressWarnings("deprecation") diff --git a/sentry-okhttp/build.gradle.kts b/sentry-okhttp/build.gradle.kts index 5abd1cf26b9..0d2b2e2d2ec 100644 --- a/sentry-okhttp/build.gradle.kts +++ b/sentry-okhttp/build.gradle.kts @@ -36,7 +36,7 @@ dependencies { testImplementation(projects.sentryTestSupport) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.okhttp) testImplementation(libs.okhttp.mockwebserver) testImplementation(libs.google.truth) diff --git a/sentry-openfeature/build.gradle.kts b/sentry-openfeature/build.gradle.kts index b079ead1fc5..56561810334 100644 --- a/sentry-openfeature/build.gradle.kts +++ b/sentry-openfeature/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { testImplementation(kotlin(Config.kotlinStdLib)) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.openfeature) } diff --git a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java index 143ebb6c16d..ad70d2346a8 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java +++ b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java @@ -17,7 +17,7 @@ public final class OtelContextScopesStorage implements IScopesStorage { @Override public void init() { - /** + /* * We're currently overriding the storage mechanism to allow for cleanup of non closed OTel * scopes. These happen when using e.g. Sentry static API due to getCurrentScopes() invoking * Context.makeCurrent and then ignoring the returned lifecycle token (OTel Scope). After fixing diff --git a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java index e44afc5a2dc..feec48908fd 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java +++ b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java @@ -29,6 +29,8 @@ public final class SentryOtelThreadLocalStorage implements ContextStorage { private static final ThreadLocal THREAD_LOCAL_STORAGE = new ThreadLocal<>(); + // Same identity check as OpenTelemetry's ThreadLocalContextStorage. + @SuppressWarnings("ReferenceEquality") @Override public Scope attach(Context toAttach) { if (toAttach == null) { diff --git a/sentry-quartz/build.gradle.kts b/sentry-quartz/build.gradle.kts index f4f0d9d07d2..bb04435f1d9 100644 --- a/sentry-quartz/build.gradle.kts +++ b/sentry-quartz/build.gradle.kts @@ -33,7 +33,7 @@ dependencies { testImplementation(kotlin(Config.kotlinStdLib)) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) } tasks.withType().configureEach { diff --git a/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java b/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java index 16fed92bd01..04d87a8b45b 100644 --- a/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java +++ b/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java @@ -48,7 +48,7 @@ public static Mono withSentryForkedRoots(final @NotNull Mono mono) { */ public static Mono withSentryScopes( final @NotNull Mono mono, final @NotNull IScopes scopes) { - /** + /* * WARNING: Cannot set the scopes as current. It would be used by others to clone again causing * shared scopes and thus leading to issues like unrelated breadcrumbs showing up in events. */ @@ -96,7 +96,7 @@ public static Flux withSentryForkedRoots(final @NotNull Flux flux) { */ public static Flux withSentryScopes( final @NotNull Flux flux, final @NotNull IScopes scopes) { - /** + /* * WARNING: Cannot set the scopes as current. It would be used by others to fork again causing * shared scopes and thus leading to issues like unrelated breadcrumbs showing up in events. */ diff --git a/sentry-spotlight/build.gradle.kts b/sentry-spotlight/build.gradle.kts index a8d538c2e2e..9833a432473 100644 --- a/sentry-spotlight/build.gradle.kts +++ b/sentry-spotlight/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { testImplementation(kotlin(Config.kotlinStdLib)) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(projects.sentryTestSupport) } diff --git a/sentry-spring-7/build.gradle.kts b/sentry-spring-7/build.gradle.kts index 4e5ea54d294..3f1d6d18a02 100644 --- a/sentry-spring-7/build.gradle.kts +++ b/sentry-spring-7/build.gradle.kts @@ -67,8 +67,8 @@ dependencies { testImplementation(libs.context.propagation) testImplementation(libs.graphql.java24) testImplementation(libs.kotlin.test.junit) - testImplementation(libs.mockito.kotlin.spring7) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.kotlin) + testImplementation(libs.mockito.core) testImplementation(libs.springboot4.starter.aspectj) testImplementation(libs.springboot4.starter.graphql) testImplementation(libs.spring.kafka4) diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java b/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java index 44ae584ec17..27720570a2e 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java @@ -25,9 +25,8 @@ public HttpServletRequestSentryUserProvider(final @NotNull SentryOptions options public @Nullable User provideUser() { if (options.getDataCollectionResolver().isUserInfo()) { final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - if (requestAttributes instanceof ServletRequestAttributes) { - final ServletRequestAttributes servletRequestAttributes = - (ServletRequestAttributes) requestAttributes; + if (requestAttributes instanceof ServletRequestAttributes servletRequestAttributes) { + final HttpServletRequest request = servletRequestAttributes.getRequest(); final User user = new User(); diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java index 4b778d68649..b36df8be77b 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java @@ -42,8 +42,7 @@ public SentryInitBeanPostProcessor() { @SuppressWarnings({"unchecked", "deprecation"}) public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, @NotNull final String beanName) throws BeansException { - if (bean instanceof SentryOptions) { - final SentryOptions options = (SentryOptions) bean; + if (bean instanceof SentryOptions options) { if (applicationContext != null) { applicationContext diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java index b6569a9953b..8c755be2dea 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java @@ -16,8 +16,8 @@ public final class SentryCacheBeanPostProcessor implements BeanPostProcessor, Pr @Override public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (bean instanceof CacheManager && !(bean instanceof SentryCacheManagerWrapper)) { - return new SentryCacheManagerWrapper((CacheManager) bean, ScopesAdapter.getInstance()); + if (bean instanceof CacheManager cacheManager && !(bean instanceof SentryCacheManagerWrapper)) { + return new SentryCacheManagerWrapper(cacheManager, ScopesAdapter.getInstance()); } return bean; } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java index e58e0e9dd97..a14f0d4c96a 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java @@ -44,9 +44,11 @@ public SentryCheckInAdvice(final @NotNull IScopes scopes) { } @Override - public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + final @Nullable Object target = invocation.getThis(); final Method mostSpecificMethod = - AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); + AopUtils.getMostSpecificMethod( + invocation.getMethod(), target != null ? target.getClass() : null); @Nullable SentryCheckIn checkInAnnotation = diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java index cb5cba62a4d..f4c630033a8 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java @@ -11,6 +11,7 @@ import org.aopalliance.intercept.MethodInvocation; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.springframework.aop.support.AopUtils; import org.springframework.core.annotation.AnnotationUtils; @@ -33,17 +34,19 @@ public SentryCaptureExceptionParameterAdvice(final @NotNull IScopes scopes) { } @Override - public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + final @Nullable Object target = invocation.getThis(); final Method mostSpecificMethod = - AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); + AopUtils.getMostSpecificMethod( + invocation.getMethod(), target != null ? target.getClass() : null); SentryCaptureExceptionParameter sentryCaptureExceptionParameter = AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCaptureExceptionParameter.class); if (sentryCaptureExceptionParameter != null) { Object[] args = invocation.getArguments(); for (Object arg : args) { - if (arg instanceof Exception) { - captureException((Exception) arg); + if (arg instanceof Exception exception) { + captureException(exception); break; } } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java index 591863d906b..647da383818 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java @@ -108,8 +108,8 @@ public void registerMappedBatchLoader( private @NotNull IScopes scopesFromContext(final @NotNull BatchLoaderEnvironment environment) { Object context = environment.getContext(); - if (context instanceof GraphQLContext) { - GraphQLContext graphqlContext = (GraphQLContext) context; + if (context instanceof GraphQLContext graphqlContext) { + return graphqlContext.getOrDefault(SENTRY_SCOPES_CONTEXT_KEY, NoOpScopes.getInstance()); } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java index 2ea390fd2dd..1a973c62031 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java @@ -12,8 +12,8 @@ public final class SentryGraphqlBeanPostProcessor implements BeanPostProcessor, @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof BatchLoaderRegistry) { - return new SentryBatchLoaderRegistry((BatchLoaderRegistry) bean); + if (bean instanceof BatchLoaderRegistry batchLoaderRegistry) { + return new SentryBatchLoaderRegistry(batchLoaderRegistry); } return bean; } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java index eff0b4154bb..c8b41d4d0f7 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java @@ -36,8 +36,8 @@ public final class SentryKafkaProducerBeanPostProcessor @SuppressWarnings({"unchecked", "rawtypes"}) public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (bean instanceof ProducerFactory) { - final @NotNull ProducerFactory factory = (ProducerFactory) bean; + if (bean instanceof ProducerFactory factory) { + final @NotNull SentryProducerPostProcessor pp = new SentryProducerPostProcessor<>(); factory.addPostProcessor(pp); if (!factory.getPostProcessors().contains(pp)) { diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java index b2b4d20b948..d08351ac5f5 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java @@ -196,7 +196,7 @@ private boolean isIgnored() { if (enqueuedTimeStr != null) { try { final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr); - final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis()); + final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis()); final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000); if (latencyMs >= 0) { transaction.setData(SpanDataConvention.MESSAGING_MESSAGE_RECEIVE_LATENCY, latencyMs); diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java index 6c9a3287edc..36eb08d524c 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java @@ -35,15 +35,17 @@ public SentrySpanAdvice(final @NotNull IScopes scopes) { @SuppressWarnings("deprecation") @Override - public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { final ISpan activeSpan = scopes.getSpan(); if (activeSpan == null || activeSpan.isNoOp()) { // there is no active transaction, we do not start new span return invocation.proceed(); } else { + final @Nullable Object target = invocation.getThis(); final Method mostSpecificMethod = - AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); + AopUtils.getMostSpecificMethod( + invocation.getMethod(), target != null ? target.getClass() : null); final Class targetClass = invocation.getMethod().getDeclaringClass(); SentrySpan sentrySpan = AnnotationUtils.findAnnotation(mostSpecificMethod, SentrySpan.class); if (sentrySpan == null) { diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java index 46a31245ba1..d0d0923a42b 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java @@ -39,7 +39,7 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IScopes scopes) { } public SentrySpanClientHttpRequestInterceptor( - final @NotNull IScopes scopes, final @NotNull boolean isRestTemplate) { + final @NotNull IScopes scopes, final boolean isRestTemplate) { this.scopes = Objects.requireNonNull(scopes, "Scopes are required"); this.traceOrigin = isRestTemplate ? TRACE_ORIGIN_REST_TEMPLATE : TRACE_ORIGIN_REST_CLIENT; } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java index b16a6ab00ef..913ee09b2d3 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java @@ -41,9 +41,11 @@ public SentryTransactionAdvice(final @NotNull IScopes scopes) { @SuppressWarnings("deprecation") @Override - public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + final @Nullable Object target = invocation.getThis(); final Method mostSpecificMethod = - AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); + AopUtils.getMostSpecificMethod( + invocation.getMethod(), target != null ? target.getClass() : null); @Nullable SentryTransaction sentryTransaction = @@ -116,7 +118,7 @@ private static class TransactionNameAndSource { private final @NotNull String name; private final @NotNull TransactionNameSource source; - public TransactionNameAndSource( + TransactionNameAndSource( final @NotNull String name, final @NotNull TransactionNameSource source) { this.name = name; this.source = source; diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java b/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java index 19e6fa0fc4e..421cb7a2a90 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java @@ -38,7 +38,7 @@ public SentryWebExceptionHandler(final @NotNull IScopes scopes) { public @NotNull Mono handle( final @NotNull ServerWebExchange serverWebExchange, final @NotNull Throwable ex) { final @Nullable IScopes requestScopes = - serverWebExchange.getAttributeOrDefault(SentryWebFilter.SENTRY_SCOPES_KEY, null); + serverWebExchange.getAttribute(SentryWebFilter.SENTRY_SCOPES_KEY); final @NotNull IScopes scopesToUse = requestScopes != null ? requestScopes : scopes; return SentryReactorUtils.withSentryScopes( diff --git a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java index efdf9dc255a..51d86eb6bb8 100644 --- a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java +++ b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java @@ -45,13 +45,12 @@ public boolean supportsEventType(final @NotNull ResolvableType eventType) { @Override public void onApplicationEvent(final @NotNull ApplicationEvent event) { final Object context = LogManager.getContext(false); - if (!(context instanceof LoggerContext)) { + if (!(context instanceof LoggerContext loggerContext)) { logger.info( "Sentry Log4j2 appender was not configured because Log4j2 Core is not the active logging backend. Log4j2 API calls may be routed through SLF4J."); return; } - final LoggerContext loggerContext = (LoggerContext) context; final Configuration configuration = loggerContext.getConfiguration(); boolean changed = false; diff --git a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java index 5dd84ab413c..88099b6eea3 100644 --- a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java +++ b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java @@ -19,11 +19,10 @@ final class SentryOkHttpClientBeanPostProcessor implements BeanPostProcessor, Pr @Override public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (!(bean instanceof OkHttpClient)) { + if (!(bean instanceof OkHttpClient client)) { return bean; } - final @NotNull OkHttpClient client = (OkHttpClient) bean; if (client.getClass() != OkHttpClient.class) { ScopesAdapter.getInstance() .getOptions() diff --git a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java index 141f6a8ba00..c9d8684304c 100644 --- a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java +++ b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java @@ -45,13 +45,12 @@ public boolean supportsEventType(final @NotNull ResolvableType eventType) { @Override public void onApplicationEvent(final @NotNull ApplicationEvent event) { final Object context = LogManager.getContext(false); - if (!(context instanceof LoggerContext)) { + if (!(context instanceof LoggerContext loggerContext)) { logger.info( "Sentry Log4j2 appender was not configured because Log4j2 Core is not the active logging backend. Log4j2 API calls may be routed through SLF4J."); return; } - final LoggerContext loggerContext = (LoggerContext) context; final Configuration configuration = loggerContext.getConfiguration(); boolean changed = false; diff --git a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java index 8409240d7fe..4c0bbf6c920 100644 --- a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java +++ b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java @@ -19,11 +19,10 @@ final class SentryOkHttpClientBeanPostProcessor implements BeanPostProcessor, Pr @Override public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (!(bean instanceof OkHttpClient)) { + if (!(bean instanceof OkHttpClient client)) { return bean; } - final @NotNull OkHttpClient client = (OkHttpClient) bean; if (client.getClass() != OkHttpClient.class) { ScopesAdapter.getInstance() .getOptions() diff --git a/sentry-spring-jakarta/build.gradle.kts b/sentry-spring-jakarta/build.gradle.kts index f103bfcbe0a..d518fce95bb 100644 --- a/sentry-spring-jakarta/build.gradle.kts +++ b/sentry-spring-jakarta/build.gradle.kts @@ -66,7 +66,7 @@ dependencies { testImplementation(libs.graphql.java24) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.springboot3.starter.aop) testImplementation(libs.springboot3.starter.graphql) testImplementation(libs.springboot3.starter.security) diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java index b7f4646b4a8..a64eb826f04 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java @@ -25,9 +25,8 @@ public HttpServletRequestSentryUserProvider(final @NotNull SentryOptions options public @Nullable User provideUser() { if (options.getDataCollectionResolver().isUserInfo()) { final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - if (requestAttributes instanceof ServletRequestAttributes) { - final ServletRequestAttributes servletRequestAttributes = - (ServletRequestAttributes) requestAttributes; + if (requestAttributes instanceof ServletRequestAttributes servletRequestAttributes) { + final HttpServletRequest request = servletRequestAttributes.getRequest(); final User user = new User(); diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java index 4d9e63a151b..28157e0336b 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java @@ -42,8 +42,7 @@ public SentryInitBeanPostProcessor() { @SuppressWarnings({"unchecked", "deprecation"}) public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, @NotNull final String beanName) throws BeansException { - if (bean instanceof SentryOptions) { - final SentryOptions options = (SentryOptions) bean; + if (bean instanceof SentryOptions options) { if (applicationContext != null) { applicationContext diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java index ec9964f7abc..ad4425131ff 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java @@ -16,8 +16,8 @@ public final class SentryCacheBeanPostProcessor implements BeanPostProcessor, Pr @Override public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (bean instanceof CacheManager && !(bean instanceof SentryCacheManagerWrapper)) { - return new SentryCacheManagerWrapper((CacheManager) bean, ScopesAdapter.getInstance()); + if (bean instanceof CacheManager cacheManager && !(bean instanceof SentryCacheManagerWrapper)) { + return new SentryCacheManagerWrapper(cacheManager, ScopesAdapter.getInstance()); } return bean; } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java index c6537f853c2..5fe03f385df 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java @@ -42,8 +42,8 @@ public Object invoke(final @NotNull MethodInvocation invocation) throws Throwabl if (sentryCaptureExceptionParameter != null) { Object[] args = invocation.getArguments(); for (Object arg : args) { - if (arg instanceof Exception) { - captureException((Exception) arg); + if (arg instanceof Exception exception) { + captureException(exception); break; } } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java index 4e7c3665aae..6a9f33e65f1 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java @@ -108,8 +108,8 @@ public void registerMappedBatchLoader( private @NotNull IScopes scopesFromContext(final @NotNull BatchLoaderEnvironment environment) { Object context = environment.getContext(); - if (context instanceof GraphQLContext) { - GraphQLContext graphqlContext = (GraphQLContext) context; + if (context instanceof GraphQLContext graphqlContext) { + return graphqlContext.getOrDefault(SENTRY_SCOPES_CONTEXT_KEY, NoOpScopes.getInstance()); } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java index 5eb4374bb1f..79bc5e11ccd 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java @@ -12,8 +12,8 @@ public final class SentryGraphqlBeanPostProcessor implements BeanPostProcessor, @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof BatchLoaderRegistry) { - return new SentryBatchLoaderRegistry((BatchLoaderRegistry) bean); + if (bean instanceof BatchLoaderRegistry batchLoaderRegistry) { + return new SentryBatchLoaderRegistry(batchLoaderRegistry); } return bean; } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java index 8a06e4e338e..dc3636a2b24 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java @@ -36,8 +36,8 @@ public final class SentryKafkaProducerBeanPostProcessor @SuppressWarnings({"unchecked", "rawtypes"}) public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (bean instanceof ProducerFactory) { - final @NotNull ProducerFactory factory = (ProducerFactory) bean; + if (bean instanceof ProducerFactory factory) { + final @NotNull SentryProducerPostProcessor pp = new SentryProducerPostProcessor<>(); factory.addPostProcessor(pp); if (!factory.getPostProcessors().contains(pp)) { diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java index 72535712695..4d5abda711f 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java @@ -196,7 +196,7 @@ private boolean isIgnored() { if (enqueuedTimeStr != null) { try { final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr); - final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis()); + final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis()); final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000); if (latencyMs >= 0) { transaction.setData(SpanDataConvention.MESSAGING_MESSAGE_RECEIVE_LATENCY, latencyMs); diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java index 0628bc1d30e..8a5d1db3e05 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java @@ -39,7 +39,7 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IScopes scopes) { } public SentrySpanClientHttpRequestInterceptor( - final @NotNull IScopes scopes, final @NotNull boolean isRestTemplate) { + final @NotNull IScopes scopes, final boolean isRestTemplate) { this.scopes = Objects.requireNonNull(scopes, "Scopes are required"); this.traceOrigin = isRestTemplate ? TRACE_ORIGIN_REST_TEMPLATE : TRACE_ORIGIN_REST_CLIENT; } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java index 95618f76fd7..833e59670e2 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java @@ -116,7 +116,7 @@ private static class TransactionNameAndSource { private final @NotNull String name; private final @NotNull TransactionNameSource source; - public TransactionNameAndSource( + TransactionNameAndSource( final @NotNull String name, final @NotNull TransactionNameSource source) { this.name = name; this.source = source; diff --git a/sentry-spring/build.gradle.kts b/sentry-spring/build.gradle.kts index 03176d7b867..c6d66456d8c 100644 --- a/sentry-spring/build.gradle.kts +++ b/sentry-spring/build.gradle.kts @@ -54,7 +54,7 @@ dependencies { testImplementation(libs.graphql.java17) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.springboot.starter.aop) testImplementation(libs.springboot.starter.graphql) testImplementation(libs.springboot.starter.security) diff --git a/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java index d1ad3086098..ed26e2ee795 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java +++ b/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java @@ -202,7 +202,7 @@ private boolean isIgnored() { if (enqueuedTimeStr != null) { try { final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr); - final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis()); + final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis()); final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000); if (latencyMs >= 0) { transaction.setData(SpanDataConvention.MESSAGING_MESSAGE_RECEIVE_LATENCY, latencyMs); diff --git a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java index 180d5df00a7..eab13d1a7d6 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java +++ b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java @@ -115,7 +115,7 @@ private static class TransactionNameAndSource { private final @NotNull String name; private final @NotNull TransactionNameSource source; - public TransactionNameAndSource( + TransactionNameAndSource( final @NotNull String name, final @NotNull TransactionNameSource source) { this.name = name; this.source = source; diff --git a/sentry-system-test-support/build.gradle.kts b/sentry-system-test-support/build.gradle.kts index 7f08bf6d01b..08f4a0a06d9 100644 --- a/sentry-system-test-support/build.gradle.kts +++ b/sentry-system-test-support/build.gradle.kts @@ -13,7 +13,7 @@ configure { } tasks.withType().configureEach { - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 + compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry-test-support/build.gradle.kts b/sentry-test-support/build.gradle.kts index a0b508c9715..da8d697e5b9 100644 --- a/sentry-test-support/build.gradle.kts +++ b/sentry-test-support/build.gradle.kts @@ -12,7 +12,7 @@ configure { } tasks.withType().configureEach { - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 + compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry/build.gradle.kts b/sentry/build.gradle.kts index 6b98ff790c6..731a6608a05 100644 --- a/sentry/build.gradle.kts +++ b/sentry/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { testImplementation(libs.javafaker) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) - testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.core) testImplementation(libs.msgpack) testImplementation(libs.okio) testImplementation(projects.sentryTestSupport) @@ -51,6 +51,9 @@ tasks { "--add-opens", "java.base/java.lang=ALL-UNNAMED", ) + // SentryEnvelopeItemTest."fromAttachment with file SecurityManager denies read access" installs + // a SecurityManager to simulate unreadable attachments; JDK 18+ refuses that without opt-in. + systemProperty("java.security.manager", "allow") environment["SENTRY_TEST_PROPERTY"] = "\"some-value\"" environment["SENTRY_TEST_MAP_KEY1"] = "\"value1\"" environment["SENTRY_TEST_MAP_KEY2"] = "value2" diff --git a/sentry/src/main/java/io/sentry/Baggage.java b/sentry/src/main/java/io/sentry/Baggage.java index 9f0753f8671..3c3b0aea28c 100644 --- a/sentry/src/main/java/io/sentry/Baggage.java +++ b/sentry/src/main/java/io/sentry/Baggage.java @@ -257,6 +257,9 @@ public String getThirdPartyHeader() { return thirdPartyHeader; } + // ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, which crashes on Android + // < 24. + @SuppressWarnings("JdkObsolete") public @NotNull String toHeaderString(@Nullable String thirdPartyBaggageHeaderString) { final StringBuilder sb = new StringBuilder(); String separator = ""; @@ -325,10 +328,14 @@ public String getThirdPartyHeader() { return sb.toString(); } + // The Charset overload requires Java 10. + @SuppressWarnings("JdkObsolete") private String encode(final @NotNull String value) throws UnsupportedEncodingException { return URLEncoder.encode(value, CHARSET).replaceAll("\\+", "%20"); } + // The Charset overload requires Java 10. + @SuppressWarnings("JdkObsolete") private static String decode(final @NotNull String value) throws UnsupportedEncodingException { return URLDecoder.decode(value, CHARSET); } diff --git a/sentry/src/main/java/io/sentry/Breadcrumb.java b/sentry/src/main/java/io/sentry/Breadcrumb.java index 4db0dcf46c5..a00fb496602 100644 --- a/sentry/src/main/java/io/sentry/Breadcrumb.java +++ b/sentry/src/main/java/io/sentry/Breadcrumb.java @@ -630,6 +630,8 @@ public void setType(@Nullable String type) { this.type = type; } + // EMPTY_DATA is a sentinel, so identity comparison is intended. + @SuppressWarnings("ReferenceEquality") private @NotNull Map getOrCreateData() { Map currentData = data; if (currentData == EMPTY_DATA) { @@ -691,6 +693,8 @@ public void setData(@Nullable String key, @Nullable Object value) { * * @param key the key */ + // EMPTY_DATA is a sentinel, so identity comparison is intended. + @SuppressWarnings("ReferenceEquality") public void removeData(@Nullable String key) { if (key == null) { return; diff --git a/sentry/src/main/java/io/sentry/CombinedContextsView.java b/sentry/src/main/java/io/sentry/CombinedContextsView.java index d9a8b14c628..0fff6b681bd 100644 --- a/sentry/src/main/java/io/sentry/CombinedContextsView.java +++ b/sentry/src/main/java/io/sentry/CombinedContextsView.java @@ -243,7 +243,7 @@ public void setSpring(@NotNull Spring spring) { @ApiStatus.Internal @Override - /** Not intended to be set on a scopes Context directly */ + /* Not intended to be set on a scopes Context directly */ public void setFeatureFlags(@NotNull FeatureFlags spring) { getDefaultContexts().setFeatureFlags(spring); } diff --git a/sentry/src/main/java/io/sentry/DateUtils.java b/sentry/src/main/java/io/sentry/DateUtils.java index fcba83fbe05..4be99b6322f 100644 --- a/sentry/src/main/java/io/sentry/DateUtils.java +++ b/sentry/src/main/java/io/sentry/DateUtils.java @@ -151,10 +151,10 @@ public static double nanosToSeconds(final long nanos) { */ @SuppressWarnings("JavaUtilDate") public static double dateToSeconds(final @NotNull Date date) { - return millisToSeconds(date.getTime()); + return millisToSeconds((double) date.getTime()); } - public static long secondsToNanos(final @NotNull long seconds) { + public static long secondsToNanos(final long seconds) { return seconds * (1000L * 1000L * 1000L); } diff --git a/sentry/src/main/java/io/sentry/DefaultSpanFactory.java b/sentry/src/main/java/io/sentry/DefaultSpanFactory.java index f664360f49b..71dd40843a4 100644 --- a/sentry/src/main/java/io/sentry/DefaultSpanFactory.java +++ b/sentry/src/main/java/io/sentry/DefaultSpanFactory.java @@ -21,7 +21,7 @@ public final class DefaultSpanFactory implements ISpanFactory { final @NotNull SpanOptions spanOptions, final @NotNull SpanContext spanContext, @Nullable ISpan parentSpan) { - /** + /* * Be careful here when executing something like parentSpan.startChild() as that might cause a * loop and a stack overflow. This can happen, e.g. when OpenTelemetry is creating spans that * use OtelSpanWrapper which calls this createSpan method that then in turn calls startChild diff --git a/sentry/src/main/java/io/sentry/DiagnosticLogger.java b/sentry/src/main/java/io/sentry/DiagnosticLogger.java index c96e061f2c1..81b8e30d2ba 100644 --- a/sentry/src/main/java/io/sentry/DiagnosticLogger.java +++ b/sentry/src/main/java/io/sentry/DiagnosticLogger.java @@ -29,6 +29,8 @@ public DiagnosticLogger(final @NotNull SentryOptions options, final @Nullable IL * @param level The SentryLevel to test against. * @return True if a log message would be recorded for the level. Otherwise false. */ + // SentryLevel is declared in ascending severity order. + @SuppressWarnings("EnumOrdinal") @Override public boolean isEnabled(final @Nullable SentryLevel level) { final SentryLevel diagLevel = options.getDiagnosticLevel(); diff --git a/sentry/src/main/java/io/sentry/DirectoryProcessor.java b/sentry/src/main/java/io/sentry/DirectoryProcessor.java index 17f65bb8c76..d9f0f32c40c 100644 --- a/sentry/src/main/java/io/sentry/DirectoryProcessor.java +++ b/sentry/src/main/java/io/sentry/DirectoryProcessor.java @@ -120,7 +120,7 @@ private static final class SendCachedEnvelopeHint private final @NotNull String filePath; private final @NotNull Queue processedEnvelopes; - public SendCachedEnvelopeHint( + SendCachedEnvelopeHint( final long flushTimeoutMillis, final @NotNull ILogger logger, final @NotNull String filePath, diff --git a/sentry/src/main/java/io/sentry/ExternalOptions.java b/sentry/src/main/java/io/sentry/ExternalOptions.java index 272cf1c13a9..810130416aa 100644 --- a/sentry/src/main/java/io/sentry/ExternalOptions.java +++ b/sentry/src/main/java/io/sentry/ExternalOptions.java @@ -242,7 +242,8 @@ public final class ExternalOptions { String profileLifecycleString = propertiesProvider.getProperty("profile-lifecycle"); if (profileLifecycleString != null && !profileLifecycleString.isEmpty()) { - options.setProfileLifecycle(ProfileLifecycle.valueOf(profileLifecycleString.toUpperCase())); + options.setProfileLifecycle( + ProfileLifecycle.valueOf(profileLifecycleString.toUpperCase(Locale.ROOT))); } return options; diff --git a/sentry/src/main/java/io/sentry/Hint.java b/sentry/src/main/java/io/sentry/Hint.java index 1e09dca5541..9281d41fa91 100644 --- a/sentry/src/main/java/io/sentry/Hint.java +++ b/sentry/src/main/java/io/sentry/Hint.java @@ -60,7 +60,7 @@ public void set(@NotNull String name, @Nullable Object hint) { } @SuppressWarnings("unchecked") - public @Nullable T getAs(@NotNull String name, @NotNull Class clazz) { + public @Nullable T getAs(@NotNull String name, @NotNull Class clazz) { try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) { Object hintValue = internalStorage.get(name); diff --git a/sentry/src/main/java/io/sentry/MonitorContexts.java b/sentry/src/main/java/io/sentry/MonitorContexts.java index a52ecc6b97f..55178893767 100644 --- a/sentry/src/main/java/io/sentry/MonitorContexts.java +++ b/sentry/src/main/java/io/sentry/MonitorContexts.java @@ -43,6 +43,9 @@ public void setTrace(final @NotNull SpanContext traceContext) { // region json + // ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, which crashes on Android + // < 24. + @SuppressWarnings("JdkObsolete") @Override public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger) throws IOException { diff --git a/sentry/src/main/java/io/sentry/ReplayRecording.java b/sentry/src/main/java/io/sentry/ReplayRecording.java index a83eddd380f..8c038d64c33 100644 --- a/sentry/src/main/java/io/sentry/ReplayRecording.java +++ b/sentry/src/main/java/io/sentry/ReplayRecording.java @@ -102,7 +102,8 @@ public void setUnknown(@Nullable Map unknown) { public static final class Deserializer implements JsonDeserializer { - @SuppressWarnings("unchecked") + // The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings({"unchecked", "EnumOrdinal"}) @Override public @NotNull ReplayRecording deserialize( @NotNull ObjectReader reader, @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/SamplingContext.java b/sentry/src/main/java/io/sentry/SamplingContext.java index 17ce111d0c2..7a9c69b0739 100644 --- a/sentry/src/main/java/io/sentry/SamplingContext.java +++ b/sentry/src/main/java/io/sentry/SamplingContext.java @@ -20,7 +20,7 @@ public final class SamplingContext { @Deprecated @SuppressWarnings("InlineMeSuggester") - /** + /* * @deprecated creating a SamplingContext is something only the SDK should do */ public SamplingContext( diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java index 54e8b893555..d02e1b75728 100644 --- a/sentry/src/main/java/io/sentry/Scope.java +++ b/sentry/src/main/java/io/sentry/Scope.java @@ -463,10 +463,10 @@ public Queue getBreadcrumbs() { */ private @Nullable Breadcrumb executeBeforeBreadcrumb( final @NotNull SentryOptions.BeforeBreadcrumbCallback callback, - @NotNull Breadcrumb breadcrumb, + final @NotNull Breadcrumb breadcrumb, final @NotNull Hint hint) { try (final @NotNull ISentryLifecycleToken ignored = SentryCallbackReentrancyGuard.enter()) { - breadcrumb = callback.execute(breadcrumb, hint); + return callback.execute(breadcrumb, hint); } catch (Throwable e) { options .getLogger() diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index 012587eaa59..f8adb54e2ca 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -1353,7 +1353,7 @@ public void captureLog(@Nullable SentryLogEvent logEvent, @Nullable IScope scope options .getClientReportRecorder() .recordLostEvent(DiscardReason.BEFORE_SEND, DataCategory.LogItem); - final @NotNull long logEventNumberOfBytes = + final long logEventNumberOfBytes = JsonSerializationUtils.byteSizeOf( options.getSerializer(), options.getLogger(), tmpLogEvent); options diff --git a/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java b/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java index 2a7f06968dc..d1858c02767 100644 --- a/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java +++ b/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java @@ -691,11 +691,12 @@ private static class CachedItem { private @Nullable byte[] bytes; private final @Nullable Callable dataFactory; - public CachedItem(final @Nullable Callable dataFactory) { + CachedItem(final @Nullable Callable dataFactory) { this.dataFactory = dataFactory; } - public @NotNull byte[] getBytes() throws Exception { + @NotNull + byte[] getBytes() throws Exception { if (bytes == null && dataFactory != null) { bytes = dataFactory.call(); } diff --git a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java index cd4ab1cc0e9..3c07ec38b91 100644 --- a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java +++ b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java @@ -11,6 +11,7 @@ import java.util.Deque; import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -141,7 +142,7 @@ Deque extractExceptionQueue(final @NotNull Throwable throwable) Deque extractExceptionQueueInternal( final @NotNull Throwable throwable, final @NotNull AtomicInteger exceptionId, - final @NotNull HashSet circularityDetector, + final @NotNull Set circularityDetector, final @NotNull Deque exceptions, @Nullable String mechanismTypeOverride) { Mechanism exceptionMechanism; diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index 2b2f9d370a0..c43b9f7a105 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -58,6 +58,8 @@ import org.jetbrains.annotations.TestOnly; /** Sentry SDK options */ +// Constructors call overridable methods; making them final would break the public API. +@SuppressWarnings("this-escape") @Open public class SentryOptions implements RateLimiterConfig { diff --git a/sentry/src/main/java/io/sentry/SentryThreadFactory.java b/sentry/src/main/java/io/sentry/SentryThreadFactory.java index 8bd14483269..cb0608f825e 100644 --- a/sentry/src/main/java/io/sentry/SentryThreadFactory.java +++ b/sentry/src/main/java/io/sentry/SentryThreadFactory.java @@ -78,6 +78,8 @@ List getCurrentThreads( * crashed. This is the case for e.g. watchdog threads which are not the one erroring. * @return a list of SentryThread or null if none */ + // Identifies the current thread by identity. + @SuppressWarnings("ReferenceEquality") @TestOnly @Nullable List getCurrentThreads( diff --git a/sentry/src/main/java/io/sentry/SentryTracer.java b/sentry/src/main/java/io/sentry/SentryTracer.java index d60187cb4d5..781cf51417e 100644 --- a/sentry/src/main/java/io/sentry/SentryTracer.java +++ b/sentry/src/main/java/io/sentry/SentryTracer.java @@ -154,7 +154,7 @@ private void onDeadlineTimeoutReached() { } @Override - public @NotNull void forceFinish( + public void forceFinish( final @NotNull SpanStatus status, final boolean dropIfNoChildren, final @Nullable Hint hint) { if (isFinished()) { return; diff --git a/sentry/src/main/java/io/sentry/SpanContext.java b/sentry/src/main/java/io/sentry/SpanContext.java index 19ab2c3ad87..4beb6673c54 100644 --- a/sentry/src/main/java/io/sentry/SpanContext.java +++ b/sentry/src/main/java/io/sentry/SpanContext.java @@ -16,6 +16,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; +// Constructors call overridable methods; making them final would break the public API. +@SuppressWarnings("this-escape") @Open public class SpanContext implements JsonUnknown, JsonSerializable { public static final String TYPE = "trace"; diff --git a/sentry/src/main/java/io/sentry/SynchronizedCollection.java b/sentry/src/main/java/io/sentry/SynchronizedCollection.java index 8a58401020b..e88d25a235e 100644 --- a/sentry/src/main/java/io/sentry/SynchronizedCollection.java +++ b/sentry/src/main/java/io/sentry/SynchronizedCollection.java @@ -50,9 +50,13 @@ class SynchronizedCollection implements Collection, Serializable { private static final long serialVersionUID = 2412805092710877986L; /** The collection to decorate */ + // Serializable only if the decorated collection is, as in Apache Commons Collections. + @SuppressWarnings("serial") private final Collection collection; /** The object to lock on, needed for List/SortedSet views */ + // Not Serializable either; the SDK never serializes these collections. + @SuppressWarnings("serial") final AutoClosableReentrantLock lock; /** diff --git a/sentry/src/main/java/io/sentry/TraceContext.java b/sentry/src/main/java/io/sentry/TraceContext.java index 1bb5508f85b..957bda79f49 100644 --- a/sentry/src/main/java/io/sentry/TraceContext.java +++ b/sentry/src/main/java/io/sentry/TraceContext.java @@ -30,7 +30,7 @@ public final class TraceContext implements JsonUnknown, JsonSerializable { } @SuppressWarnings("InlineMeSuggester") - /** + /* * @deprecated please use the constructor than also takes sampleRand */ @Deprecated diff --git a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java index 6ea61895799..a6015051d1c 100644 --- a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java +++ b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java @@ -47,6 +47,8 @@ public UncaughtExceptionHandlerIntegration() { this.threadAdapter = threadAdapter; } + // Both integrations must share the same global scope instance. + @SuppressWarnings("ReferenceEquality") @Override public final void register(final @NotNull IScopes scopes, final @NotNull SentryOptions options) { if (registered) { diff --git a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java index 8a097486db1..8dca5dfb7e3 100644 --- a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java +++ b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java @@ -265,6 +265,8 @@ private void flush() { } } + // DELETE_MARKER and CLEAR_MARKER are sentinels, so identity comparison is intended. + @SuppressWarnings("ReferenceEquality") private void writePending() { // ConcurrentHashMap's iterator is weakly consistent, so removing while iterating is safe. Keys // added after iteration starts may be missed, but flush() re-checks and queues another write. diff --git a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java index 5df6d473f78..009e28c22ad 100644 --- a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java +++ b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java @@ -14,9 +14,16 @@ public final class ExceptionMechanismException extends RuntimeException { private static final long serialVersionUID = 142345454265713915L; + // Never serialized. + @SuppressWarnings("serial") private final @NotNull Mechanism exceptionMechanism; + private final @NotNull Throwable throwable; + + // Never serialized. + @SuppressWarnings("serial") private final @Nullable Thread thread; + private final boolean snapshot; /** diff --git a/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java b/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java index 5a02a911ace..84448878196 100644 --- a/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java +++ b/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java @@ -233,13 +233,14 @@ private static class FeatureFlagEntry { private final boolean result; private final long nanos; - public FeatureFlagEntry(final @NotNull String flag, final boolean result, final long nanos) { + FeatureFlagEntry(final @NotNull String flag, final boolean result, final long nanos) { this.flag = flag; this.result = result; this.nanos = nanos; } - public @NotNull FeatureFlag toFeatureFlag() { + @NotNull + FeatureFlag toFeatureFlag() { return new FeatureFlag(flag, result); } } diff --git a/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java b/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java index 1f7ac93950e..fc1c313ec43 100644 --- a/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java +++ b/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java @@ -93,7 +93,7 @@ private static final class Module { private final @NotNull String name; private final @NotNull String version; - public Module(final @NotNull String name, final @NotNull String version) { + Module(final @NotNull String name, final @NotNull String version) { this.name = name; this.version = version; } diff --git a/sentry/src/main/java/io/sentry/logger/LoggerApi.java b/sentry/src/main/java/io/sentry/logger/LoggerApi.java index 3741ddc6209..69f5a5a44bc 100644 --- a/sentry/src/main/java/io/sentry/logger/LoggerApi.java +++ b/sentry/src/main/java/io/sentry/logger/LoggerApi.java @@ -152,7 +152,7 @@ private void captureLog( } } - private @NotNull HashMap createAttributes( + private @NotNull Map createAttributes( final @NotNull SentryLogParameters params, final @NotNull String message, final @Nullable Object... args) { @@ -247,8 +247,7 @@ private void captureLog( return attributes; } - private void setServerName( - final @NotNull HashMap attributes) { + private void setServerName(final @NotNull Map attributes) { final @NotNull SentryOptions options = scopes.getOptions(); final @Nullable String optionsServerName = options.getServerName(); if (optionsServerName != null) { @@ -265,7 +264,7 @@ private void setServerName( } } - private void setUser(final @NotNull HashMap attributes) { + private void setUser(final @NotNull Map attributes) { final @Nullable User user = scopes.getCombinedScopeView().getUser(); if (user == null) { // In case no user is set, we should fallback to the distinct id, known as installation id, diff --git a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java index d70b4ab5c97..70f5006be23 100644 --- a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java +++ b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java @@ -156,7 +156,7 @@ private void captureMetrics( } } - private @NotNull HashMap createAttributes( + private @NotNull Map createAttributes( final @NotNull SentryMetricsParameters params) { final @NotNull HashMap attributes = new HashMap<>(); @@ -232,8 +232,7 @@ private void captureMetrics( return attributes; } - private void setServerName( - final @NotNull HashMap attributes) { + private void setServerName(final @NotNull Map attributes) { final @NotNull SentryOptions options = scopes.getOptions(); final @Nullable String optionsServerName = options.getServerName(); if (optionsServerName != null) { @@ -250,7 +249,7 @@ private void setServerName( } } - private void setUser(final @NotNull HashMap attributes) { + private void setUser(final @NotNull Map attributes) { final @Nullable User user = scopes.getCombinedScopeView().getUser(); if (user == null) { // In case no user is set, we should fallback to the distinct id, known as installation id, diff --git a/sentry/src/main/java/io/sentry/protocol/Contexts.java b/sentry/src/main/java/io/sentry/protocol/Contexts.java index f6ba635383a..d5076714076 100644 --- a/sentry/src/main/java/io/sentry/protocol/Contexts.java +++ b/sentry/src/main/java/io/sentry/protocol/Contexts.java @@ -36,6 +36,8 @@ public class Contexts implements JsonSerializable { public Contexts() {} + // Constructors call overridable methods; making them final would break the public API. + @SuppressWarnings("this-escape") public Contexts(final @NotNull Contexts contexts) { for (final Map.Entry entry : contexts.entrySet()) { if (entry != null) { @@ -252,6 +254,9 @@ public void clear() { internalStorage.clear(); } + // ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, which crashes on Android + // < 24. + @SuppressWarnings("JdkObsolete") public @NotNull Enumeration keys() { return internalStorage.keys(); } diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java b/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java index fc9c8c7e690..792a46ed5bb 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java @@ -17,6 +17,8 @@ public enum RRWebEventType implements JsonSerializable { Custom, Plugin; + // The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger) throws IOException { @@ -24,6 +26,8 @@ public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger } public static final class Deserializer implements JsonDeserializer { + // The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public @NotNull RRWebEventType deserialize( final @NotNull ObjectReader reader, final @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java b/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java index aff3c55ac37..df926d49be1 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java @@ -30,6 +30,8 @@ public enum IncrementalSource implements JsonSerializable { AdoptedStyleSheet, CustomElement; + // The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) throws IOException { @@ -37,6 +39,8 @@ public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) } public static final class Deserializer implements JsonDeserializer { + // The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public @NotNull IncrementalSource deserialize( final @NotNull ObjectReader reader, final @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java b/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java index c7bd613c1b6..6f224591659 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java @@ -30,6 +30,8 @@ public enum InteractionType implements JsonSerializable { TouchEnd, TouchCancel; + // The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) throws IOException { @@ -37,6 +39,8 @@ public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) } public static final class Deserializer implements JsonDeserializer { + // The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public @NotNull InteractionType deserialize( final @NotNull ObjectReader reader, final @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/time/Deadline.java b/sentry/src/main/java/io/sentry/time/Deadline.java index b6cc63e8768..e2aeef9f72c 100644 --- a/sentry/src/main/java/io/sentry/time/Deadline.java +++ b/sentry/src/main/java/io/sentry/time/Deadline.java @@ -79,6 +79,8 @@ public long remaining(final @NotNull TimeUnit unit) { * @throws IllegalArgumentException if the two were created from different tickers, whose origins * are unrelated and whose ticks are therefore not comparable. */ + // Deadlines are only comparable when they share the same ticker instance. + @SuppressWarnings("ReferenceEquality") public boolean isAfter(final @NotNull Deadline other) { if (ticker != other.ticker) { throw new IllegalArgumentException( diff --git a/sentry/src/main/java/io/sentry/util/HttpUtils.java b/sentry/src/main/java/io/sentry/util/HttpUtils.java index 59ed67eb9f8..e81c9820e15 100644 --- a/sentry/src/main/java/io/sentry/util/HttpUtils.java +++ b/sentry/src/main/java/io/sentry/util/HttpUtils.java @@ -125,6 +125,8 @@ public static boolean containsSensitiveHeader(final @NotNull String header) { return filteredHeaders; } + // The Charset overload requires Java 10. + @SuppressWarnings("JdkObsolete") private static @NotNull String decodeQueryParamName(final @NotNull String name) { try { return URLDecoder.decode(name, "UTF-8"); diff --git a/sentry/src/main/java/io/sentry/util/InitUtil.java b/sentry/src/main/java/io/sentry/util/InitUtil.java index 471723ac188..f41099b26ad 100644 --- a/sentry/src/main/java/io/sentry/util/InitUtil.java +++ b/sentry/src/main/java/io/sentry/util/InitUtil.java @@ -16,6 +16,8 @@ @ApiStatus.Internal public final class InitUtil { + // InitPriority is declared in ascending priority order. + @SuppressWarnings("EnumOrdinal") public static boolean shouldInit( final @Nullable SentryOptions previousOptions, final @NotNull SentryOptions newOptions, diff --git a/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java b/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java index fc9bc75aa3f..4e5f9be90e5 100644 --- a/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java +++ b/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java @@ -129,7 +129,7 @@ public void close() { // Nothing to close } - public long getByteCount() { + long getByteCount() { return byteCount; } diff --git a/sentry/src/main/java/io/sentry/util/Objects.java b/sentry/src/main/java/io/sentry/util/Objects.java index df7aeab38b8..20f21c570b7 100644 --- a/sentry/src/main/java/io/sentry/util/Objects.java +++ b/sentry/src/main/java/io/sentry/util/Objects.java @@ -14,6 +14,8 @@ public static T requireNonNull(final @Nullable T obj, final @NotNull String return obj; } + // Identity short-circuit, same as java.util.Objects.equals (Java 7+). + @SuppressWarnings("ReferenceEquality") public static boolean equals(@Nullable Object a, @Nullable Object b) { return (a == b) || (a != null && a.equals(b)); } diff --git a/sentry/src/main/java/io/sentry/util/Platform.java b/sentry/src/main/java/io/sentry/util/Platform.java index ad2a4e7f3c3..bad0f214db3 100644 --- a/sentry/src/main/java/io/sentry/util/Platform.java +++ b/sentry/src/main/java/io/sentry/util/Platform.java @@ -1,7 +1,6 @@ package io.sentry.util; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @ApiStatus.Internal @@ -27,7 +26,7 @@ public final class Platform { try { final @Nullable String javaStringVersion = System.getProperty("java.specification.version"); if (javaStringVersion != null) { - final @NotNull double javaVersion = Double.parseDouble(javaStringVersion); + final double javaVersion = Double.parseDouble(javaStringVersion); isJavaNinePlus = javaVersion >= 9.0; } else { isJavaNinePlus = false; diff --git a/sentry/src/main/java/io/sentry/util/UUIDGenerator.java b/sentry/src/main/java/io/sentry/util/UUIDGenerator.java index 1da7b4feee1..0402190c851 100644 --- a/sentry/src/main/java/io/sentry/util/UUIDGenerator.java +++ b/sentry/src/main/java/io/sentry/util/UUIDGenerator.java @@ -56,7 +56,7 @@ public static UUID randomUUID() { // clear variant randomBytes[8] &= 0x3f; // set to IETF variant - randomBytes[8] |= 0x80; + randomBytes[8] = (byte) (randomBytes[8] | 0x80); long msb = 0; long lsb = 0; for (int i = 0; i < 8; i++) { diff --git a/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java b/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java index 42df5ca35b9..2bd50125656 100644 --- a/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java +++ b/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java @@ -34,6 +34,8 @@ private NetworkBodyParser() {} * @param logger Optional logger * @return A NetworkBody or null if bytes are null/empty */ + // The charset is a name from the Content-Type header; unsupported names are handled below. + @SuppressWarnings("JdkObsolete") public static @Nullable NetworkBody fromBytes( @Nullable final byte[] bytes, @Nullable final String contentType, @@ -131,6 +133,8 @@ private static NetworkBody parseJson( } /** Parses URL-encoded form data into a JsonObject NetworkBody. */ + // The Charset overload requires Java 10. + @SuppressWarnings("JdkObsolete") @NotNull private static NetworkBody parseFormUrlEncoded( @NotNull final String content, final boolean isPartial, @Nullable final ILogger logger) { @@ -206,7 +210,7 @@ private static class Result { private SaferJsonParser() {} @NotNull - public static SaferJsonParser.Result parse(final @NotNull JsonReader reader) { + static SaferJsonParser.Result parse(final @NotNull JsonReader reader) { final SaferJsonParser parser = new SaferJsonParser(); parser.result.data = parser.parse(reader, 0); return parser.result; diff --git a/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java b/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java index 4991a554c1e..52e44a37eb9 100644 --- a/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java +++ b/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java @@ -1502,6 +1502,8 @@ public String getPath() { * @throws NumberFormatException if any unicode escape sequences are * malformed. */ + // Vendored from Gson, kept identical to upstream. + @SuppressWarnings("lossy-conversions") private char readEscapeCharacter() throws IOException { if (pos == limit && !fillBuffer(1)) { throw syntaxError("Unterminated escape sequence"); diff --git a/sentry/src/test/java/io/sentry/OutboxSenderTest.kt b/sentry/src/test/java/io/sentry/OutboxSenderTest.kt index eecacc95bd2..703f0823c00 100644 --- a/sentry/src/test/java/io/sentry/OutboxSenderTest.kt +++ b/sentry/src/test/java/io/sentry/OutboxSenderTest.kt @@ -17,6 +17,7 @@ import kotlin.test.assertFalse import kotlin.test.assertNotNull import kotlin.test.assertTrue import org.mockito.kotlin.any +import org.mockito.kotlin.anyVararg import org.mockito.kotlin.argWhere import org.mockito.kotlin.check import org.mockito.kotlin.eq @@ -309,7 +310,7 @@ class OutboxSenderTest { sut.processEnvelopeFile(path, hints) // Additionally make sure we have no errors logged - verify(fixture.logger).log(eq(SentryLevel.ERROR), any(), any()) + verify(fixture.logger).log(eq(SentryLevel.ERROR), any(), anyVararg()) verify(fixture.scopes, never()).captureEvent(any()) assertFalse(File(path).exists()) } @@ -327,7 +328,7 @@ class OutboxSenderTest { sut.processEnvelopeFile(path, hints) // Additionally make sure we have no errors logged - verify(fixture.logger).log(eq(SentryLevel.ERROR), any(), any()) + verify(fixture.logger).log(eq(SentryLevel.ERROR), any(), anyVararg()) verify(fixture.scopes, never()).captureEvent(any()) assertFalse(File(path).exists()) } diff --git a/sentry/src/test/java/io/sentry/PreviousSessionFinalizerTest.kt b/sentry/src/test/java/io/sentry/PreviousSessionFinalizerTest.kt index 3a730e971bf..4fb74690c37 100644 --- a/sentry/src/test/java/io/sentry/PreviousSessionFinalizerTest.kt +++ b/sentry/src/test/java/io/sentry/PreviousSessionFinalizerTest.kt @@ -13,6 +13,7 @@ import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder import org.mockito.kotlin.any +import org.mockito.kotlin.anyVararg import org.mockito.kotlin.argThat import org.mockito.kotlin.mock import org.mockito.kotlin.never @@ -280,7 +281,7 @@ class PreviousSessionFinalizerTest { "Timed out waiting to flush previous session to its own file in session finalizer." ) }, - any(), + anyVararg(), ) verify(fixture.scopes, never()).captureEnvelope(any()) } From 8ff189dbbb9dd3088324203553eb7a5e0866a4cd Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Fri, 9 Oct 2026 11:09:49 +0200 Subject: [PATCH 02/22] build: Compile tests for JDK 21 and fix buildSrc JVM target --- build.gradle.kts | 29 +++++++++++---------- buildSrc/build.gradle.kts | 6 ----- sentry-apollo/build.gradle.kts | 2 ++ sentry-system-test-support/build.gradle.kts | 5 ++-- sentry-test-support/build.gradle.kts | 5 ++-- 5 files changed, 23 insertions(+), 24 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index acd50995df0..1776997de2e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -116,23 +116,24 @@ allprojects { subprojects { apply { plugin("io.sentry.spotless") } - // Mockito 5 and mockito-kotlin 5+ are built for Java 11. Test code is never published, so it - // compiles for at least Java 11 while the published code keeps its own target. Runs in - // afterEvaluate, as most modules pin the JVM target of all their compile tasks. - afterEvaluate { - tasks.withType().matching { it.name.contains("Test") }.configureEach { - if (JavaVersion.toVersion(targetCompatibility) < JavaVersion.VERSION_11) { - sourceCompatibility = JavaVersion.VERSION_11.toString() - targetCompatibility = JavaVersion.VERSION_11.toString() - } - } - tasks.withType().matching { it.name.contains("Test") }.configureEach { - if (compilerOptions.jvmTarget.get() < org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11) { - compilerOptions.jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11) + // Mockito 5 and mockito-kotlin 5+ are built for Java 11, so test code (never published) can't + // share the Java 8 target of the published code; it compiles for the build JDK instead. + // Registered once each plugin is applied, so this afterEvaluate runs after the plugins and the + // module have pinned the JVM target of all compile tasks. + listOf("java", "com.android.library", "com.android.application").forEach { pluginId -> + plugins.withId(pluginId) { + afterEvaluate { + val isTestTask = { task: Task -> task.name.contains("Test") && !task.name.contains("AndroidTest") } + tasks.withType().matching(isTestTask).configureEach { + sourceCompatibility = JavaVersion.VERSION_21.toString() + targetCompatibility = JavaVersion.VERSION_21.toString() + } + tasks.withType().matching(isTestTask).configureEach { + compilerOptions.jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21) + } } } } - listOf("com.android.library", "com.android.application").forEach { pluginId -> plugins.withId(pluginId) { // Robolectric's SDK 37 sandbox (the default, as targetSdk is 37) reflectively writes diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 451e5827ed9..876c922b222 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,5 +1,3 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - plugins { `kotlin-dsl` } @@ -7,7 +5,3 @@ plugins { repositories { mavenCentral() } - -tasks.withType().configureEach { - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 -} diff --git a/sentry-apollo/build.gradle.kts b/sentry-apollo/build.gradle.kts index 8da93b3c77c..1187f2c3545 100644 --- a/sentry-apollo/build.gradle.kts +++ b/sentry-apollo/build.gradle.kts @@ -45,6 +45,8 @@ tasks.withType().configureEach { options.errorprone { check("NullAway", net.ltgt.gradle.errorprone.CheckSeverity.ERROR) option("NullAway:AnnotatedPackages", "io.sentry") + // Generated by the Apollo plugin and marked "DO NOT MODIFY". + excludedPaths.set(".*/LaunchDetailsQuery.java") } } diff --git a/sentry-system-test-support/build.gradle.kts b/sentry-system-test-support/build.gradle.kts index 08f4a0a06d9..32bfa45ee93 100644 --- a/sentry-system-test-support/build.gradle.kts +++ b/sentry-system-test-support/build.gradle.kts @@ -7,9 +7,10 @@ plugins { id("com.apollographql.apollo") version "4.1.1" } +// Not published. Mockito 5 and mockito-kotlin 5+ are built for Java 11. configure { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } tasks.withType().configureEach { diff --git a/sentry-test-support/build.gradle.kts b/sentry-test-support/build.gradle.kts index da8d697e5b9..4c3776df8ea 100644 --- a/sentry-test-support/build.gradle.kts +++ b/sentry-test-support/build.gradle.kts @@ -6,9 +6,10 @@ plugins { alias(libs.plugins.gradle.versions) } +// Not published. Mockito 5 and mockito-kotlin 5+ are built for Java 11. configure { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } tasks.withType().configureEach { From 3dc76c011ccf7857489c0ed2108e74fc20366666 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 13 Oct 2026 09:37:11 +0200 Subject: [PATCH 03/22] build: Compile with a JDK 21 toolchain from a build-logic convention plugin --- CONTRIBUTING.md | 4 +- build-logic/build.gradle.kts | 2 + .../kotlin/io.sentry.jvm-targets.gradle.kts | 50 +++++++++++++++++++ build.gradle.kts | 50 ++++--------------- gradle/libs.versions.toml | 1 + .../build.gradle.kts | 2 - .../sentry-uitest-android/build.gradle.kts | 3 -- sentry-apache-http-client-5/build.gradle.kts | 4 +- sentry-apollo-3/build.gradle.kts | 2 +- sentry-apollo-4/build.gradle.kts | 2 +- sentry-apollo-5/build.gradle.kts | 2 +- sentry-apollo/build.gradle.kts | 2 +- sentry-async-profiler/build.gradle.kts | 2 +- sentry-graphql-22/build.gradle.kts | 2 +- sentry-graphql-core/build.gradle.kts | 2 +- sentry-graphql/build.gradle.kts | 2 +- sentry-jcache/build.gradle.kts | 2 +- sentry-jdbc/build.gradle.kts | 2 +- sentry-jul/build.gradle.kts | 2 +- sentry-kafka/build.gradle.kts | 2 +- sentry-kotlin-extensions/build.gradle.kts | 2 +- sentry-ktor-client/build.gradle.kts | 2 +- sentry-launchdarkly-server/build.gradle.kts | 2 +- sentry-log4j2/build.gradle.kts | 2 +- sentry-logback/build.gradle.kts | 2 +- sentry-okhttp/build.gradle.kts | 2 +- sentry-openfeature/build.gradle.kts | 2 +- sentry-openfeign/build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- sentry-quartz/build.gradle.kts | 2 +- sentry-reactor/build.gradle.kts | 8 ++- sentry-servlet-jakarta/build.gradle.kts | 2 +- sentry-servlet/build.gradle.kts | 2 +- sentry-spotlight/build.gradle.kts | 2 +- sentry-spring-7/build.gradle.kts | 8 ++- sentry-spring-boot-4-starter/build.gradle.kts | 8 ++- sentry-spring-boot-4/build.gradle.kts | 8 ++- sentry-spring-boot-jakarta/build.gradle.kts | 8 ++- .../build.gradle.kts | 8 ++- sentry-spring-boot-starter/build.gradle.kts | 2 +- sentry-spring-boot/build.gradle.kts | 2 +- sentry-spring-jakarta/build.gradle.kts | 19 ++++--- sentry-spring/build.gradle.kts | 2 +- sentry-system-test-support/build.gradle.kts | 9 +--- sentry-test-support/build.gradle.kts | 9 +--- sentry/build.gradle.kts | 2 +- settings.gradle.kts | 2 + 50 files changed, 134 insertions(+), 133 deletions(-) create mode 100644 build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7d4abc716ad..91da88b98a7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,9 @@ We suggest opening an issue to discuss bigger changes before investing on a big # Requirements -The project requires you to run JDK 21. +Gradle runs on JDK 17 or newer. Compilation and tests use a JDK 21 +[toolchain](https://docs.gradle.org/current/userguide/toolchains.html), so you also need a +JDK 21 installed; Gradle finds it in the usual locations (`JAVA_HOME`, SDKMAN!, asdf, IntelliJ). ## Android diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index bba758f9b79..2688055085e 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -9,6 +9,8 @@ repositories { dependencies { implementation(libs.animalsniffer.gradle.plugin) implementation(libs.spotlessLib) + // Only for the Kotlin task types the jvm-targets plugin configures. + compileOnly(libs.kotlin.gradle.plugin) } gradlePlugin { diff --git a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts new file mode 100644 index 00000000000..bf52d24a940 --- /dev/null +++ b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts @@ -0,0 +1,50 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile + +/** + * Picks the JDK that compiles the code and runs the tests, and lifts test code off the Java 8 + * target that the published modules use. + */ +val buildJdk = JavaLanguageVersion.of(21) + +// Compile and run tests on this JDK whatever JDK runs Gradle. Error Prone 2.50 ships Java 21 +// bytecode, so javac itself has to be 21; without a toolchain, building on JDK 17 fails with +// "UnsupportedClassVersionError: com/google/errorprone/ErrorProneJavacPlugin". +// This selects the JDK only; each module pins the bytecode level of its published code itself. +plugins.withType { + extensions.configure { toolchain { languageVersion.set(buildJdk) } } +} + +// Mockito 5 and mockito-kotlin 6 are built for Java 11, so test code (never published) can't share +// the Java 8 target of the published code. The library modules pin main compilation only, so their +// test tasks follow the toolchain on their own. Two groups can't do that and need the override +// below: Android modules, because AGP applies compileOptions to every variant including the unit +// tests, and the samples, which still pin every compile task and consume sentry-system-test-support. +fun Project.followToolchainInTests(taskFilter: (Task) -> Boolean) { + // Both languages have to move together or the Kotlin plugin rejects the mismatch. AGP sets these + // task properties while creating the variants, so the override has to run after evaluation. + afterEvaluate { + tasks.withType().matching(taskFilter).configureEach { + sourceCompatibility = buildJdk.toString() + targetCompatibility = buildJdk.toString() + } + tasks.withType().matching(taskFilter).configureEach { + compilerOptions.jvmTarget.set(JvmTarget.fromTarget(buildJdk.toString())) + } + } +} + +if (path.startsWith(":sentry-samples")) { + plugins.withId("java") { followToolchainInTests { it.name.contains("Test") } } +} + +listOf("com.android.library", "com.android.application").forEach { pluginId -> + plugins.withId(pluginId) { + followToolchainInTests { it.name.contains("UnitTest") } + + // Robolectric's SDK 37 sandbox (the default, as targetSdk is 37) reflectively writes + // FileDescriptor fields in ApplicationSharedMemory; without this, setup fails with + // "Failed to interact with raw FileDescriptor internals". + tasks.withType().configureEach { jvmArgs("--add-opens=java.base/java.io=ALL-UNNAMED") } + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 1776997de2e..b4487426eee 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,8 +29,10 @@ plugins { alias(libs.plugins.sentry) apply false } -check(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)) { - "This build requires JDK 21 or newer, but runs on JDK ${JavaVersion.current()}." +// Only the Gradle daemon itself, buildSrc and the plugins run on this JDK; compilation and tests +// use the JDK 21 toolchain configured below. 17 is the minimum AGP 9 accepts. +check(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { + "This build requires JDK 17 or newer to run Gradle, but runs on JDK ${JavaVersion.current()}." } buildscript { @@ -115,35 +117,7 @@ allprojects { subprojects { apply { plugin("io.sentry.spotless") } - - // Mockito 5 and mockito-kotlin 5+ are built for Java 11, so test code (never published) can't - // share the Java 8 target of the published code; it compiles for the build JDK instead. - // Registered once each plugin is applied, so this afterEvaluate runs after the plugins and the - // module have pinned the JVM target of all compile tasks. - listOf("java", "com.android.library", "com.android.application").forEach { pluginId -> - plugins.withId(pluginId) { - afterEvaluate { - val isTestTask = { task: Task -> task.name.contains("Test") && !task.name.contains("AndroidTest") } - tasks.withType().matching(isTestTask).configureEach { - sourceCompatibility = JavaVersion.VERSION_21.toString() - targetCompatibility = JavaVersion.VERSION_21.toString() - } - tasks.withType().matching(isTestTask).configureEach { - compilerOptions.jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21) - } - } - } - } - listOf("com.android.library", "com.android.application").forEach { pluginId -> - plugins.withId(pluginId) { - // Robolectric's SDK 37 sandbox (the default, as targetSdk is 37) reflectively writes - // FileDescriptor fields in ApplicationSharedMemory; without this, setup fails with - // "Failed to interact with raw FileDescriptor internals". - tasks.withType().configureEach { - jvmArgs("--add-opens=java.base/java.io=ALL-UNNAMED") - } - } - } + apply { plugin("io.sentry.jvm-targets") } plugins.withId(Config.QualityPlugins.detektPlugin) { configure { @@ -195,18 +169,14 @@ subprojects { configure { withJavadocJar() - - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 } - // Compile against the class library of the target Java version instead of the build - // JDK's, so newer JDK APIs (e.g. List.getFirst()) can't leak into published bytecode. - val javaExtension = the() + // Published code targets Java 8. release compiles against that version's class library + // instead of the build JDK's, so newer JDK APIs (e.g. List.getFirst()) can't leak into + // published bytecode. Modules that publish a higher level override this; test code is + // never published and follows the toolchain. tasks.named("compileJava") { - options.release.set( - provider { javaExtension.targetCompatibility.majorVersion.toInt() } - ) + options.release.set(8) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aa598b8c35b..e4d1c101c57 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -152,6 +152,7 @@ log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "lo leakcanary = { module = "com.squareup.leakcanary:leakcanary-android", version = "2.14" } lottie-compose = { module = "com.airbnb.android:lottie-compose", version = "6.7.1" } logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } +kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } nopen-annotations = { module = "com.jakewharton.nopen:nopen-annotations", version.ref = "nopen" } nopen-checker = { module = "com.jakewharton.nopen:nopen-checker", version.ref = "nopen" } nullaway = { module = "com.uber.nullaway:nullaway", version = "0.14.2" } diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts index 9ca0c1f6d9d..e606ab52553 100644 --- a/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts +++ b/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts @@ -1,5 +1,4 @@ import io.gitlab.arturbosch.detekt.Detekt -import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { id("com.android.application") @@ -33,7 +32,6 @@ android { proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } - kotlin { compilerOptions.jvmTarget = JvmTarget.JVM_11 } buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() } androidComponents.beforeVariants { diff --git a/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts index 85ff2b1a3c7..8f479470cac 100644 --- a/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts +++ b/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts @@ -1,6 +1,5 @@ import io.gitlab.arturbosch.detekt.Detekt import net.ltgt.gradle.errorprone.errorprone -import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { id("com.android.application") @@ -65,8 +64,6 @@ android { } } - kotlin { compilerOptions.jvmTarget = JvmTarget.JVM_11 } - lint { warningsAsErrors = true checkDependencies = true diff --git a/sentry-apache-http-client-5/build.gradle.kts b/sentry-apache-http-client-5/build.gradle.kts index 7502fb6c4b8..06c5f839f95 100644 --- a/sentry-apache-http-client-5/build.gradle.kts +++ b/sentry-apache-http-client-5/build.gradle.kts @@ -1,6 +1,7 @@ import net.ltgt.gradle.errorprone.errorprone import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinVersion +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { `java-library` @@ -12,11 +13,12 @@ plugins { } kotlin { - compilerOptions.jvmTarget = JvmTarget.JVM_1_8 compilerOptions.languageVersion = KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = KotlinVersion.KOTLIN_1_9 } +tasks.named("compileKotlin") { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 } + dependencies { api(projects.sentry) api(libs.apache.httpclient) diff --git a/sentry-apollo-3/build.gradle.kts b/sentry-apollo-3/build.gradle.kts index 9f07593e5f6..544f8ea04a3 100644 --- a/sentry-apollo-3/build.gradle.kts +++ b/sentry-apollo-3/build.gradle.kts @@ -12,7 +12,7 @@ plugins { id("io.sentry.animalsniffer.android") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-apollo-4/build.gradle.kts b/sentry-apollo-4/build.gradle.kts index 7534347c4e1..6f85910a889 100644 --- a/sentry-apollo-4/build.gradle.kts +++ b/sentry-apollo-4/build.gradle.kts @@ -12,7 +12,7 @@ plugins { id("io.sentry.animalsniffer.android") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-apollo-5/build.gradle.kts b/sentry-apollo-5/build.gradle.kts index 2f93f36e739..2d78dff8fa1 100644 --- a/sentry-apollo-5/build.gradle.kts +++ b/sentry-apollo-5/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer.android") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-apollo/build.gradle.kts b/sentry-apollo/build.gradle.kts index 1187f2c3545..f7025af97b1 100644 --- a/sentry-apollo/build.gradle.kts +++ b/sentry-apollo/build.gradle.kts @@ -12,7 +12,7 @@ plugins { id("io.sentry.animalsniffer.android") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-async-profiler/build.gradle.kts b/sentry-async-profiler/build.gradle.kts index 976452f94aa..3bcdefd1d82 100644 --- a/sentry-async-profiler/build.gradle.kts +++ b/sentry-async-profiler/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-graphql-22/build.gradle.kts b/sentry-graphql-22/build.gradle.kts index ba36db3e40b..4c4c41cbd38 100644 --- a/sentry-graphql-22/build.gradle.kts +++ b/sentry-graphql-22/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-graphql-core/build.gradle.kts b/sentry-graphql-core/build.gradle.kts index 5044127fb42..df0496f070e 100644 --- a/sentry-graphql-core/build.gradle.kts +++ b/sentry-graphql-core/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-graphql/build.gradle.kts b/sentry-graphql/build.gradle.kts index 484c2ed8499..cd71e537c21 100644 --- a/sentry-graphql/build.gradle.kts +++ b/sentry-graphql/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-jcache/build.gradle.kts b/sentry-jcache/build.gradle.kts index 3c8829eaf04..b773c42c340 100644 --- a/sentry-jcache/build.gradle.kts +++ b/sentry-jcache/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-jdbc/build.gradle.kts b/sentry-jdbc/build.gradle.kts index 425f707083d..9d0aa1596fe 100644 --- a/sentry-jdbc/build.gradle.kts +++ b/sentry-jdbc/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-jul/build.gradle.kts b/sentry-jul/build.gradle.kts index 2eec61eb171..130b46ad5ed 100644 --- a/sentry-jul/build.gradle.kts +++ b/sentry-jul/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-kafka/build.gradle.kts b/sentry-kafka/build.gradle.kts index 94ce4d528c1..37240c8305e 100644 --- a/sentry-kafka/build.gradle.kts +++ b/sentry-kafka/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-kotlin-extensions/build.gradle.kts b/sentry-kotlin-extensions/build.gradle.kts index 101761b2a82..ded17d445e7 100644 --- a/sentry-kotlin-extensions/build.gradle.kts +++ b/sentry-kotlin-extensions/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer.android") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-ktor-client/build.gradle.kts b/sentry-ktor-client/build.gradle.kts index 2d17fc7ce53..eaf43d30da8 100644 --- a/sentry-ktor-client/build.gradle.kts +++ b/sentry-ktor-client/build.gradle.kts @@ -12,7 +12,7 @@ plugins { id("io.sentry.animalsniffer.android") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-launchdarkly-server/build.gradle.kts b/sentry-launchdarkly-server/build.gradle.kts index 1e9c074226f..f2ed3d15742 100644 --- a/sentry-launchdarkly-server/build.gradle.kts +++ b/sentry-launchdarkly-server/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-log4j2/build.gradle.kts b/sentry-log4j2/build.gradle.kts index 6e5250ece50..2d2444a2395 100644 --- a/sentry-log4j2/build.gradle.kts +++ b/sentry-log4j2/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-logback/build.gradle.kts b/sentry-logback/build.gradle.kts index de2c9dbb807..48f84725a78 100644 --- a/sentry-logback/build.gradle.kts +++ b/sentry-logback/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-okhttp/build.gradle.kts b/sentry-okhttp/build.gradle.kts index 0d2b2e2d2ec..0b3e2388415 100644 --- a/sentry-okhttp/build.gradle.kts +++ b/sentry-okhttp/build.gradle.kts @@ -12,7 +12,7 @@ plugins { id("io.sentry.animalsniffer.android") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-openfeature/build.gradle.kts b/sentry-openfeature/build.gradle.kts index 56561810334..6750e22e61c 100644 --- a/sentry-openfeature/build.gradle.kts +++ b/sentry-openfeature/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-openfeign/build.gradle.kts b/sentry-openfeign/build.gradle.kts index 3baa85dee26..6ff446e3c14 100644 --- a/sentry-openfeign/build.gradle.kts +++ b/sentry-openfeign/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts index 087568d03ee..3390f2695c8 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts +++ b/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts @@ -10,7 +10,7 @@ plugins { alias(libs.plugins.gradle.versions) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/build.gradle.kts index 3585aa40d4a..28a1b030e15 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/build.gradle.kts +++ b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/build.gradle.kts @@ -10,7 +10,7 @@ plugins { alias(libs.plugins.gradle.versions) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts index a252628c1a2..1c1e7f984ba 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts +++ b/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts @@ -10,7 +10,7 @@ plugins { alias(libs.plugins.gradle.versions) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-opentelemetry/sentry-opentelemetry-otlp/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-otlp/build.gradle.kts index ec240c681ae..afab9ef180f 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-otlp/build.gradle.kts +++ b/sentry-opentelemetry/sentry-opentelemetry-otlp/build.gradle.kts @@ -10,7 +10,7 @@ plugins { alias(libs.plugins.gradle.versions) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-quartz/build.gradle.kts b/sentry-quartz/build.gradle.kts index bb04435f1d9..b5387daf207 100644 --- a/sentry-quartz/build.gradle.kts +++ b/sentry-quartz/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-reactor/build.gradle.kts b/sentry-reactor/build.gradle.kts index fe9023586ef..b98eafd028f 100644 --- a/sentry-reactor/build.gradle.kts +++ b/sentry-reactor/build.gradle.kts @@ -10,12 +10,10 @@ plugins { alias(libs.plugins.buildconfig) } -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} +// Published code targets Java 17. Test code is not published and follows the toolchain. +tasks.named("compileJava") { options.release.set(17) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-servlet-jakarta/build.gradle.kts b/sentry-servlet-jakarta/build.gradle.kts index 5762a4ae52b..b9d6ffc2ec4 100644 --- a/sentry-servlet-jakarta/build.gradle.kts +++ b/sentry-servlet-jakarta/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-servlet/build.gradle.kts b/sentry-servlet/build.gradle.kts index c2e3fe8e52e..08ac7d45284 100644 --- a/sentry-servlet/build.gradle.kts +++ b/sentry-servlet/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-spotlight/build.gradle.kts b/sentry-spotlight/build.gradle.kts index 9833a432473..072cb360e61 100644 --- a/sentry-spotlight/build.gradle.kts +++ b/sentry-spotlight/build.gradle.kts @@ -11,7 +11,7 @@ plugins { alias(libs.plugins.buildconfig) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/sentry-spring-7/build.gradle.kts b/sentry-spring-7/build.gradle.kts index 3f1d6d18a02..c848c9416a0 100644 --- a/sentry-spring-7/build.gradle.kts +++ b/sentry-spring-7/build.gradle.kts @@ -12,12 +12,10 @@ plugins { alias(libs.plugins.springboot4) apply false } -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} +// Published code targets Java 17. Test code is not published and follows the toolchain. +tasks.named("compileJava") { options.release.set(17) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions { jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1) diff --git a/sentry-spring-boot-4-starter/build.gradle.kts b/sentry-spring-boot-4-starter/build.gradle.kts index bffe53aab01..7ad300d4790 100644 --- a/sentry-spring-boot-4-starter/build.gradle.kts +++ b/sentry-spring-boot-4-starter/build.gradle.kts @@ -11,12 +11,10 @@ plugins { alias(libs.plugins.springboot4) apply false } -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} +// Published code targets Java 17. Test code is not published and follows the toolchain. +tasks.named("compileJava") { options.release.set(17) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-spring-boot-4/build.gradle.kts b/sentry-spring-boot-4/build.gradle.kts index d1128ce8a03..ce3a42989e8 100644 --- a/sentry-spring-boot-4/build.gradle.kts +++ b/sentry-spring-boot-4/build.gradle.kts @@ -13,12 +13,10 @@ plugins { alias(libs.plugins.springboot4) apply false } -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} +// Published code targets Java 17. Test code is not published and follows the toolchain. +tasks.named("compileJava") { options.release.set(17) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions { jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9) diff --git a/sentry-spring-boot-jakarta/build.gradle.kts b/sentry-spring-boot-jakarta/build.gradle.kts index 5f2bbe87b34..8c1a07aa9cf 100644 --- a/sentry-spring-boot-jakarta/build.gradle.kts +++ b/sentry-spring-boot-jakarta/build.gradle.kts @@ -12,12 +12,10 @@ plugins { alias(libs.plugins.springboot3) apply false } -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} +// Published code targets Java 17. Test code is not published and follows the toolchain. +tasks.named("compileJava") { options.release.set(17) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-spring-boot-starter-jakarta/build.gradle.kts b/sentry-spring-boot-starter-jakarta/build.gradle.kts index c6fe511073e..63594df7a2e 100644 --- a/sentry-spring-boot-starter-jakarta/build.gradle.kts +++ b/sentry-spring-boot-starter-jakarta/build.gradle.kts @@ -11,12 +11,10 @@ plugins { alias(libs.plugins.springboot3) apply false } -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} +// Published code targets Java 17. Test code is not published and follows the toolchain. +tasks.named("compileJava") { options.release.set(17) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-spring-boot-starter/build.gradle.kts b/sentry-spring-boot-starter/build.gradle.kts index cd05baecc4d..641b335becb 100644 --- a/sentry-spring-boot-starter/build.gradle.kts +++ b/sentry-spring-boot-starter/build.gradle.kts @@ -10,7 +10,7 @@ plugins { alias(libs.plugins.gradle.versions) } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-spring-boot/build.gradle.kts b/sentry-spring-boot/build.gradle.kts index 27cb2d7805c..c5537accef1 100644 --- a/sentry-spring-boot/build.gradle.kts +++ b/sentry-spring-boot/build.gradle.kts @@ -12,7 +12,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-spring-jakarta/build.gradle.kts b/sentry-spring-jakarta/build.gradle.kts index d518fce95bb..138ad1e5f16 100644 --- a/sentry-spring-jakarta/build.gradle.kts +++ b/sentry-spring-jakarta/build.gradle.kts @@ -12,18 +12,17 @@ plugins { alias(libs.plugins.springboot3) apply false } -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 +// Published code targets Java 17. Test code is not published and follows the toolchain. +tasks.named("compileJava") { options.release.set(17) } + +kotlin { + compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 + compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 + compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") } -tasks.withType().configureEach { - kotlin { - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 - compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 - compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 - compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - } +tasks.named("compileKotlin") { + compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 } dependencies { diff --git a/sentry-spring/build.gradle.kts b/sentry-spring/build.gradle.kts index c6d66456d8c..71eb6d1f15e 100644 --- a/sentry-spring/build.gradle.kts +++ b/sentry-spring/build.gradle.kts @@ -12,7 +12,7 @@ plugins { id("io.sentry.animalsniffer") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-system-test-support/build.gradle.kts b/sentry-system-test-support/build.gradle.kts index 32bfa45ee93..daea0bca4b3 100644 --- a/sentry-system-test-support/build.gradle.kts +++ b/sentry-system-test-support/build.gradle.kts @@ -7,14 +7,9 @@ plugins { id("com.apollographql.apollo") version "4.1.1" } -// Not published. Mockito 5 and mockito-kotlin 5+ are built for Java 11. -configure { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} - +// Not published and test-only, so it keeps the toolchain's JVM target instead of pinning Java 8 +// like the published modules do. tasks.withType().configureEach { - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry-test-support/build.gradle.kts b/sentry-test-support/build.gradle.kts index 4c3776df8ea..4f5ab04b21f 100644 --- a/sentry-test-support/build.gradle.kts +++ b/sentry-test-support/build.gradle.kts @@ -6,14 +6,9 @@ plugins { alias(libs.plugins.gradle.versions) } -// Not published. Mockito 5 and mockito-kotlin 5+ are built for Java 11. -configure { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} - +// Not published and test-only, so it keeps the toolchain's JVM target instead of pinning Java 8 +// like the published modules do. tasks.withType().configureEach { - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry/build.gradle.kts b/sentry/build.gradle.kts index 731a6608a05..9cbcf5bf2c0 100644 --- a/sentry/build.gradle.kts +++ b/sentry/build.gradle.kts @@ -11,7 +11,7 @@ plugins { id("io.sentry.animalsniffer.android") } -tasks.withType().configureEach { +tasks.named("compileKotlin") { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 } diff --git a/settings.gradle.kts b/settings.gradle.kts index 413ab5fd59b..97eaa4dd000 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,6 +20,8 @@ pluginManagement { plugins { id("com.gradle.develocity") version "4.5.0" id("com.gradle.common-custom-user-data-gradle-plugin") version "2.8.0" + // Downloads the JDK of the toolchain configured in build.gradle.kts when no local one matches. + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } develocity { From 26b8a60e4b49bf27aa995d6a6229f1a59412b723 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 13 Oct 2026 09:37:11 +0200 Subject: [PATCH 04/22] docs(kafka): Explain the explicit double cast at the latency call site --- .../io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java index d08351ac5f5..dca7c7d61dd 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java @@ -196,6 +196,8 @@ private boolean isIgnored() { if (enqueuedTimeStr != null) { try { final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr); + // millisToSeconds takes a double; the cast is explicit for Error Prone's + // LongDoubleConversion check. final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis()); final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000); if (latencyMs >= 0) { From 9788085a758a8d1c22905559a46ae153bed59139 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 13 Oct 2026 11:02:47 +0200 Subject: [PATCH 05/22] build: Compile the samples and their tests with the toolchain JDK --- .../main/kotlin/io.sentry.jvm-targets.gradle.kts | 4 ---- .../build.gradle.kts | 14 -------------- .../sentry-samples-console-otlp/build.gradle.kts | 14 -------------- .../sentry-samples-console/build.gradle.kts | 14 -------------- sentry-samples/sentry-samples-jul/build.gradle.kts | 10 ---------- .../sentry-samples-log4j2/build.gradle.kts | 10 ---------- .../sentry-samples-logback/build.gradle.kts | 10 ---------- .../sentry-samples-spring-7/build.gradle.kts | 5 ----- .../build.gradle.kts | 10 ---------- .../build.gradle.kts | 10 ---------- .../build.gradle.kts | 10 ---------- .../build.gradle.kts | 10 ---------- .../build.gradle.kts | 5 ----- .../sentry-samples-spring-boot-4/build.gradle.kts | 10 ---------- .../build.gradle.kts | 12 ------------ .../build.gradle.kts | 11 ----------- .../build.gradle.kts | 12 ------------ .../build.gradle.kts | 12 ------------ .../build.gradle.kts | 12 ------------ .../build.gradle.kts | 11 ----------- .../build.gradle.kts | 5 ----- .../build.gradle.kts | 5 ----- .../sentry-samples-spring-boot/build.gradle.kts | 10 ---------- .../sentry-samples-spring-jakarta/build.gradle.kts | 5 ----- .../sentry-samples-spring/build.gradle.kts | 6 ------ 25 files changed, 237 deletions(-) diff --git a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts index bf52d24a940..9acf91301dc 100644 --- a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts +++ b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts @@ -34,10 +34,6 @@ fun Project.followToolchainInTests(taskFilter: (Task) -> Boolean) { } } -if (path.startsWith(":sentry-samples")) { - plugins.withId("java") { followToolchainInTests { it.name.contains("Test") } } -} - listOf("com.android.library", "com.android.application").forEach { pluginId -> plugins.withId(pluginId) { followToolchainInTests { it.name.contains("UnitTest") } diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts index a71f0bb9040..57d1dea0e8d 100644 --- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts @@ -11,23 +11,9 @@ plugins { application { mainClass.set("io.sentry.samples.console.Main") } -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -tasks.withType().configureEach { - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 -} - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-console-otlp/build.gradle.kts b/sentry-samples/sentry-samples-console-otlp/build.gradle.kts index 491583175ae..58a8578c7d1 100644 --- a/sentry-samples/sentry-samples-console-otlp/build.gradle.kts +++ b/sentry-samples/sentry-samples-console-otlp/build.gradle.kts @@ -11,23 +11,9 @@ plugins { application { mainClass.set("io.sentry.samples.console.Main") } -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -tasks.withType().configureEach { - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 -} - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-console/build.gradle.kts b/sentry-samples/sentry-samples-console/build.gradle.kts index d714a0ed541..f0b0d862896 100644 --- a/sentry-samples/sentry-samples-console/build.gradle.kts +++ b/sentry-samples/sentry-samples-console/build.gradle.kts @@ -11,23 +11,9 @@ plugins { application { mainClass.set("io.sentry.samples.console.Main") } -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -tasks.withType().configureEach { - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 -} - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-jul/build.gradle.kts b/sentry-samples/sentry-samples-jul/build.gradle.kts index 3edf8e427a7..6fa4bbb8c8b 100644 --- a/sentry-samples/sentry-samples-jul/build.gradle.kts +++ b/sentry-samples/sentry-samples-jul/build.gradle.kts @@ -11,19 +11,9 @@ plugins { application { mainClass.set("io.sentry.samples.jul.Main") } -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-log4j2/build.gradle.kts index 809167d040c..901604d2cff 100644 --- a/sentry-samples/sentry-samples-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-log4j2/build.gradle.kts @@ -11,19 +11,9 @@ plugins { application { mainClass.set("io.sentry.samples.log4j2.Main") } -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-logback/build.gradle.kts b/sentry-samples/sentry-samples-logback/build.gradle.kts index 8bbc70a8fbb..6d6e7051030 100644 --- a/sentry-samples/sentry-samples-logback/build.gradle.kts +++ b/sentry-samples/sentry-samples-logback/build.gradle.kts @@ -11,19 +11,9 @@ plugins { application { mainClass.set("io.sentry.samples.logback.Main") } -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-spring-7/build.gradle.kts b/sentry-samples/sentry-samples-spring-7/build.gradle.kts index 8770dd8d380..82a18d86c73 100644 --- a/sentry-samples/sentry-samples-spring-7/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-7/build.gradle.kts @@ -22,10 +22,6 @@ group = "io.sentry.sample.spring-7" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - dependencyManagement { imports { mavenBom(SpringBootPlugin.BOM_COORDINATES) @@ -65,7 +61,6 @@ tasks.withType().configureEach { // skip metadata version check, as Spring 7 / Spring Boot 4 is // compiled against a newer version of Kotlin compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry-samples/sentry-samples-spring-boot-4-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-log4j2/build.gradle.kts index 2ca03bfc284..06cbdbe9400 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-log4j2/build.gradle.kts @@ -13,22 +13,12 @@ group = "io.sentry.sample.spring-boot-4-log4j2" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - tasks.withType().configureEach { kotlin { explicitApi() // skip metadata version check, as Spring 7 / Spring Boot 4 is // compiled against a newer version of Kotlin compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts index a2fefae6bac..bfd59790ce2 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts @@ -13,22 +13,12 @@ group = "io.sentry.sample.spring-boot-4" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - tasks.withType().configureEach { kotlin { explicitApi() // skip metadata version check, as Spring 7 / Spring Boot 4 is // compiled against a newer version of Kotlin compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts index 112465bb5fd..15bb3fca8a8 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts @@ -14,22 +14,12 @@ group = "io.sentry.sample.spring-boot-4" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - tasks.withType().configureEach { kotlin { explicitApi() // skip metadata version check, as Spring 7 / Spring Boot 4 is // compiled against a newer version of Kotlin compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts index d995d39de2a..c5bc2b96fb3 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts @@ -13,22 +13,12 @@ group = "io.sentry.sample.spring-boot-4-otlp" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - tasks.withType().configureEach { kotlin { explicitApi() // skip metadata version check, as Spring 7 / Spring Boot 4 is // compiled against a newer version of Kotlin compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts index e5b44c1793a..c0c021e8320 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts @@ -13,10 +13,6 @@ group = "io.sentry.sample.spring-boot-4-webflux" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - dependencies { implementation(Config.Libs.kotlinReflect) implementation(kotlin(Config.kotlinStdLib, KotlinCompilerVersion.VERSION)) @@ -53,7 +49,6 @@ tasks.withType().configureEach { // skip metadata version check, as Spring 7 / Spring Boot 4 is // compiled against a newer version of Kotlin compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts index 3ec1817ce66..00b85d45bd5 100644 --- a/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts @@ -13,22 +13,12 @@ group = "io.sentry.sample.spring-boot-4" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - tasks.withType().configureEach { kotlin { explicitApi() // skip metadata version check, as Spring 7 / Spring Boot 4 is // compiled against a newer version of Kotlin compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check") - compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 } diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts index 9ac03b5ebf8..6769fb5b41c 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts @@ -14,10 +14,6 @@ group = "io.sentry.sample.spring-boot-jakarta-log4j2" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - dependencyManagement { imports { mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}") @@ -27,17 +23,9 @@ dependencyManagement { // Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version extra["kotlin-coroutines.version"] = "1.9.0" -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -tasks.withType().configureEach { compilerOptions.jvmTarget = JvmTarget.JVM_17 } - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts index 6d1549842ce..72a42c57e61 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts @@ -14,10 +14,6 @@ group = "io.sentry.sample.spring-boot-jakarta" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - dependencyManagement { imports { mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}") @@ -28,16 +24,9 @@ dependencyManagement { // Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version extra["kotlin-coroutines.version"] = "1.9.0" -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - tasks.withType().configureEach { - compilerOptions.jvmTarget = JvmTarget.JVM_17 kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts index bfe39c0dfab..0991fd13cf6 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts @@ -15,10 +15,6 @@ group = "io.sentry.sample.spring-boot-jakarta" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - dependencyManagement { imports { mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}") @@ -28,17 +24,9 @@ dependencyManagement { // Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version extra["kotlin-coroutines.version"] = "1.9.0" -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -tasks.withType().configureEach { compilerOptions.jvmTarget = JvmTarget.JVM_17 } - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts index 722ccc69d3e..6e89b5d5021 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts @@ -14,10 +14,6 @@ group = "io.sentry.sample.spring-boot-jakarta" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - dependencyManagement { imports { mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}") @@ -27,17 +23,9 @@ dependencyManagement { // Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version extra["kotlin-coroutines.version"] = "1.9.0" -configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -tasks.withType().configureEach { compilerOptions.jvmTarget = JvmTarget.JVM_17 } - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts index 466c4fa7b58..a88a9585c20 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts @@ -17,10 +17,6 @@ group = "io.sentry.sample.spring-boot" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_11 - -java.targetCompatibility = JavaVersion.VERSION_11 - fun springBoot2SupportsOptionalIntegrations(): Boolean { val version = libs.versions.springboot2.get().removeSuffix(".RELEASE") val parts = version.split(".").map { it.toIntOrNull() ?: 0 } @@ -33,17 +29,9 @@ val includeGraphql = !project.hasProperty("excludeGraphql") && springBoot2SupportsOptionalIntegrations() val includeKafka = !project.hasProperty("excludeKafka") && springBoot2SupportsOptionalIntegrations() -configure { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} - -tasks.withType().configureEach { compilerOptions.jvmTarget = JvmTarget.JVM_11 } - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_11 } } diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts index f27ee6b2346..c832c1aadd6 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts @@ -17,10 +17,6 @@ group = "io.sentry.sample.spring-boot" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_11 - -java.targetCompatibility = JavaVersion.VERSION_11 - fun springBoot2SupportsOptionalIntegrations(): Boolean { val version = libs.versions.springboot2.get().removeSuffix(".RELEASE") val parts = version.split(".").map { it.toIntOrNull() ?: 0 } @@ -33,16 +29,9 @@ val includeGraphql = !project.hasProperty("excludeGraphql") && springBoot2SupportsOptionalIntegrations() val includeKafka = !project.hasProperty("excludeKafka") && springBoot2SupportsOptionalIntegrations() -configure { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} - tasks.withType().configureEach { - compilerOptions.jvmTarget = JvmTarget.JVM_11 kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_11 } } diff --git a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts index 08f74e90baa..9c785cfa0ee 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts @@ -14,10 +14,6 @@ group = "io.sentry.sample.spring-boot-webflux-jakarta" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - dependencyManagement { imports { mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}") @@ -59,7 +55,6 @@ dependencies { tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts index 1ef3a196e9c..a7cbc3fb59d 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts @@ -17,10 +17,6 @@ group = "io.sentry.sample.spring-boot" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_11 - -java.targetCompatibility = JavaVersion.VERSION_11 - fun springBoot2SupportsGraphql(): Boolean { val version = libs.versions.springboot2.get().removeSuffix(".RELEASE") val parts = version.split(".").map { it.toIntOrNull() ?: 0 } @@ -94,7 +90,6 @@ configure { tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_11 } } diff --git a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts index 86ed855e2d3..3e2fa1d45e7 100644 --- a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts @@ -17,10 +17,6 @@ group = "io.sentry.sample.spring-boot" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_11 - -java.targetCompatibility = JavaVersion.VERSION_11 - fun springBoot2SupportsOptionalIntegrations(): Boolean { val version = libs.versions.springboot2.get().removeSuffix(".RELEASE") val parts = version.split(".").map { it.toIntOrNull() ?: 0 } @@ -33,15 +29,9 @@ val includeGraphql = !project.hasProperty("excludeGraphql") && springBoot2SupportsOptionalIntegrations() val includeKafka = !project.hasProperty("excludeKafka") && springBoot2SupportsOptionalIntegrations() -configure { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} - tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_11 } } diff --git a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts index 2d28ed2531f..125f9c99111 100644 --- a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts @@ -20,10 +20,6 @@ group = "io.sentry.sample.spring-jakarta" version = "0.0.1-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 - -java.targetCompatibility = JavaVersion.VERSION_17 - // Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version extra["kotlin-coroutines.version"] = "1.9.0" @@ -64,7 +60,6 @@ dependencies { tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_17 } } diff --git a/sentry-samples/sentry-samples-spring/build.gradle.kts b/sentry-samples/sentry-samples-spring/build.gradle.kts index 7c6b6a915fc..171341eb65f 100644 --- a/sentry-samples/sentry-samples-spring/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring/build.gradle.kts @@ -20,11 +20,6 @@ group = "io.sentry.sample.spring" version = "0.0.1-SNAPSHOT" -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - // Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version extra["kotlin-coroutines.version"] = "1.9.0" @@ -65,7 +60,6 @@ dependencies { tasks.withType().configureEach { kotlin { compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict") - compilerOptions.jvmTarget = JvmTarget.JVM_1_8 } } From f6de52dd398c0b7b7772c7febbe00400cdc052bf Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Tue, 13 Oct 2026 09:53:17 +0000 Subject: [PATCH 06/22] Format code --- .../sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts | 1 - .../build.gradle.kts | 1 - .../build.gradle.kts | 1 - .../sentry-samples-spring-boot-jakarta/build.gradle.kts | 1 - .../build.gradle.kts | 1 - .../sentry-samples-spring-boot-opentelemetry/build.gradle.kts | 1 - .../sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts | 1 - .../sentry-samples-spring-boot-webflux/build.gradle.kts | 1 - sentry-samples/sentry-samples-spring-boot/build.gradle.kts | 1 - sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts | 1 - sentry-samples/sentry-samples-spring/build.gradle.kts | 1 - 11 files changed, 11 deletions(-) diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts index 6769fb5b41c..3535e1232e2 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts index 72a42c57e61..da761af1f62 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts index 0991fd13cf6..9b59911bd34 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.springframework.boot.gradle.tasks.run.BootRun diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts index 6e89b5d5021..cdc5753a9c5 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts index a88a9585c20..038dd3cd630 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts index c832c1aadd6..83a181ea055 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts index 9c785cfa0ee..342aaa0d70c 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts index a7cbc3fb59d..d49017c18d6 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts index 3e2fa1d45e7..bc544994253 100644 --- a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts index 125f9c99111..022b9fbb0c6 100644 --- a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring/build.gradle.kts b/sentry-samples/sentry-samples-spring/build.gradle.kts index 171341eb65f..d8bc46c86f3 100644 --- a/sentry-samples/sentry-samples-spring/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { From 6e811767ffd137f8674ce3395c0e994fe38be4c5 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 13 Oct 2026 12:05:23 +0200 Subject: [PATCH 07/22] build: Drop the now-unused JvmTarget imports from the samples --- .../sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts | 1 - .../build.gradle.kts | 1 - .../build.gradle.kts | 1 - .../sentry-samples-spring-boot-jakarta/build.gradle.kts | 1 - .../build.gradle.kts | 1 - .../sentry-samples-spring-boot-opentelemetry/build.gradle.kts | 1 - .../sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts | 1 - .../sentry-samples-spring-boot-webflux/build.gradle.kts | 1 - sentry-samples/sentry-samples-spring-boot/build.gradle.kts | 1 - sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts | 1 - sentry-samples/sentry-samples-spring/build.gradle.kts | 1 - 11 files changed, 11 deletions(-) diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts index 6769fb5b41c..3535e1232e2 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts index 72a42c57e61..da761af1f62 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts index 0991fd13cf6..9b59911bd34 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.springframework.boot.gradle.tasks.run.BootRun diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts index 6e89b5d5021..cdc5753a9c5 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts index a88a9585c20..038dd3cd630 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts index c832c1aadd6..83a181ea055 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts index 9c785cfa0ee..342aaa0d70c 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts index a7cbc3fb59d..d49017c18d6 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts index 3e2fa1d45e7..bc544994253 100644 --- a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts @@ -1,5 +1,4 @@ import org.jetbrains.kotlin.config.KotlinCompilerVersion -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts index 125f9c99111..022b9fbb0c6 100644 --- a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { diff --git a/sentry-samples/sentry-samples-spring/build.gradle.kts b/sentry-samples/sentry-samples-spring/build.gradle.kts index 171341eb65f..d8bc46c86f3 100644 --- a/sentry-samples/sentry-samples-spring/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { From 1c7fbf3ed0b05b448993cc268132b5e69522db4e Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 13 Oct 2026 12:05:23 +0200 Subject: [PATCH 08/22] build: Clarify the jvm-targets plugin comments and rename its helper --- .../kotlin/io.sentry.jvm-targets.gradle.kts | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts index 9acf91301dc..693c72386c5 100644 --- a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts +++ b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts @@ -1,28 +1,22 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile -/** - * Picks the JDK that compiles the code and runs the tests, and lifts test code off the Java 8 - * target that the published modules use. - */ +// Compilation and tests run on this JDK whatever JDK runs Gradle. Error Prone 2.50 ships Java 21 +// bytecode, so javac itself has to be 21; on JDK 17 it fails with "UnsupportedClassVersionError: +// com/google/errorprone/ErrorProneJavacPlugin". This picks the JDK only - every module pins the +// bytecode level it publishes itself. val buildJdk = JavaLanguageVersion.of(21) -// Compile and run tests on this JDK whatever JDK runs Gradle. Error Prone 2.50 ships Java 21 -// bytecode, so javac itself has to be 21; without a toolchain, building on JDK 17 fails with -// "UnsupportedClassVersionError: com/google/errorprone/ErrorProneJavacPlugin". -// This selects the JDK only; each module pins the bytecode level of its published code itself. plugins.withType { extensions.configure { toolchain { languageVersion.set(buildJdk) } } } -// Mockito 5 and mockito-kotlin 6 are built for Java 11, so test code (never published) can't share -// the Java 8 target of the published code. The library modules pin main compilation only, so their -// test tasks follow the toolchain on their own. Two groups can't do that and need the override -// below: Android modules, because AGP applies compileOptions to every variant including the unit -// tests, and the samples, which still pin every compile task and consume sentry-system-test-support. -fun Project.followToolchainInTests(taskFilter: (Task) -> Boolean) { - // Both languages have to move together or the Kotlin plugin rejects the mismatch. AGP sets these - // task properties while creating the variants, so the override has to run after evaluation. +/** + * Targets [buildJdk] in the compile tasks that [taskFilter] selects. Both languages move together, + * because the Kotlin plugin rejects a Java/Kotlin target mismatch. + */ +fun Project.applyToolchainToCompileTasks(taskFilter: (Task) -> Boolean) { + // AGP assigns these task properties while it creates the variants, so this has to run later. afterEvaluate { tasks.withType().matching(taskFilter).configureEach { sourceCompatibility = buildJdk.toString() @@ -36,7 +30,11 @@ fun Project.followToolchainInTests(taskFilter: (Task) -> Boolean) { listOf("com.android.library", "com.android.application").forEach { pluginId -> plugins.withId(pluginId) { - followToolchainInTests { it.name.contains("UnitTest") } + // Mockito 5 and mockito-kotlin 6 are built for Java 11, so test code (never published) can't + // share the Java 8 target of the published code. Other modules pin main compilation only, which + // leaves their test tasks on the toolchain; AGP has no such split, as compileOptions applies to + // every variant, so its unit tests need this. + applyToolchainToCompileTasks { it.name.contains("UnitTest") } // Robolectric's SDK 37 sandbox (the default, as targetSdk is 37) reflectively writes // FileDescriptor fields in ApplicationSharedMemory; without this, setup fails with From 7bd342c6c21713d8a76df35d033f78c5d041efd1 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 13 Oct 2026 13:04:32 +0200 Subject: [PATCH 09/22] build: Require JDK 21 to run Gradle again --- CONTRIBUTING.md | 6 +++--- .../src/main/kotlin/io.sentry.jvm-targets.gradle.kts | 7 +++---- build.gradle.kts | 6 ++---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 91da88b98a7..21de7f0c59b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,9 +5,9 @@ We suggest opening an issue to discuss bigger changes before investing on a big # Requirements -Gradle runs on JDK 17 or newer. Compilation and tests use a JDK 21 -[toolchain](https://docs.gradle.org/current/userguide/toolchains.html), so you also need a -JDK 21 installed; Gradle finds it in the usual locations (`JAVA_HOME`, SDKMAN!, asdf, IntelliJ). +The project requires you to run JDK 21 or newer. Compilation and tests always happen on JDK 21 +through a [toolchain](https://docs.gradle.org/current/userguide/toolchains.html), so a newer JDK +runs the build but never changes its output. ## Android diff --git a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts index 693c72386c5..39b31b8cc91 100644 --- a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts +++ b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts @@ -1,10 +1,9 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile -// Compilation and tests run on this JDK whatever JDK runs Gradle. Error Prone 2.50 ships Java 21 -// bytecode, so javac itself has to be 21; on JDK 17 it fails with "UnsupportedClassVersionError: -// com/google/errorprone/ErrorProneJavacPlugin". This picks the JDK only - every module pins the -// bytecode level it publishes itself. +// Compilation and tests run on this JDK whatever JDK runs Gradle, so a contributor on a newer JDK +// gets the same output as CI. Error Prone 2.50 ships Java 21 bytecode and needs javac 21 as well. +// This picks the JDK only - every module pins the bytecode level it publishes itself. val buildJdk = JavaLanguageVersion.of(21) plugins.withType { diff --git a/build.gradle.kts b/build.gradle.kts index b4487426eee..ccdc34091d2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,10 +29,8 @@ plugins { alias(libs.plugins.sentry) apply false } -// Only the Gradle daemon itself, buildSrc and the plugins run on this JDK; compilation and tests -// use the JDK 21 toolchain configured below. 17 is the minimum AGP 9 accepts. -check(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { - "This build requires JDK 17 or newer to run Gradle, but runs on JDK ${JavaVersion.current()}." +check(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)) { + "This build requires JDK 21 or newer, but runs on JDK ${JavaVersion.current()}." } buildscript { From 37b01cf72a3b7fa08ad41cb59a08e490f96f7e41 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 13 Oct 2026 13:04:32 +0200 Subject: [PATCH 10/22] build: Keep the Spring Boot 2 sample apps on their published bytecode level --- .../build.gradle.kts | 10 ++++++++++ .../build.gradle.kts | 10 ++++++++++ .../build.gradle.kts | 10 ++++++++++ .../sentry-samples-spring-boot/build.gradle.kts | 10 ++++++++++ sentry-samples/sentry-samples-spring/build.gradle.kts | 10 ++++++++++ 5 files changed, 50 insertions(+) diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts index 038dd3cd630..5ffc83b7f65 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts @@ -10,6 +10,16 @@ plugins { id("io.sentry.systemtest") } +// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version +// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the +// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test +// code keeps following the toolchain. +tasks.named("compileJava") { options.release.set(11) } + +tasks.named("compileKotlin") { + compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 +} + application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") } group = "io.sentry.sample.spring-boot" diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts index 83a181ea055..3b7f56523df 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts @@ -10,6 +10,16 @@ plugins { id("io.sentry.systemtest") } +// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version +// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the +// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test +// code keeps following the toolchain. +tasks.named("compileJava") { options.release.set(11) } + +tasks.named("compileKotlin") { + compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 +} + application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") } group = "io.sentry.sample.spring-boot" diff --git a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts index d49017c18d6..fe1859c0df7 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts @@ -10,6 +10,16 @@ plugins { id("io.sentry.systemtest") } +// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version +// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the +// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test +// code keeps following the toolchain. +tasks.named("compileJava") { options.release.set(11) } + +tasks.named("compileKotlin") { + compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 +} + application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") } group = "io.sentry.sample.spring-boot" diff --git a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts index bc544994253..316e98ebdb6 100644 --- a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts @@ -10,6 +10,16 @@ plugins { id("io.sentry.systemtest") } +// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version +// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the +// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test +// code keeps following the toolchain. +tasks.named("compileJava") { options.release.set(11) } + +tasks.named("compileKotlin") { + compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 +} + application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") } group = "io.sentry.sample.spring-boot" diff --git a/sentry-samples/sentry-samples-spring/build.gradle.kts b/sentry-samples/sentry-samples-spring/build.gradle.kts index d8bc46c86f3..8ae94a2e367 100644 --- a/sentry-samples/sentry-samples-spring/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring/build.gradle.kts @@ -10,6 +10,16 @@ plugins { id("io.sentry.systemtest") } +// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version +// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the +// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test +// code keeps following the toolchain. +tasks.named("compileJava") { options.release.set(8) } + +tasks.named("compileKotlin") { + compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 +} + application { mainClass.set("io.sentry.samples.spring.Main") } // Ensure WAR is up to date before run task From d663f0138f3f345a0224074c8fc8cc695ad171bf Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 13 Oct 2026 13:04:32 +0200 Subject: [PATCH 11/22] ci: Drop the stale Java version from the build job name --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 955803c7cf3..76781f577aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ concurrency: jobs: build: - name: Build Job ubuntu-latest - Java 17 + name: Build Job ubuntu-latest runs-on: ubuntu-latest env: From 445f5e4edb6a0d4ae1ab44ef7f0c42b7ce417720 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Tue, 13 Oct 2026 15:18:06 +0200 Subject: [PATCH 12/22] build: Keep Robolectric at 4.15 and leave its test environment untouched --- build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts | 5 ----- gradle/libs.versions.toml | 2 +- .../src/test/resources/robolectric.properties | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts index 39b31b8cc91..7afa1e1429b 100644 --- a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts +++ b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts @@ -34,10 +34,5 @@ listOf("com.android.library", "com.android.application").forEach { pluginId -> // leaves their test tasks on the toolchain; AGP has no such split, as compileOptions applies to // every variant, so its unit tests need this. applyToolchainToCompileTasks { it.name.contains("UnitTest") } - - // Robolectric's SDK 37 sandbox (the default, as targetSdk is 37) reflectively writes - // FileDescriptor fields in ApplicationSharedMemory; without this, setup fails with - // "Failed to interact with raw FileDescriptor internals". - tasks.withType().configureEach { jvmArgs("--add-opens=java.base/java.io=ALL-UNNAMED") } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e4d1c101c57..7b7fb63fb0d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -281,7 +281,7 @@ okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version. # apollo-runtime 5.x pulls in okhttp 5.x; mockwebserver 4.x is incompatible with that classpath okhttp-mockwebserver5 = { module = "com.squareup.okhttp3:mockwebserver", version = "5.3.0" } okio = { module = "com.squareup.okio:okio", version = "1.13.0" } -roboelectric = { module = "org.robolectric:robolectric", version = "4.17" } +roboelectric = { module = "org.robolectric:robolectric", version = "4.15" } [bundles] androidx-room2 = ["androidx-room-runtime", "androidx-room-ktx"] diff --git a/sentry-android-core/src/test/resources/robolectric.properties b/sentry-android-core/src/test/resources/robolectric.properties index c0f2ddf599d..c216eeab9dc 100644 --- a/sentry-android-core/src/test/resources/robolectric.properties +++ b/sentry-android-core/src/test/resources/robolectric.properties @@ -1,2 +1,2 @@ -sdk=23 +sdk=21 application=io.sentry.android.core.ApplicationStub From 2de047f9ad657239b154ee91245e27107fcfee3e Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Wed, 14 Oct 2026 08:52:50 +0200 Subject: [PATCH 13/22] build: Move the Java 8 release pin into the jvm-targets convention plugin --- .../kotlin/io.sentry.jvm-targets.gradle.kts | 17 +++++++++++++++++ build.gradle.kts | 11 ++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts index 7afa1e1429b..806c1db290b 100644 --- a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts +++ b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts @@ -36,3 +36,20 @@ listOf("com.android.library", "com.android.application").forEach { pluginId -> applyToolchainToCompileTasks { it.name.contains("UnitTest") } } } + +// Published code targets Java 8. release compiles against that version's class library instead of +// the build JDK's, so newer JDK APIs (e.g. List.getFirst()) can't leak into published bytecode. +// Modules that publish a higher level override this; test code and samples are never published and +// follow the toolchain. +// Keep this in sync with the publication filter in the root build script. +val isPublished = + !name.contains("sample") && + !name.contains("integration-tests") && + name != "sentry-system-test-support" && + name != "sentry-test-support" + +if (isPublished) { + plugins.withId("java-library") { + tasks.named("compileJava") { options.release.set(8) } + } +} diff --git a/build.gradle.kts b/build.gradle.kts index ccdc34091d2..7957f948d1b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -168,19 +168,12 @@ subprojects { configure { withJavadocJar() } - - // Published code targets Java 8. release compiles against that version's class library - // instead of the build JDK's, so newer JDK APIs (e.g. List.getFirst()) can't leak into - // published bytecode. Modules that publish a higher level override this; test code is - // never published and follows the toolchain. - tasks.named("compileJava") { - options.release.set(8) - } } // AGP 9 defaults Android modules to Java 11. Pin the published library modules back // to Java 8 so their bytecode stays consumable by Java 8 projects, mirroring the - // java-library pin above. + // java-library pin in the io.sentry.jvm-targets plugin. AGP compiles against android.jar, + // so it has no release equivalent. plugins.withId("com.android.library") { configure { compileOptions { From 561324bf41de6540330e83c743218bb779f351c8 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Thu, 15 Oct 2026 07:05:38 +0200 Subject: [PATCH 14/22] build: Drop the Error Prone and NullAway code fixes, they move to their own PR --- .../sentry/android/core/ApplicationNotResponding.java | 2 -- .../sentry/android/core/SentryUserFeedbackButton.java | 2 -- .../android/core/performance/AppStartMetrics.java | 2 -- .../JfrAsyncProfilerToSentryProfileConverter.java | 2 +- .../src/main/java/io/sentry/jul/SentryHandler.java | 2 -- .../io/sentry/kafka/SentryKafkaConsumerTracing.java | 2 +- .../java/io/sentry/kafka/SentryKafkaProducer.java | 6 ++---- .../main/java/io/sentry/logback/SentryAppender.java | 3 +-- .../opentelemetry/OtelContextScopesStorage.java | 2 +- .../opentelemetry/SentryOtelThreadLocalStorage.java | 2 -- .../java/io/sentry/reactor/SentryReactorUtils.java | 4 ++-- .../spring7/HttpServletRequestSentryUserProvider.java | 5 +++-- .../sentry/spring7/SentryInitBeanPostProcessor.java | 3 ++- .../spring7/cache/SentryCacheBeanPostProcessor.java | 4 ++-- .../sentry/spring7/checkin/SentryCheckInAdvice.java | 6 ++---- .../SentryCaptureExceptionParameterAdvice.java | 11 ++++------- .../spring7/graphql/SentryBatchLoaderRegistry.java | 4 ++-- .../graphql/SentryGraphqlBeanPostProcessor.java | 4 ++-- .../kafka/SentryKafkaProducerBeanPostProcessor.java | 4 ++-- .../spring7/kafka/SentryKafkaRecordInterceptor.java | 4 +--- .../io/sentry/spring7/tracing/SentrySpanAdvice.java | 6 ++---- .../SentrySpanClientHttpRequestInterceptor.java | 2 +- .../spring7/tracing/SentryTransactionAdvice.java | 8 +++----- .../spring7/webflux/SentryWebExceptionHandler.java | 2 +- .../sentry/spring/boot4/SentryLog4j2Initializer.java | 3 ++- .../boot4/SentryOkHttpClientBeanPostProcessor.java | 3 ++- .../spring/boot/jakarta/SentryLog4j2Initializer.java | 3 ++- .../jakarta/SentryOkHttpClientBeanPostProcessor.java | 3 ++- .../jakarta/HttpServletRequestSentryUserProvider.java | 5 +++-- .../spring/jakarta/SentryInitBeanPostProcessor.java | 3 ++- .../jakarta/cache/SentryCacheBeanPostProcessor.java | 4 ++-- .../SentryCaptureExceptionParameterAdvice.java | 4 ++-- .../jakarta/graphql/SentryBatchLoaderRegistry.java | 4 ++-- .../graphql/SentryGraphqlBeanPostProcessor.java | 4 ++-- .../kafka/SentryKafkaProducerBeanPostProcessor.java | 4 ++-- .../jakarta/kafka/SentryKafkaRecordInterceptor.java | 2 +- .../SentrySpanClientHttpRequestInterceptor.java | 2 +- .../jakarta/tracing/SentryTransactionAdvice.java | 2 +- .../spring/kafka/SentryKafkaRecordInterceptor.java | 2 +- .../spring/tracing/SentryTransactionAdvice.java | 2 +- sentry/src/main/java/io/sentry/Baggage.java | 7 ------- sentry/src/main/java/io/sentry/Breadcrumb.java | 4 ---- .../src/main/java/io/sentry/CombinedContextsView.java | 2 +- sentry/src/main/java/io/sentry/DateUtils.java | 4 ++-- .../src/main/java/io/sentry/DefaultSpanFactory.java | 2 +- sentry/src/main/java/io/sentry/DiagnosticLogger.java | 2 -- .../src/main/java/io/sentry/DirectoryProcessor.java | 2 +- sentry/src/main/java/io/sentry/ExternalOptions.java | 3 +-- sentry/src/main/java/io/sentry/Hint.java | 2 +- sentry/src/main/java/io/sentry/MonitorContexts.java | 3 --- sentry/src/main/java/io/sentry/ReplayRecording.java | 3 +-- sentry/src/main/java/io/sentry/SamplingContext.java | 2 +- sentry/src/main/java/io/sentry/Scope.java | 4 ++-- sentry/src/main/java/io/sentry/SentryClient.java | 2 +- .../src/main/java/io/sentry/SentryEnvelopeItem.java | 5 ++--- .../main/java/io/sentry/SentryExceptionFactory.java | 3 +-- sentry/src/main/java/io/sentry/SentryOptions.java | 2 -- .../src/main/java/io/sentry/SentryThreadFactory.java | 2 -- sentry/src/main/java/io/sentry/SentryTracer.java | 2 +- sentry/src/main/java/io/sentry/SpanContext.java | 2 -- .../main/java/io/sentry/SynchronizedCollection.java | 4 ---- sentry/src/main/java/io/sentry/TraceContext.java | 2 +- .../sentry/UncaughtExceptionHandlerIntegration.java | 2 -- .../java/io/sentry/cache/PersistingScopeObserver.java | 2 -- .../sentry/exception/ExceptionMechanismException.java | 7 ------- .../io/sentry/featureflags/FeatureFlagBuffer.java | 5 ++--- .../internal/modules/ManifestModulesLoader.java | 2 +- sentry/src/main/java/io/sentry/logger/LoggerApi.java | 7 ++++--- .../src/main/java/io/sentry/metrics/MetricsApi.java | 7 ++++--- sentry/src/main/java/io/sentry/protocol/Contexts.java | 5 ----- .../src/main/java/io/sentry/rrweb/RRWebEventType.java | 4 ---- .../sentry/rrweb/RRWebIncrementalSnapshotEvent.java | 4 ---- .../java/io/sentry/rrweb/RRWebInteractionEvent.java | 4 ---- sentry/src/main/java/io/sentry/time/Deadline.java | 2 -- sentry/src/main/java/io/sentry/util/HttpUtils.java | 2 -- sentry/src/main/java/io/sentry/util/InitUtil.java | 2 -- .../java/io/sentry/util/JsonSerializationUtils.java | 2 +- sentry/src/main/java/io/sentry/util/Objects.java | 2 -- sentry/src/main/java/io/sentry/util/Platform.java | 3 ++- .../src/main/java/io/sentry/util/UUIDGenerator.java | 2 +- .../io/sentry/util/network/NetworkBodyParser.java | 6 +----- .../java/io/sentry/vendor/gson/stream/JsonReader.java | 2 -- 82 files changed, 96 insertions(+), 182 deletions(-) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationNotResponding.java b/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationNotResponding.java index 9d76cdf298b..7b21c2e392c 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationNotResponding.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationNotResponding.java @@ -17,8 +17,6 @@ final class ApplicationNotResponding extends RuntimeException { private static final long serialVersionUID = 252541144579117016L; - // Never serialized. - @SuppressWarnings("serial") private final @Nullable Thread thread; ApplicationNotResponding(final @Nullable String message) { diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java b/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java index 0ae5583253e..f842f18674b 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java @@ -13,8 +13,6 @@ /** * @deprecated `SentryUserFeedbackButton` will be removed in the next major version */ -// Constructors call overridable methods; making them final would break the public API. -@SuppressWarnings("this-escape") @Deprecated public class SentryUserFeedbackButton extends Button { diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java b/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java index 090ca2d2669..82376a75d8b 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java @@ -50,8 +50,6 @@ *

This class is also responsible for - determining the app start type (cold, warm) - determining * if the app was launched in foreground */ -// Constructors call overridable methods; making them final would break the public API. -@SuppressWarnings("this-escape") @ApiStatus.Internal public class AppStartMetrics extends ActivityLifecycleCallbacksAdapter { public interface HeadlessAppStartListener { diff --git a/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java b/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java index a0ce94c08ec..718fae422f7 100644 --- a/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java +++ b/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java @@ -83,7 +83,7 @@ private class ProfileEventVisitor implements EventCollector.Visitor { private final @NotNull JfrReader jfr; private final @NotNull Arguments args; - ProfileEventVisitor( + public ProfileEventVisitor( @NotNull SentryProfile sentryProfile, @NotNull SentryStackTraceFactory stackTraceFactory, @NotNull JfrReader jfr, diff --git a/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java b/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java index c0eb576ce77..4442052dd41 100644 --- a/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java +++ b/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java @@ -40,8 +40,6 @@ import org.slf4j.MDC; /** Logging handler in charge of sending the java.util.logging records to a Sentry server. */ -// Constructors call overridable methods; making them final would break the public API. -@SuppressWarnings("this-escape") @Open public class SentryHandler extends Handler { public static final String MECHANISM_TYPE = "JulSentryHandler"; diff --git a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java index a45505f1019..dbce760de99 100644 --- a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java +++ b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java @@ -247,7 +247,7 @@ private void finishTransaction( try { final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr); - final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis()); + final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis()); final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000); return latencyMs >= 0 ? latencyMs : null; } catch (NumberFormatException ignored) { diff --git a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java index 573038d5ee9..bcc538e339c 100644 --- a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java +++ b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java @@ -114,8 +114,7 @@ static final class SentryProducerHandler implements InvocationHandler { } @Override - // Proxy equals() is identity-based. - @SuppressWarnings({"unchecked", "ReferenceEquality"}) + @SuppressWarnings("unchecked") public @Nullable Object invoke( final @NotNull Object proxy, final @NotNull Method method, final @Nullable Object[] args) throws Throwable { @@ -237,8 +236,7 @@ private void maybeInjectHeaders(final @NotNull Headers headers, final @Nullable headers.remove(SENTRY_ENQUEUED_TIME_HEADER); headers.add( SENTRY_ENQUEUED_TIME_HEADER, - DateUtils.doubleToBigDecimal( - DateUtils.millisToSeconds((double) System.currentTimeMillis())) + DateUtils.doubleToBigDecimal(DateUtils.millisToSeconds(System.currentTimeMillis())) .toString() .getBytes(StandardCharsets.UTF_8)); } catch (Throwable t) { diff --git a/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java b/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java index 66f61a182e5..722845e2d70 100644 --- a/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java +++ b/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java @@ -197,8 +197,7 @@ protected void captureLog(@NotNull ILoggingEvent loggingEvent) { final @NotNull SentryLogParameters params = SentryLogParameters.create(attributes); params.setOrigin("auto.log.logback"); - Sentry.logger() - .log(sentryLevel, params, formattedMessage, arguments != null ? arguments : new Object[0]); + Sentry.logger().log(sentryLevel, params, formattedMessage, arguments); } @SuppressWarnings("deprecation") diff --git a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java index ad70d2346a8..143ebb6c16d 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java +++ b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java @@ -17,7 +17,7 @@ public final class OtelContextScopesStorage implements IScopesStorage { @Override public void init() { - /* + /** * We're currently overriding the storage mechanism to allow for cleanup of non closed OTel * scopes. These happen when using e.g. Sentry static API due to getCurrentScopes() invoking * Context.makeCurrent and then ignoring the returned lifecycle token (OTel Scope). After fixing diff --git a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java index feec48908fd..e44afc5a2dc 100644 --- a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java +++ b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java @@ -29,8 +29,6 @@ public final class SentryOtelThreadLocalStorage implements ContextStorage { private static final ThreadLocal THREAD_LOCAL_STORAGE = new ThreadLocal<>(); - // Same identity check as OpenTelemetry's ThreadLocalContextStorage. - @SuppressWarnings("ReferenceEquality") @Override public Scope attach(Context toAttach) { if (toAttach == null) { diff --git a/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java b/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java index 04d87a8b45b..16fed92bd01 100644 --- a/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java +++ b/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java @@ -48,7 +48,7 @@ public static Mono withSentryForkedRoots(final @NotNull Mono mono) { */ public static Mono withSentryScopes( final @NotNull Mono mono, final @NotNull IScopes scopes) { - /* + /** * WARNING: Cannot set the scopes as current. It would be used by others to clone again causing * shared scopes and thus leading to issues like unrelated breadcrumbs showing up in events. */ @@ -96,7 +96,7 @@ public static Flux withSentryForkedRoots(final @NotNull Flux flux) { */ public static Flux withSentryScopes( final @NotNull Flux flux, final @NotNull IScopes scopes) { - /* + /** * WARNING: Cannot set the scopes as current. It would be used by others to fork again causing * shared scopes and thus leading to issues like unrelated breadcrumbs showing up in events. */ diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java b/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java index 27720570a2e..44ae584ec17 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java @@ -25,8 +25,9 @@ public HttpServletRequestSentryUserProvider(final @NotNull SentryOptions options public @Nullable User provideUser() { if (options.getDataCollectionResolver().isUserInfo()) { final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - if (requestAttributes instanceof ServletRequestAttributes servletRequestAttributes) { - + if (requestAttributes instanceof ServletRequestAttributes) { + final ServletRequestAttributes servletRequestAttributes = + (ServletRequestAttributes) requestAttributes; final HttpServletRequest request = servletRequestAttributes.getRequest(); final User user = new User(); diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java index b36df8be77b..4b778d68649 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java @@ -42,7 +42,8 @@ public SentryInitBeanPostProcessor() { @SuppressWarnings({"unchecked", "deprecation"}) public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, @NotNull final String beanName) throws BeansException { - if (bean instanceof SentryOptions options) { + if (bean instanceof SentryOptions) { + final SentryOptions options = (SentryOptions) bean; if (applicationContext != null) { applicationContext diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java index 8c755be2dea..b6569a9953b 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java @@ -16,8 +16,8 @@ public final class SentryCacheBeanPostProcessor implements BeanPostProcessor, Pr @Override public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (bean instanceof CacheManager cacheManager && !(bean instanceof SentryCacheManagerWrapper)) { - return new SentryCacheManagerWrapper(cacheManager, ScopesAdapter.getInstance()); + if (bean instanceof CacheManager && !(bean instanceof SentryCacheManagerWrapper)) { + return new SentryCacheManagerWrapper((CacheManager) bean, ScopesAdapter.getInstance()); } return bean; } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java index a14f0d4c96a..e58e0e9dd97 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java @@ -44,11 +44,9 @@ public SentryCheckInAdvice(final @NotNull IScopes scopes) { } @Override - public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { - final @Nullable Object target = invocation.getThis(); + public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { final Method mostSpecificMethod = - AopUtils.getMostSpecificMethod( - invocation.getMethod(), target != null ? target.getClass() : null); + AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); @Nullable SentryCheckIn checkInAnnotation = diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java index f4c630033a8..cb5cba62a4d 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java @@ -11,7 +11,6 @@ import org.aopalliance.intercept.MethodInvocation; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.springframework.aop.support.AopUtils; import org.springframework.core.annotation.AnnotationUtils; @@ -34,19 +33,17 @@ public SentryCaptureExceptionParameterAdvice(final @NotNull IScopes scopes) { } @Override - public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { - final @Nullable Object target = invocation.getThis(); + public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { final Method mostSpecificMethod = - AopUtils.getMostSpecificMethod( - invocation.getMethod(), target != null ? target.getClass() : null); + AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); SentryCaptureExceptionParameter sentryCaptureExceptionParameter = AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCaptureExceptionParameter.class); if (sentryCaptureExceptionParameter != null) { Object[] args = invocation.getArguments(); for (Object arg : args) { - if (arg instanceof Exception exception) { - captureException(exception); + if (arg instanceof Exception) { + captureException((Exception) arg); break; } } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java index 647da383818..591863d906b 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java @@ -108,8 +108,8 @@ public void registerMappedBatchLoader( private @NotNull IScopes scopesFromContext(final @NotNull BatchLoaderEnvironment environment) { Object context = environment.getContext(); - if (context instanceof GraphQLContext graphqlContext) { - + if (context instanceof GraphQLContext) { + GraphQLContext graphqlContext = (GraphQLContext) context; return graphqlContext.getOrDefault(SENTRY_SCOPES_CONTEXT_KEY, NoOpScopes.getInstance()); } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java index 1a973c62031..2ea390fd2dd 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java @@ -12,8 +12,8 @@ public final class SentryGraphqlBeanPostProcessor implements BeanPostProcessor, @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof BatchLoaderRegistry batchLoaderRegistry) { - return new SentryBatchLoaderRegistry(batchLoaderRegistry); + if (bean instanceof BatchLoaderRegistry) { + return new SentryBatchLoaderRegistry((BatchLoaderRegistry) bean); } return bean; } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java index c8b41d4d0f7..eff0b4154bb 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java @@ -36,8 +36,8 @@ public final class SentryKafkaProducerBeanPostProcessor @SuppressWarnings({"unchecked", "rawtypes"}) public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (bean instanceof ProducerFactory factory) { - + if (bean instanceof ProducerFactory) { + final @NotNull ProducerFactory factory = (ProducerFactory) bean; final @NotNull SentryProducerPostProcessor pp = new SentryProducerPostProcessor<>(); factory.addPostProcessor(pp); if (!factory.getPostProcessors().contains(pp)) { diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java index dca7c7d61dd..b2b4d20b948 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java @@ -196,9 +196,7 @@ private boolean isIgnored() { if (enqueuedTimeStr != null) { try { final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr); - // millisToSeconds takes a double; the cast is explicit for Error Prone's - // LongDoubleConversion check. - final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis()); + final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis()); final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000); if (latencyMs >= 0) { transaction.setData(SpanDataConvention.MESSAGING_MESSAGE_RECEIVE_LATENCY, latencyMs); diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java index 36eb08d524c..6c9a3287edc 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java @@ -35,17 +35,15 @@ public SentrySpanAdvice(final @NotNull IScopes scopes) { @SuppressWarnings("deprecation") @Override - public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { + public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { final ISpan activeSpan = scopes.getSpan(); if (activeSpan == null || activeSpan.isNoOp()) { // there is no active transaction, we do not start new span return invocation.proceed(); } else { - final @Nullable Object target = invocation.getThis(); final Method mostSpecificMethod = - AopUtils.getMostSpecificMethod( - invocation.getMethod(), target != null ? target.getClass() : null); + AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); final Class targetClass = invocation.getMethod().getDeclaringClass(); SentrySpan sentrySpan = AnnotationUtils.findAnnotation(mostSpecificMethod, SentrySpan.class); if (sentrySpan == null) { diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java index d0d0923a42b..46a31245ba1 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java @@ -39,7 +39,7 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IScopes scopes) { } public SentrySpanClientHttpRequestInterceptor( - final @NotNull IScopes scopes, final boolean isRestTemplate) { + final @NotNull IScopes scopes, final @NotNull boolean isRestTemplate) { this.scopes = Objects.requireNonNull(scopes, "Scopes are required"); this.traceOrigin = isRestTemplate ? TRACE_ORIGIN_REST_TEMPLATE : TRACE_ORIGIN_REST_CLIENT; } diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java index 913ee09b2d3..b16a6ab00ef 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java @@ -41,11 +41,9 @@ public SentryTransactionAdvice(final @NotNull IScopes scopes) { @SuppressWarnings("deprecation") @Override - public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { - final @Nullable Object target = invocation.getThis(); + public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable { final Method mostSpecificMethod = - AopUtils.getMostSpecificMethod( - invocation.getMethod(), target != null ? target.getClass() : null); + AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass()); @Nullable SentryTransaction sentryTransaction = @@ -118,7 +116,7 @@ private static class TransactionNameAndSource { private final @NotNull String name; private final @NotNull TransactionNameSource source; - TransactionNameAndSource( + public TransactionNameAndSource( final @NotNull String name, final @NotNull TransactionNameSource source) { this.name = name; this.source = source; diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java b/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java index 421cb7a2a90..19e6fa0fc4e 100644 --- a/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java +++ b/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java @@ -38,7 +38,7 @@ public SentryWebExceptionHandler(final @NotNull IScopes scopes) { public @NotNull Mono handle( final @NotNull ServerWebExchange serverWebExchange, final @NotNull Throwable ex) { final @Nullable IScopes requestScopes = - serverWebExchange.getAttribute(SentryWebFilter.SENTRY_SCOPES_KEY); + serverWebExchange.getAttributeOrDefault(SentryWebFilter.SENTRY_SCOPES_KEY, null); final @NotNull IScopes scopesToUse = requestScopes != null ? requestScopes : scopes; return SentryReactorUtils.withSentryScopes( diff --git a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java index 51d86eb6bb8..efdf9dc255a 100644 --- a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java +++ b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java @@ -45,12 +45,13 @@ public boolean supportsEventType(final @NotNull ResolvableType eventType) { @Override public void onApplicationEvent(final @NotNull ApplicationEvent event) { final Object context = LogManager.getContext(false); - if (!(context instanceof LoggerContext loggerContext)) { + if (!(context instanceof LoggerContext)) { logger.info( "Sentry Log4j2 appender was not configured because Log4j2 Core is not the active logging backend. Log4j2 API calls may be routed through SLF4J."); return; } + final LoggerContext loggerContext = (LoggerContext) context; final Configuration configuration = loggerContext.getConfiguration(); boolean changed = false; diff --git a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java index 88099b6eea3..5dd84ab413c 100644 --- a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java +++ b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java @@ -19,10 +19,11 @@ final class SentryOkHttpClientBeanPostProcessor implements BeanPostProcessor, Pr @Override public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (!(bean instanceof OkHttpClient client)) { + if (!(bean instanceof OkHttpClient)) { return bean; } + final @NotNull OkHttpClient client = (OkHttpClient) bean; if (client.getClass() != OkHttpClient.class) { ScopesAdapter.getInstance() .getOptions() diff --git a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java index c9d8684304c..141f6a8ba00 100644 --- a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java +++ b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java @@ -45,12 +45,13 @@ public boolean supportsEventType(final @NotNull ResolvableType eventType) { @Override public void onApplicationEvent(final @NotNull ApplicationEvent event) { final Object context = LogManager.getContext(false); - if (!(context instanceof LoggerContext loggerContext)) { + if (!(context instanceof LoggerContext)) { logger.info( "Sentry Log4j2 appender was not configured because Log4j2 Core is not the active logging backend. Log4j2 API calls may be routed through SLF4J."); return; } + final LoggerContext loggerContext = (LoggerContext) context; final Configuration configuration = loggerContext.getConfiguration(); boolean changed = false; diff --git a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java index 4c0bbf6c920..8409240d7fe 100644 --- a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java +++ b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java @@ -19,10 +19,11 @@ final class SentryOkHttpClientBeanPostProcessor implements BeanPostProcessor, Pr @Override public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (!(bean instanceof OkHttpClient client)) { + if (!(bean instanceof OkHttpClient)) { return bean; } + final @NotNull OkHttpClient client = (OkHttpClient) bean; if (client.getClass() != OkHttpClient.class) { ScopesAdapter.getInstance() .getOptions() diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java index a64eb826f04..b7f4646b4a8 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java @@ -25,8 +25,9 @@ public HttpServletRequestSentryUserProvider(final @NotNull SentryOptions options public @Nullable User provideUser() { if (options.getDataCollectionResolver().isUserInfo()) { final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - if (requestAttributes instanceof ServletRequestAttributes servletRequestAttributes) { - + if (requestAttributes instanceof ServletRequestAttributes) { + final ServletRequestAttributes servletRequestAttributes = + (ServletRequestAttributes) requestAttributes; final HttpServletRequest request = servletRequestAttributes.getRequest(); final User user = new User(); diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java index 28157e0336b..4d9e63a151b 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java @@ -42,7 +42,8 @@ public SentryInitBeanPostProcessor() { @SuppressWarnings({"unchecked", "deprecation"}) public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, @NotNull final String beanName) throws BeansException { - if (bean instanceof SentryOptions options) { + if (bean instanceof SentryOptions) { + final SentryOptions options = (SentryOptions) bean; if (applicationContext != null) { applicationContext diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java index ad4425131ff..ec9964f7abc 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java @@ -16,8 +16,8 @@ public final class SentryCacheBeanPostProcessor implements BeanPostProcessor, Pr @Override public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (bean instanceof CacheManager cacheManager && !(bean instanceof SentryCacheManagerWrapper)) { - return new SentryCacheManagerWrapper(cacheManager, ScopesAdapter.getInstance()); + if (bean instanceof CacheManager && !(bean instanceof SentryCacheManagerWrapper)) { + return new SentryCacheManagerWrapper((CacheManager) bean, ScopesAdapter.getInstance()); } return bean; } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java index 5fe03f385df..c6537f853c2 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java @@ -42,8 +42,8 @@ public Object invoke(final @NotNull MethodInvocation invocation) throws Throwabl if (sentryCaptureExceptionParameter != null) { Object[] args = invocation.getArguments(); for (Object arg : args) { - if (arg instanceof Exception exception) { - captureException(exception); + if (arg instanceof Exception) { + captureException((Exception) arg); break; } } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java index 6a9f33e65f1..4e7c3665aae 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java @@ -108,8 +108,8 @@ public void registerMappedBatchLoader( private @NotNull IScopes scopesFromContext(final @NotNull BatchLoaderEnvironment environment) { Object context = environment.getContext(); - if (context instanceof GraphQLContext graphqlContext) { - + if (context instanceof GraphQLContext) { + GraphQLContext graphqlContext = (GraphQLContext) context; return graphqlContext.getOrDefault(SENTRY_SCOPES_CONTEXT_KEY, NoOpScopes.getInstance()); } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java index 79bc5e11ccd..5eb4374bb1f 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java @@ -12,8 +12,8 @@ public final class SentryGraphqlBeanPostProcessor implements BeanPostProcessor, @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof BatchLoaderRegistry batchLoaderRegistry) { - return new SentryBatchLoaderRegistry(batchLoaderRegistry); + if (bean instanceof BatchLoaderRegistry) { + return new SentryBatchLoaderRegistry((BatchLoaderRegistry) bean); } return bean; } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java index dc3636a2b24..8a06e4e338e 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java @@ -36,8 +36,8 @@ public final class SentryKafkaProducerBeanPostProcessor @SuppressWarnings({"unchecked", "rawtypes"}) public @NotNull Object postProcessAfterInitialization( final @NotNull Object bean, final @NotNull String beanName) throws BeansException { - if (bean instanceof ProducerFactory factory) { - + if (bean instanceof ProducerFactory) { + final @NotNull ProducerFactory factory = (ProducerFactory) bean; final @NotNull SentryProducerPostProcessor pp = new SentryProducerPostProcessor<>(); factory.addPostProcessor(pp); if (!factory.getPostProcessors().contains(pp)) { diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java index 4d5abda711f..72535712695 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java @@ -196,7 +196,7 @@ private boolean isIgnored() { if (enqueuedTimeStr != null) { try { final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr); - final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis()); + final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis()); final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000); if (latencyMs >= 0) { transaction.setData(SpanDataConvention.MESSAGING_MESSAGE_RECEIVE_LATENCY, latencyMs); diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java index 8a5d1db3e05..0628bc1d30e 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java @@ -39,7 +39,7 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IScopes scopes) { } public SentrySpanClientHttpRequestInterceptor( - final @NotNull IScopes scopes, final boolean isRestTemplate) { + final @NotNull IScopes scopes, final @NotNull boolean isRestTemplate) { this.scopes = Objects.requireNonNull(scopes, "Scopes are required"); this.traceOrigin = isRestTemplate ? TRACE_ORIGIN_REST_TEMPLATE : TRACE_ORIGIN_REST_CLIENT; } diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java index 833e59670e2..95618f76fd7 100644 --- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java +++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java @@ -116,7 +116,7 @@ private static class TransactionNameAndSource { private final @NotNull String name; private final @NotNull TransactionNameSource source; - TransactionNameAndSource( + public TransactionNameAndSource( final @NotNull String name, final @NotNull TransactionNameSource source) { this.name = name; this.source = source; diff --git a/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java index ed26e2ee795..d1ad3086098 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java +++ b/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java @@ -202,7 +202,7 @@ private boolean isIgnored() { if (enqueuedTimeStr != null) { try { final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr); - final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis()); + final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis()); final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000); if (latencyMs >= 0) { transaction.setData(SpanDataConvention.MESSAGING_MESSAGE_RECEIVE_LATENCY, latencyMs); diff --git a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java index eab13d1a7d6..180d5df00a7 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java +++ b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java @@ -115,7 +115,7 @@ private static class TransactionNameAndSource { private final @NotNull String name; private final @NotNull TransactionNameSource source; - TransactionNameAndSource( + public TransactionNameAndSource( final @NotNull String name, final @NotNull TransactionNameSource source) { this.name = name; this.source = source; diff --git a/sentry/src/main/java/io/sentry/Baggage.java b/sentry/src/main/java/io/sentry/Baggage.java index 3c3b0aea28c..9f0753f8671 100644 --- a/sentry/src/main/java/io/sentry/Baggage.java +++ b/sentry/src/main/java/io/sentry/Baggage.java @@ -257,9 +257,6 @@ public String getThirdPartyHeader() { return thirdPartyHeader; } - // ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, which crashes on Android - // < 24. - @SuppressWarnings("JdkObsolete") public @NotNull String toHeaderString(@Nullable String thirdPartyBaggageHeaderString) { final StringBuilder sb = new StringBuilder(); String separator = ""; @@ -328,14 +325,10 @@ public String getThirdPartyHeader() { return sb.toString(); } - // The Charset overload requires Java 10. - @SuppressWarnings("JdkObsolete") private String encode(final @NotNull String value) throws UnsupportedEncodingException { return URLEncoder.encode(value, CHARSET).replaceAll("\\+", "%20"); } - // The Charset overload requires Java 10. - @SuppressWarnings("JdkObsolete") private static String decode(final @NotNull String value) throws UnsupportedEncodingException { return URLDecoder.decode(value, CHARSET); } diff --git a/sentry/src/main/java/io/sentry/Breadcrumb.java b/sentry/src/main/java/io/sentry/Breadcrumb.java index a00fb496602..4db0dcf46c5 100644 --- a/sentry/src/main/java/io/sentry/Breadcrumb.java +++ b/sentry/src/main/java/io/sentry/Breadcrumb.java @@ -630,8 +630,6 @@ public void setType(@Nullable String type) { this.type = type; } - // EMPTY_DATA is a sentinel, so identity comparison is intended. - @SuppressWarnings("ReferenceEquality") private @NotNull Map getOrCreateData() { Map currentData = data; if (currentData == EMPTY_DATA) { @@ -693,8 +691,6 @@ public void setData(@Nullable String key, @Nullable Object value) { * * @param key the key */ - // EMPTY_DATA is a sentinel, so identity comparison is intended. - @SuppressWarnings("ReferenceEquality") public void removeData(@Nullable String key) { if (key == null) { return; diff --git a/sentry/src/main/java/io/sentry/CombinedContextsView.java b/sentry/src/main/java/io/sentry/CombinedContextsView.java index 0fff6b681bd..d9a8b14c628 100644 --- a/sentry/src/main/java/io/sentry/CombinedContextsView.java +++ b/sentry/src/main/java/io/sentry/CombinedContextsView.java @@ -243,7 +243,7 @@ public void setSpring(@NotNull Spring spring) { @ApiStatus.Internal @Override - /* Not intended to be set on a scopes Context directly */ + /** Not intended to be set on a scopes Context directly */ public void setFeatureFlags(@NotNull FeatureFlags spring) { getDefaultContexts().setFeatureFlags(spring); } diff --git a/sentry/src/main/java/io/sentry/DateUtils.java b/sentry/src/main/java/io/sentry/DateUtils.java index 4be99b6322f..fcba83fbe05 100644 --- a/sentry/src/main/java/io/sentry/DateUtils.java +++ b/sentry/src/main/java/io/sentry/DateUtils.java @@ -151,10 +151,10 @@ public static double nanosToSeconds(final long nanos) { */ @SuppressWarnings("JavaUtilDate") public static double dateToSeconds(final @NotNull Date date) { - return millisToSeconds((double) date.getTime()); + return millisToSeconds(date.getTime()); } - public static long secondsToNanos(final long seconds) { + public static long secondsToNanos(final @NotNull long seconds) { return seconds * (1000L * 1000L * 1000L); } diff --git a/sentry/src/main/java/io/sentry/DefaultSpanFactory.java b/sentry/src/main/java/io/sentry/DefaultSpanFactory.java index 71dd40843a4..f664360f49b 100644 --- a/sentry/src/main/java/io/sentry/DefaultSpanFactory.java +++ b/sentry/src/main/java/io/sentry/DefaultSpanFactory.java @@ -21,7 +21,7 @@ public final class DefaultSpanFactory implements ISpanFactory { final @NotNull SpanOptions spanOptions, final @NotNull SpanContext spanContext, @Nullable ISpan parentSpan) { - /* + /** * Be careful here when executing something like parentSpan.startChild() as that might cause a * loop and a stack overflow. This can happen, e.g. when OpenTelemetry is creating spans that * use OtelSpanWrapper which calls this createSpan method that then in turn calls startChild diff --git a/sentry/src/main/java/io/sentry/DiagnosticLogger.java b/sentry/src/main/java/io/sentry/DiagnosticLogger.java index 81b8e30d2ba..c96e061f2c1 100644 --- a/sentry/src/main/java/io/sentry/DiagnosticLogger.java +++ b/sentry/src/main/java/io/sentry/DiagnosticLogger.java @@ -29,8 +29,6 @@ public DiagnosticLogger(final @NotNull SentryOptions options, final @Nullable IL * @param level The SentryLevel to test against. * @return True if a log message would be recorded for the level. Otherwise false. */ - // SentryLevel is declared in ascending severity order. - @SuppressWarnings("EnumOrdinal") @Override public boolean isEnabled(final @Nullable SentryLevel level) { final SentryLevel diagLevel = options.getDiagnosticLevel(); diff --git a/sentry/src/main/java/io/sentry/DirectoryProcessor.java b/sentry/src/main/java/io/sentry/DirectoryProcessor.java index d9f0f32c40c..17f65bb8c76 100644 --- a/sentry/src/main/java/io/sentry/DirectoryProcessor.java +++ b/sentry/src/main/java/io/sentry/DirectoryProcessor.java @@ -120,7 +120,7 @@ private static final class SendCachedEnvelopeHint private final @NotNull String filePath; private final @NotNull Queue processedEnvelopes; - SendCachedEnvelopeHint( + public SendCachedEnvelopeHint( final long flushTimeoutMillis, final @NotNull ILogger logger, final @NotNull String filePath, diff --git a/sentry/src/main/java/io/sentry/ExternalOptions.java b/sentry/src/main/java/io/sentry/ExternalOptions.java index 810130416aa..272cf1c13a9 100644 --- a/sentry/src/main/java/io/sentry/ExternalOptions.java +++ b/sentry/src/main/java/io/sentry/ExternalOptions.java @@ -242,8 +242,7 @@ public final class ExternalOptions { String profileLifecycleString = propertiesProvider.getProperty("profile-lifecycle"); if (profileLifecycleString != null && !profileLifecycleString.isEmpty()) { - options.setProfileLifecycle( - ProfileLifecycle.valueOf(profileLifecycleString.toUpperCase(Locale.ROOT))); + options.setProfileLifecycle(ProfileLifecycle.valueOf(profileLifecycleString.toUpperCase())); } return options; diff --git a/sentry/src/main/java/io/sentry/Hint.java b/sentry/src/main/java/io/sentry/Hint.java index 9281d41fa91..1e09dca5541 100644 --- a/sentry/src/main/java/io/sentry/Hint.java +++ b/sentry/src/main/java/io/sentry/Hint.java @@ -60,7 +60,7 @@ public void set(@NotNull String name, @Nullable Object hint) { } @SuppressWarnings("unchecked") - public @Nullable T getAs(@NotNull String name, @NotNull Class clazz) { + public @Nullable T getAs(@NotNull String name, @NotNull Class clazz) { try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) { Object hintValue = internalStorage.get(name); diff --git a/sentry/src/main/java/io/sentry/MonitorContexts.java b/sentry/src/main/java/io/sentry/MonitorContexts.java index 55178893767..a52ecc6b97f 100644 --- a/sentry/src/main/java/io/sentry/MonitorContexts.java +++ b/sentry/src/main/java/io/sentry/MonitorContexts.java @@ -43,9 +43,6 @@ public void setTrace(final @NotNull SpanContext traceContext) { // region json - // ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, which crashes on Android - // < 24. - @SuppressWarnings("JdkObsolete") @Override public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger) throws IOException { diff --git a/sentry/src/main/java/io/sentry/ReplayRecording.java b/sentry/src/main/java/io/sentry/ReplayRecording.java index 8c038d64c33..a83eddd380f 100644 --- a/sentry/src/main/java/io/sentry/ReplayRecording.java +++ b/sentry/src/main/java/io/sentry/ReplayRecording.java @@ -102,8 +102,7 @@ public void setUnknown(@Nullable Map unknown) { public static final class Deserializer implements JsonDeserializer { - // The rrweb protocol encodes these enums by ordinal. - @SuppressWarnings({"unchecked", "EnumOrdinal"}) + @SuppressWarnings("unchecked") @Override public @NotNull ReplayRecording deserialize( @NotNull ObjectReader reader, @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/SamplingContext.java b/sentry/src/main/java/io/sentry/SamplingContext.java index 7a9c69b0739..17ce111d0c2 100644 --- a/sentry/src/main/java/io/sentry/SamplingContext.java +++ b/sentry/src/main/java/io/sentry/SamplingContext.java @@ -20,7 +20,7 @@ public final class SamplingContext { @Deprecated @SuppressWarnings("InlineMeSuggester") - /* + /** * @deprecated creating a SamplingContext is something only the SDK should do */ public SamplingContext( diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java index d02e1b75728..54e8b893555 100644 --- a/sentry/src/main/java/io/sentry/Scope.java +++ b/sentry/src/main/java/io/sentry/Scope.java @@ -463,10 +463,10 @@ public Queue getBreadcrumbs() { */ private @Nullable Breadcrumb executeBeforeBreadcrumb( final @NotNull SentryOptions.BeforeBreadcrumbCallback callback, - final @NotNull Breadcrumb breadcrumb, + @NotNull Breadcrumb breadcrumb, final @NotNull Hint hint) { try (final @NotNull ISentryLifecycleToken ignored = SentryCallbackReentrancyGuard.enter()) { - return callback.execute(breadcrumb, hint); + breadcrumb = callback.execute(breadcrumb, hint); } catch (Throwable e) { options .getLogger() diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index f8adb54e2ca..012587eaa59 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -1353,7 +1353,7 @@ public void captureLog(@Nullable SentryLogEvent logEvent, @Nullable IScope scope options .getClientReportRecorder() .recordLostEvent(DiscardReason.BEFORE_SEND, DataCategory.LogItem); - final long logEventNumberOfBytes = + final @NotNull long logEventNumberOfBytes = JsonSerializationUtils.byteSizeOf( options.getSerializer(), options.getLogger(), tmpLogEvent); options diff --git a/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java b/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java index d1858c02767..2a7f06968dc 100644 --- a/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java +++ b/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java @@ -691,12 +691,11 @@ private static class CachedItem { private @Nullable byte[] bytes; private final @Nullable Callable dataFactory; - CachedItem(final @Nullable Callable dataFactory) { + public CachedItem(final @Nullable Callable dataFactory) { this.dataFactory = dataFactory; } - @NotNull - byte[] getBytes() throws Exception { + public @NotNull byte[] getBytes() throws Exception { if (bytes == null && dataFactory != null) { bytes = dataFactory.call(); } diff --git a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java index 3c07ec38b91..cd4ab1cc0e9 100644 --- a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java +++ b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java @@ -11,7 +11,6 @@ import java.util.Deque; import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -142,7 +141,7 @@ Deque extractExceptionQueue(final @NotNull Throwable throwable) Deque extractExceptionQueueInternal( final @NotNull Throwable throwable, final @NotNull AtomicInteger exceptionId, - final @NotNull Set circularityDetector, + final @NotNull HashSet circularityDetector, final @NotNull Deque exceptions, @Nullable String mechanismTypeOverride) { Mechanism exceptionMechanism; diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index c43b9f7a105..2b2f9d370a0 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -58,8 +58,6 @@ import org.jetbrains.annotations.TestOnly; /** Sentry SDK options */ -// Constructors call overridable methods; making them final would break the public API. -@SuppressWarnings("this-escape") @Open public class SentryOptions implements RateLimiterConfig { diff --git a/sentry/src/main/java/io/sentry/SentryThreadFactory.java b/sentry/src/main/java/io/sentry/SentryThreadFactory.java index cb0608f825e..8bd14483269 100644 --- a/sentry/src/main/java/io/sentry/SentryThreadFactory.java +++ b/sentry/src/main/java/io/sentry/SentryThreadFactory.java @@ -78,8 +78,6 @@ List getCurrentThreads( * crashed. This is the case for e.g. watchdog threads which are not the one erroring. * @return a list of SentryThread or null if none */ - // Identifies the current thread by identity. - @SuppressWarnings("ReferenceEquality") @TestOnly @Nullable List getCurrentThreads( diff --git a/sentry/src/main/java/io/sentry/SentryTracer.java b/sentry/src/main/java/io/sentry/SentryTracer.java index 781cf51417e..d60187cb4d5 100644 --- a/sentry/src/main/java/io/sentry/SentryTracer.java +++ b/sentry/src/main/java/io/sentry/SentryTracer.java @@ -154,7 +154,7 @@ private void onDeadlineTimeoutReached() { } @Override - public void forceFinish( + public @NotNull void forceFinish( final @NotNull SpanStatus status, final boolean dropIfNoChildren, final @Nullable Hint hint) { if (isFinished()) { return; diff --git a/sentry/src/main/java/io/sentry/SpanContext.java b/sentry/src/main/java/io/sentry/SpanContext.java index 4beb6673c54..19ab2c3ad87 100644 --- a/sentry/src/main/java/io/sentry/SpanContext.java +++ b/sentry/src/main/java/io/sentry/SpanContext.java @@ -16,8 +16,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -// Constructors call overridable methods; making them final would break the public API. -@SuppressWarnings("this-escape") @Open public class SpanContext implements JsonUnknown, JsonSerializable { public static final String TYPE = "trace"; diff --git a/sentry/src/main/java/io/sentry/SynchronizedCollection.java b/sentry/src/main/java/io/sentry/SynchronizedCollection.java index e88d25a235e..8a58401020b 100644 --- a/sentry/src/main/java/io/sentry/SynchronizedCollection.java +++ b/sentry/src/main/java/io/sentry/SynchronizedCollection.java @@ -50,13 +50,9 @@ class SynchronizedCollection implements Collection, Serializable { private static final long serialVersionUID = 2412805092710877986L; /** The collection to decorate */ - // Serializable only if the decorated collection is, as in Apache Commons Collections. - @SuppressWarnings("serial") private final Collection collection; /** The object to lock on, needed for List/SortedSet views */ - // Not Serializable either; the SDK never serializes these collections. - @SuppressWarnings("serial") final AutoClosableReentrantLock lock; /** diff --git a/sentry/src/main/java/io/sentry/TraceContext.java b/sentry/src/main/java/io/sentry/TraceContext.java index 957bda79f49..1bb5508f85b 100644 --- a/sentry/src/main/java/io/sentry/TraceContext.java +++ b/sentry/src/main/java/io/sentry/TraceContext.java @@ -30,7 +30,7 @@ public final class TraceContext implements JsonUnknown, JsonSerializable { } @SuppressWarnings("InlineMeSuggester") - /* + /** * @deprecated please use the constructor than also takes sampleRand */ @Deprecated diff --git a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java index a6015051d1c..6ea61895799 100644 --- a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java +++ b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java @@ -47,8 +47,6 @@ public UncaughtExceptionHandlerIntegration() { this.threadAdapter = threadAdapter; } - // Both integrations must share the same global scope instance. - @SuppressWarnings("ReferenceEquality") @Override public final void register(final @NotNull IScopes scopes, final @NotNull SentryOptions options) { if (registered) { diff --git a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java index 8dca5dfb7e3..8a097486db1 100644 --- a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java +++ b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java @@ -265,8 +265,6 @@ private void flush() { } } - // DELETE_MARKER and CLEAR_MARKER are sentinels, so identity comparison is intended. - @SuppressWarnings("ReferenceEquality") private void writePending() { // ConcurrentHashMap's iterator is weakly consistent, so removing while iterating is safe. Keys // added after iteration starts may be missed, but flush() re-checks and queues another write. diff --git a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java index 009e28c22ad..5df6d473f78 100644 --- a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java +++ b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java @@ -14,16 +14,9 @@ public final class ExceptionMechanismException extends RuntimeException { private static final long serialVersionUID = 142345454265713915L; - // Never serialized. - @SuppressWarnings("serial") private final @NotNull Mechanism exceptionMechanism; - private final @NotNull Throwable throwable; - - // Never serialized. - @SuppressWarnings("serial") private final @Nullable Thread thread; - private final boolean snapshot; /** diff --git a/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java b/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java index 84448878196..5a02a911ace 100644 --- a/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java +++ b/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java @@ -233,14 +233,13 @@ private static class FeatureFlagEntry { private final boolean result; private final long nanos; - FeatureFlagEntry(final @NotNull String flag, final boolean result, final long nanos) { + public FeatureFlagEntry(final @NotNull String flag, final boolean result, final long nanos) { this.flag = flag; this.result = result; this.nanos = nanos; } - @NotNull - FeatureFlag toFeatureFlag() { + public @NotNull FeatureFlag toFeatureFlag() { return new FeatureFlag(flag, result); } } diff --git a/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java b/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java index fc1c313ec43..1f7ac93950e 100644 --- a/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java +++ b/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java @@ -93,7 +93,7 @@ private static final class Module { private final @NotNull String name; private final @NotNull String version; - Module(final @NotNull String name, final @NotNull String version) { + public Module(final @NotNull String name, final @NotNull String version) { this.name = name; this.version = version; } diff --git a/sentry/src/main/java/io/sentry/logger/LoggerApi.java b/sentry/src/main/java/io/sentry/logger/LoggerApi.java index 69f5a5a44bc..3741ddc6209 100644 --- a/sentry/src/main/java/io/sentry/logger/LoggerApi.java +++ b/sentry/src/main/java/io/sentry/logger/LoggerApi.java @@ -152,7 +152,7 @@ private void captureLog( } } - private @NotNull Map createAttributes( + private @NotNull HashMap createAttributes( final @NotNull SentryLogParameters params, final @NotNull String message, final @Nullable Object... args) { @@ -247,7 +247,8 @@ private void captureLog( return attributes; } - private void setServerName(final @NotNull Map attributes) { + private void setServerName( + final @NotNull HashMap attributes) { final @NotNull SentryOptions options = scopes.getOptions(); final @Nullable String optionsServerName = options.getServerName(); if (optionsServerName != null) { @@ -264,7 +265,7 @@ private void setServerName(final @NotNull Map attributes) { + private void setUser(final @NotNull HashMap attributes) { final @Nullable User user = scopes.getCombinedScopeView().getUser(); if (user == null) { // In case no user is set, we should fallback to the distinct id, known as installation id, diff --git a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java index 70f5006be23..d70b4ab5c97 100644 --- a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java +++ b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java @@ -156,7 +156,7 @@ private void captureMetrics( } } - private @NotNull Map createAttributes( + private @NotNull HashMap createAttributes( final @NotNull SentryMetricsParameters params) { final @NotNull HashMap attributes = new HashMap<>(); @@ -232,7 +232,8 @@ private void captureMetrics( return attributes; } - private void setServerName(final @NotNull Map attributes) { + private void setServerName( + final @NotNull HashMap attributes) { final @NotNull SentryOptions options = scopes.getOptions(); final @Nullable String optionsServerName = options.getServerName(); if (optionsServerName != null) { @@ -249,7 +250,7 @@ private void setServerName(final @NotNull Map attributes) { + private void setUser(final @NotNull HashMap attributes) { final @Nullable User user = scopes.getCombinedScopeView().getUser(); if (user == null) { // In case no user is set, we should fallback to the distinct id, known as installation id, diff --git a/sentry/src/main/java/io/sentry/protocol/Contexts.java b/sentry/src/main/java/io/sentry/protocol/Contexts.java index d5076714076..f6ba635383a 100644 --- a/sentry/src/main/java/io/sentry/protocol/Contexts.java +++ b/sentry/src/main/java/io/sentry/protocol/Contexts.java @@ -36,8 +36,6 @@ public class Contexts implements JsonSerializable { public Contexts() {} - // Constructors call overridable methods; making them final would break the public API. - @SuppressWarnings("this-escape") public Contexts(final @NotNull Contexts contexts) { for (final Map.Entry entry : contexts.entrySet()) { if (entry != null) { @@ -254,9 +252,6 @@ public void clear() { internalStorage.clear(); } - // ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, which crashes on Android - // < 24. - @SuppressWarnings("JdkObsolete") public @NotNull Enumeration keys() { return internalStorage.keys(); } diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java b/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java index 792a46ed5bb..fc9c8c7e690 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java @@ -17,8 +17,6 @@ public enum RRWebEventType implements JsonSerializable { Custom, Plugin; - // The rrweb protocol encodes these enums by ordinal. - @SuppressWarnings("EnumOrdinal") @Override public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger) throws IOException { @@ -26,8 +24,6 @@ public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger } public static final class Deserializer implements JsonDeserializer { - // The rrweb protocol encodes these enums by ordinal. - @SuppressWarnings("EnumOrdinal") @Override public @NotNull RRWebEventType deserialize( final @NotNull ObjectReader reader, final @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java b/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java index df926d49be1..aff3c55ac37 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java @@ -30,8 +30,6 @@ public enum IncrementalSource implements JsonSerializable { AdoptedStyleSheet, CustomElement; - // The rrweb protocol encodes these enums by ordinal. - @SuppressWarnings("EnumOrdinal") @Override public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) throws IOException { @@ -39,8 +37,6 @@ public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) } public static final class Deserializer implements JsonDeserializer { - // The rrweb protocol encodes these enums by ordinal. - @SuppressWarnings("EnumOrdinal") @Override public @NotNull IncrementalSource deserialize( final @NotNull ObjectReader reader, final @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java b/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java index 6f224591659..c7bd613c1b6 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java @@ -30,8 +30,6 @@ public enum InteractionType implements JsonSerializable { TouchEnd, TouchCancel; - // The rrweb protocol encodes these enums by ordinal. - @SuppressWarnings("EnumOrdinal") @Override public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) throws IOException { @@ -39,8 +37,6 @@ public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) } public static final class Deserializer implements JsonDeserializer { - // The rrweb protocol encodes these enums by ordinal. - @SuppressWarnings("EnumOrdinal") @Override public @NotNull InteractionType deserialize( final @NotNull ObjectReader reader, final @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/time/Deadline.java b/sentry/src/main/java/io/sentry/time/Deadline.java index e2aeef9f72c..b6cc63e8768 100644 --- a/sentry/src/main/java/io/sentry/time/Deadline.java +++ b/sentry/src/main/java/io/sentry/time/Deadline.java @@ -79,8 +79,6 @@ public long remaining(final @NotNull TimeUnit unit) { * @throws IllegalArgumentException if the two were created from different tickers, whose origins * are unrelated and whose ticks are therefore not comparable. */ - // Deadlines are only comparable when they share the same ticker instance. - @SuppressWarnings("ReferenceEquality") public boolean isAfter(final @NotNull Deadline other) { if (ticker != other.ticker) { throw new IllegalArgumentException( diff --git a/sentry/src/main/java/io/sentry/util/HttpUtils.java b/sentry/src/main/java/io/sentry/util/HttpUtils.java index e81c9820e15..59ed67eb9f8 100644 --- a/sentry/src/main/java/io/sentry/util/HttpUtils.java +++ b/sentry/src/main/java/io/sentry/util/HttpUtils.java @@ -125,8 +125,6 @@ public static boolean containsSensitiveHeader(final @NotNull String header) { return filteredHeaders; } - // The Charset overload requires Java 10. - @SuppressWarnings("JdkObsolete") private static @NotNull String decodeQueryParamName(final @NotNull String name) { try { return URLDecoder.decode(name, "UTF-8"); diff --git a/sentry/src/main/java/io/sentry/util/InitUtil.java b/sentry/src/main/java/io/sentry/util/InitUtil.java index f41099b26ad..471723ac188 100644 --- a/sentry/src/main/java/io/sentry/util/InitUtil.java +++ b/sentry/src/main/java/io/sentry/util/InitUtil.java @@ -16,8 +16,6 @@ @ApiStatus.Internal public final class InitUtil { - // InitPriority is declared in ascending priority order. - @SuppressWarnings("EnumOrdinal") public static boolean shouldInit( final @Nullable SentryOptions previousOptions, final @NotNull SentryOptions newOptions, diff --git a/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java b/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java index 4e5f9be90e5..fc9bc75aa3f 100644 --- a/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java +++ b/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java @@ -129,7 +129,7 @@ public void close() { // Nothing to close } - long getByteCount() { + public long getByteCount() { return byteCount; } diff --git a/sentry/src/main/java/io/sentry/util/Objects.java b/sentry/src/main/java/io/sentry/util/Objects.java index 20f21c570b7..df7aeab38b8 100644 --- a/sentry/src/main/java/io/sentry/util/Objects.java +++ b/sentry/src/main/java/io/sentry/util/Objects.java @@ -14,8 +14,6 @@ public static T requireNonNull(final @Nullable T obj, final @NotNull String return obj; } - // Identity short-circuit, same as java.util.Objects.equals (Java 7+). - @SuppressWarnings("ReferenceEquality") public static boolean equals(@Nullable Object a, @Nullable Object b) { return (a == b) || (a != null && a.equals(b)); } diff --git a/sentry/src/main/java/io/sentry/util/Platform.java b/sentry/src/main/java/io/sentry/util/Platform.java index bad0f214db3..ad2a4e7f3c3 100644 --- a/sentry/src/main/java/io/sentry/util/Platform.java +++ b/sentry/src/main/java/io/sentry/util/Platform.java @@ -1,6 +1,7 @@ package io.sentry.util; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @ApiStatus.Internal @@ -26,7 +27,7 @@ public final class Platform { try { final @Nullable String javaStringVersion = System.getProperty("java.specification.version"); if (javaStringVersion != null) { - final double javaVersion = Double.parseDouble(javaStringVersion); + final @NotNull double javaVersion = Double.parseDouble(javaStringVersion); isJavaNinePlus = javaVersion >= 9.0; } else { isJavaNinePlus = false; diff --git a/sentry/src/main/java/io/sentry/util/UUIDGenerator.java b/sentry/src/main/java/io/sentry/util/UUIDGenerator.java index 0402190c851..1da7b4feee1 100644 --- a/sentry/src/main/java/io/sentry/util/UUIDGenerator.java +++ b/sentry/src/main/java/io/sentry/util/UUIDGenerator.java @@ -56,7 +56,7 @@ public static UUID randomUUID() { // clear variant randomBytes[8] &= 0x3f; // set to IETF variant - randomBytes[8] = (byte) (randomBytes[8] | 0x80); + randomBytes[8] |= 0x80; long msb = 0; long lsb = 0; for (int i = 0; i < 8; i++) { diff --git a/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java b/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java index 2bd50125656..42df5ca35b9 100644 --- a/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java +++ b/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java @@ -34,8 +34,6 @@ private NetworkBodyParser() {} * @param logger Optional logger * @return A NetworkBody or null if bytes are null/empty */ - // The charset is a name from the Content-Type header; unsupported names are handled below. - @SuppressWarnings("JdkObsolete") public static @Nullable NetworkBody fromBytes( @Nullable final byte[] bytes, @Nullable final String contentType, @@ -133,8 +131,6 @@ private static NetworkBody parseJson( } /** Parses URL-encoded form data into a JsonObject NetworkBody. */ - // The Charset overload requires Java 10. - @SuppressWarnings("JdkObsolete") @NotNull private static NetworkBody parseFormUrlEncoded( @NotNull final String content, final boolean isPartial, @Nullable final ILogger logger) { @@ -210,7 +206,7 @@ private static class Result { private SaferJsonParser() {} @NotNull - static SaferJsonParser.Result parse(final @NotNull JsonReader reader) { + public static SaferJsonParser.Result parse(final @NotNull JsonReader reader) { final SaferJsonParser parser = new SaferJsonParser(); parser.result.data = parser.parse(reader, 0); return parser.result; diff --git a/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java b/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java index 52e44a37eb9..4991a554c1e 100644 --- a/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java +++ b/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java @@ -1502,8 +1502,6 @@ public String getPath() { * @throws NumberFormatException if any unicode escape sequences are * malformed. */ - // Vendored from Gson, kept identical to upstream. - @SuppressWarnings("lossy-conversions") private char readEscapeCharacter() throws IOException { if (pos == limit && !fillBuffer(1)) { throw syntaxError("Unterminated escape sequence"); From ddae2a90a58885c8f31e810aa3bbc518855786ef Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Thu, 15 Oct 2026 07:14:00 +0200 Subject: [PATCH 15/22] ci: Drop the stale Java version from the build job name --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 256a9d0f21f..70cd7909a79 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,8 +11,8 @@ concurrency: jobs: build: - # Job name is a required status check in the main branch ruleset; keep it stable. - name: Build Job ubuntu-latest - Java 17 + # Job name is a required status check in the main branch ruleset; update it there too. + name: Build Job ubuntu-latest # Runs on Bitrise-hosted runners (same pattern as sentry-cocoa) instead of # GitHub-hosted ubuntu-latest, which ran out of memory during `make preMerge`. runs-on: ["bitrise_pool_name:tahoe"] From aaa1ef0a0db85f4d1f63d51b9d34e6fceb333a40 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Thu, 15 Oct 2026 08:02:39 +0200 Subject: [PATCH 16/22] fix(core): Suppress the new Error Prone and javac 21 findings in the sentry module --- sentry/src/main/java/io/sentry/Baggage.java | 8 ++++++++ sentry/src/main/java/io/sentry/Breadcrumb.java | 4 ++++ sentry/src/main/java/io/sentry/DiagnosticLogger.java | 2 ++ sentry/src/main/java/io/sentry/MonitorContexts.java | 4 ++++ sentry/src/main/java/io/sentry/ReplayRecording.java | 3 ++- sentry/src/main/java/io/sentry/SentryOptions.java | 3 +++ sentry/src/main/java/io/sentry/SentryThreadFactory.java | 2 ++ sentry/src/main/java/io/sentry/SpanContext.java | 3 +++ .../src/main/java/io/sentry/SynchronizedCollection.java | 5 +++++ .../io/sentry/UncaughtExceptionHandlerIntegration.java | 2 ++ .../java/io/sentry/cache/PersistingScopeObserver.java | 3 +++ sentry/src/main/java/io/sentry/protocol/Contexts.java | 7 +++++++ sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java | 4 ++++ .../io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java | 4 ++++ .../main/java/io/sentry/rrweb/RRWebInteractionEvent.java | 4 ++++ sentry/src/main/java/io/sentry/time/Deadline.java | 2 ++ sentry/src/main/java/io/sentry/util/HttpUtils.java | 2 ++ sentry/src/main/java/io/sentry/util/InitUtil.java | 2 ++ sentry/src/main/java/io/sentry/util/Objects.java | 2 ++ .../java/io/sentry/vendor/gson/stream/JsonReader.java | 2 ++ 20 files changed, 67 insertions(+), 1 deletion(-) diff --git a/sentry/src/main/java/io/sentry/Baggage.java b/sentry/src/main/java/io/sentry/Baggage.java index 9f0753f8671..980b6cf8061 100644 --- a/sentry/src/main/java/io/sentry/Baggage.java +++ b/sentry/src/main/java/io/sentry/Baggage.java @@ -257,6 +257,10 @@ public String getThirdPartyHeader() { return thirdPartyHeader; } + // TODO Fix for JDK21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, + // which crashes on Android + // < 24. + @SuppressWarnings("JdkObsolete") public @NotNull String toHeaderString(@Nullable String thirdPartyBaggageHeaderString) { final StringBuilder sb = new StringBuilder(); String separator = ""; @@ -325,10 +329,14 @@ public String getThirdPartyHeader() { return sb.toString(); } + // TODO Fix for JDK21: The Charset overload requires Java 10. + @SuppressWarnings("JdkObsolete") private String encode(final @NotNull String value) throws UnsupportedEncodingException { return URLEncoder.encode(value, CHARSET).replaceAll("\\+", "%20"); } + // TODO Fix for JDK21: The Charset overload requires Java 10. + @SuppressWarnings("JdkObsolete") private static String decode(final @NotNull String value) throws UnsupportedEncodingException { return URLDecoder.decode(value, CHARSET); } diff --git a/sentry/src/main/java/io/sentry/Breadcrumb.java b/sentry/src/main/java/io/sentry/Breadcrumb.java index 4db0dcf46c5..040652eb791 100644 --- a/sentry/src/main/java/io/sentry/Breadcrumb.java +++ b/sentry/src/main/java/io/sentry/Breadcrumb.java @@ -630,6 +630,8 @@ public void setType(@Nullable String type) { this.type = type; } + // TODO Fix for JDK21: EMPTY_DATA is a sentinel, so identity comparison is intended. + @SuppressWarnings("ReferenceEquality") private @NotNull Map getOrCreateData() { Map currentData = data; if (currentData == EMPTY_DATA) { @@ -691,6 +693,8 @@ public void setData(@Nullable String key, @Nullable Object value) { * * @param key the key */ + // TODO Fix for JDK21: EMPTY_DATA is a sentinel, so identity comparison is intended. + @SuppressWarnings("ReferenceEquality") public void removeData(@Nullable String key) { if (key == null) { return; diff --git a/sentry/src/main/java/io/sentry/DiagnosticLogger.java b/sentry/src/main/java/io/sentry/DiagnosticLogger.java index c96e061f2c1..83cd0e56e69 100644 --- a/sentry/src/main/java/io/sentry/DiagnosticLogger.java +++ b/sentry/src/main/java/io/sentry/DiagnosticLogger.java @@ -29,6 +29,8 @@ public DiagnosticLogger(final @NotNull SentryOptions options, final @Nullable IL * @param level The SentryLevel to test against. * @return True if a log message would be recorded for the level. Otherwise false. */ + // TODO Fix for JDK21: SentryLevel is declared in ascending severity order. + @SuppressWarnings("EnumOrdinal") @Override public boolean isEnabled(final @Nullable SentryLevel level) { final SentryLevel diagLevel = options.getDiagnosticLevel(); diff --git a/sentry/src/main/java/io/sentry/MonitorContexts.java b/sentry/src/main/java/io/sentry/MonitorContexts.java index a52ecc6b97f..2883a2d6134 100644 --- a/sentry/src/main/java/io/sentry/MonitorContexts.java +++ b/sentry/src/main/java/io/sentry/MonitorContexts.java @@ -43,6 +43,10 @@ public void setTrace(final @NotNull SpanContext traceContext) { // region json + // TODO Fix for JDK21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, + // which crashes on Android + // < 24. + @SuppressWarnings("JdkObsolete") @Override public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger) throws IOException { diff --git a/sentry/src/main/java/io/sentry/ReplayRecording.java b/sentry/src/main/java/io/sentry/ReplayRecording.java index a83eddd380f..f5aee98e71b 100644 --- a/sentry/src/main/java/io/sentry/ReplayRecording.java +++ b/sentry/src/main/java/io/sentry/ReplayRecording.java @@ -102,7 +102,8 @@ public void setUnknown(@Nullable Map unknown) { public static final class Deserializer implements JsonDeserializer { - @SuppressWarnings("unchecked") + // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings({"unchecked", "EnumOrdinal"}) @Override public @NotNull ReplayRecording deserialize( @NotNull ObjectReader reader, @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index f9b9fb13c93..6c15a89bd3a 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -58,6 +58,9 @@ import org.jetbrains.annotations.TestOnly; /** Sentry SDK options */ +// TODO Fix for JDK21: Constructors call overridable methods; making them final would break the +// public API. +@SuppressWarnings("this-escape") @Open public class SentryOptions implements RateLimiterConfig { diff --git a/sentry/src/main/java/io/sentry/SentryThreadFactory.java b/sentry/src/main/java/io/sentry/SentryThreadFactory.java index 8bd14483269..e5123f24910 100644 --- a/sentry/src/main/java/io/sentry/SentryThreadFactory.java +++ b/sentry/src/main/java/io/sentry/SentryThreadFactory.java @@ -78,6 +78,8 @@ List getCurrentThreads( * crashed. This is the case for e.g. watchdog threads which are not the one erroring. * @return a list of SentryThread or null if none */ + // TODO Fix for JDK21: Identifies the current thread by identity. + @SuppressWarnings("ReferenceEquality") @TestOnly @Nullable List getCurrentThreads( diff --git a/sentry/src/main/java/io/sentry/SpanContext.java b/sentry/src/main/java/io/sentry/SpanContext.java index 19ab2c3ad87..890eea026fe 100644 --- a/sentry/src/main/java/io/sentry/SpanContext.java +++ b/sentry/src/main/java/io/sentry/SpanContext.java @@ -16,6 +16,9 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; +// TODO Fix for JDK21: Constructors call overridable methods; making them final would break the +// public API. +@SuppressWarnings("this-escape") @Open public class SpanContext implements JsonUnknown, JsonSerializable { public static final String TYPE = "trace"; diff --git a/sentry/src/main/java/io/sentry/SynchronizedCollection.java b/sentry/src/main/java/io/sentry/SynchronizedCollection.java index 8a58401020b..9d34b255c45 100644 --- a/sentry/src/main/java/io/sentry/SynchronizedCollection.java +++ b/sentry/src/main/java/io/sentry/SynchronizedCollection.java @@ -50,9 +50,14 @@ class SynchronizedCollection implements Collection, Serializable { private static final long serialVersionUID = 2412805092710877986L; /** The collection to decorate */ + // TODO Fix for JDK21: Serializable only if the decorated collection is, as in Apache Commons + // Collections. + @SuppressWarnings("serial") private final Collection collection; /** The object to lock on, needed for List/SortedSet views */ + // TODO Fix for JDK21: Not Serializable either; the SDK never serializes these collections. + @SuppressWarnings("serial") final AutoClosableReentrantLock lock; /** diff --git a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java index 6ea61895799..3eb0bfabdb9 100644 --- a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java +++ b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java @@ -47,6 +47,8 @@ public UncaughtExceptionHandlerIntegration() { this.threadAdapter = threadAdapter; } + // TODO Fix for JDK21: Both integrations must share the same global scope instance. + @SuppressWarnings("ReferenceEquality") @Override public final void register(final @NotNull IScopes scopes, final @NotNull SentryOptions options) { if (registered) { diff --git a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java index 8a097486db1..c469d005773 100644 --- a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java +++ b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java @@ -265,6 +265,9 @@ private void flush() { } } + // TODO Fix for JDK21: DELETE_MARKER and CLEAR_MARKER are sentinels, so identity comparison is + // intended. + @SuppressWarnings("ReferenceEquality") private void writePending() { // ConcurrentHashMap's iterator is weakly consistent, so removing while iterating is safe. Keys // added after iteration starts may be missed, but flush() re-checks and queues another write. diff --git a/sentry/src/main/java/io/sentry/protocol/Contexts.java b/sentry/src/main/java/io/sentry/protocol/Contexts.java index f6ba635383a..6f7e793b566 100644 --- a/sentry/src/main/java/io/sentry/protocol/Contexts.java +++ b/sentry/src/main/java/io/sentry/protocol/Contexts.java @@ -36,6 +36,9 @@ public class Contexts implements JsonSerializable { public Contexts() {} + // TODO Fix for JDK21: Constructors call overridable methods; making them final would break the + // public API. + @SuppressWarnings("this-escape") public Contexts(final @NotNull Contexts contexts) { for (final Map.Entry entry : contexts.entrySet()) { if (entry != null) { @@ -252,6 +255,10 @@ public void clear() { internalStorage.clear(); } + // TODO Fix for JDK21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, + // which crashes on Android + // < 24. + @SuppressWarnings("JdkObsolete") public @NotNull Enumeration keys() { return internalStorage.keys(); } diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java b/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java index fc9c8c7e690..b243f29ae6d 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java @@ -17,6 +17,8 @@ public enum RRWebEventType implements JsonSerializable { Custom, Plugin; + // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger) throws IOException { @@ -24,6 +26,8 @@ public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger } public static final class Deserializer implements JsonDeserializer { + // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public @NotNull RRWebEventType deserialize( final @NotNull ObjectReader reader, final @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java b/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java index aff3c55ac37..d8efdfb9148 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java @@ -30,6 +30,8 @@ public enum IncrementalSource implements JsonSerializable { AdoptedStyleSheet, CustomElement; + // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) throws IOException { @@ -37,6 +39,8 @@ public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) } public static final class Deserializer implements JsonDeserializer { + // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public @NotNull IncrementalSource deserialize( final @NotNull ObjectReader reader, final @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java b/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java index c7bd613c1b6..e3e8028010f 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java @@ -30,6 +30,8 @@ public enum InteractionType implements JsonSerializable { TouchEnd, TouchCancel; + // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) throws IOException { @@ -37,6 +39,8 @@ public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) } public static final class Deserializer implements JsonDeserializer { + // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + @SuppressWarnings("EnumOrdinal") @Override public @NotNull InteractionType deserialize( final @NotNull ObjectReader reader, final @NotNull ILogger logger) throws Exception { diff --git a/sentry/src/main/java/io/sentry/time/Deadline.java b/sentry/src/main/java/io/sentry/time/Deadline.java index b6cc63e8768..a4f7d0f5416 100644 --- a/sentry/src/main/java/io/sentry/time/Deadline.java +++ b/sentry/src/main/java/io/sentry/time/Deadline.java @@ -79,6 +79,8 @@ public long remaining(final @NotNull TimeUnit unit) { * @throws IllegalArgumentException if the two were created from different tickers, whose origins * are unrelated and whose ticks are therefore not comparable. */ + // TODO Fix for JDK21: Deadlines are only comparable when they share the same ticker instance. + @SuppressWarnings("ReferenceEquality") public boolean isAfter(final @NotNull Deadline other) { if (ticker != other.ticker) { throw new IllegalArgumentException( diff --git a/sentry/src/main/java/io/sentry/util/HttpUtils.java b/sentry/src/main/java/io/sentry/util/HttpUtils.java index 59ed67eb9f8..bae17006d44 100644 --- a/sentry/src/main/java/io/sentry/util/HttpUtils.java +++ b/sentry/src/main/java/io/sentry/util/HttpUtils.java @@ -125,6 +125,8 @@ public static boolean containsSensitiveHeader(final @NotNull String header) { return filteredHeaders; } + // TODO Fix for JDK21: The Charset overload requires Java 10. + @SuppressWarnings("JdkObsolete") private static @NotNull String decodeQueryParamName(final @NotNull String name) { try { return URLDecoder.decode(name, "UTF-8"); diff --git a/sentry/src/main/java/io/sentry/util/InitUtil.java b/sentry/src/main/java/io/sentry/util/InitUtil.java index 471723ac188..b45e68c6808 100644 --- a/sentry/src/main/java/io/sentry/util/InitUtil.java +++ b/sentry/src/main/java/io/sentry/util/InitUtil.java @@ -16,6 +16,8 @@ @ApiStatus.Internal public final class InitUtil { + // TODO Fix for JDK21: InitPriority is declared in ascending priority order. + @SuppressWarnings("EnumOrdinal") public static boolean shouldInit( final @Nullable SentryOptions previousOptions, final @NotNull SentryOptions newOptions, diff --git a/sentry/src/main/java/io/sentry/util/Objects.java b/sentry/src/main/java/io/sentry/util/Objects.java index df7aeab38b8..3a3885ec105 100644 --- a/sentry/src/main/java/io/sentry/util/Objects.java +++ b/sentry/src/main/java/io/sentry/util/Objects.java @@ -14,6 +14,8 @@ public static T requireNonNull(final @Nullable T obj, final @NotNull String return obj; } + // TODO Fix for JDK21: Identity short-circuit, same as java.util.Objects.equals (Java 7+). + @SuppressWarnings("ReferenceEquality") public static boolean equals(@Nullable Object a, @Nullable Object b) { return (a == b) || (a != null && a.equals(b)); } diff --git a/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java b/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java index 4991a554c1e..bf94c6c31d6 100644 --- a/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java +++ b/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java @@ -1502,6 +1502,8 @@ public String getPath() { * @throws NumberFormatException if any unicode escape sequences are * malformed. */ + // TODO Fix for JDK21: Vendored from Gson, kept identical to upstream. + @SuppressWarnings("lossy-conversions") private char readEscapeCharacter() throws IOException { if (pos == limit && !fillBuffer(1)) { throw syntaxError("Unterminated escape sequence"); From fef477263d4a4385c0ca6ac4c6eb1754148d1993 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Thu, 15 Oct 2026 08:03:05 +0200 Subject: [PATCH 17/22] fix(core): Resolve the remaining Error Prone and javac 21 findings in the sentry module --- sentry/src/main/java/io/sentry/CombinedContextsView.java | 2 +- sentry/src/main/java/io/sentry/DateUtils.java | 4 ++-- sentry/src/main/java/io/sentry/DefaultSpanFactory.java | 2 +- sentry/src/main/java/io/sentry/DirectoryProcessor.java | 2 +- sentry/src/main/java/io/sentry/ExternalOptions.java | 3 ++- sentry/src/main/java/io/sentry/Hint.java | 2 +- sentry/src/main/java/io/sentry/SamplingContext.java | 2 +- sentry/src/main/java/io/sentry/Scope.java | 5 ++--- sentry/src/main/java/io/sentry/SentryEnvelopeItem.java | 5 +++-- sentry/src/main/java/io/sentry/SentryExceptionFactory.java | 3 ++- sentry/src/main/java/io/sentry/SentryTracer.java | 2 +- sentry/src/main/java/io/sentry/TraceContext.java | 2 +- .../io/sentry/exception/ExceptionMechanismException.java | 7 +++++++ .../java/io/sentry/featureflags/FeatureFlagBuffer.java | 5 +++-- .../io/sentry/internal/modules/ManifestModulesLoader.java | 2 +- sentry/src/main/java/io/sentry/logger/LoggerApi.java | 7 +++---- sentry/src/main/java/io/sentry/metrics/MetricsApi.java | 7 +++---- .../main/java/io/sentry/util/JsonSerializationUtils.java | 2 +- sentry/src/main/java/io/sentry/util/Platform.java | 3 +-- sentry/src/main/java/io/sentry/util/UUIDGenerator.java | 2 +- .../java/io/sentry/util/network/NetworkBodyParser.java | 7 ++++++- 21 files changed, 44 insertions(+), 32 deletions(-) diff --git a/sentry/src/main/java/io/sentry/CombinedContextsView.java b/sentry/src/main/java/io/sentry/CombinedContextsView.java index d9a8b14c628..0fff6b681bd 100644 --- a/sentry/src/main/java/io/sentry/CombinedContextsView.java +++ b/sentry/src/main/java/io/sentry/CombinedContextsView.java @@ -243,7 +243,7 @@ public void setSpring(@NotNull Spring spring) { @ApiStatus.Internal @Override - /** Not intended to be set on a scopes Context directly */ + /* Not intended to be set on a scopes Context directly */ public void setFeatureFlags(@NotNull FeatureFlags spring) { getDefaultContexts().setFeatureFlags(spring); } diff --git a/sentry/src/main/java/io/sentry/DateUtils.java b/sentry/src/main/java/io/sentry/DateUtils.java index fcba83fbe05..4be99b6322f 100644 --- a/sentry/src/main/java/io/sentry/DateUtils.java +++ b/sentry/src/main/java/io/sentry/DateUtils.java @@ -151,10 +151,10 @@ public static double nanosToSeconds(final long nanos) { */ @SuppressWarnings("JavaUtilDate") public static double dateToSeconds(final @NotNull Date date) { - return millisToSeconds(date.getTime()); + return millisToSeconds((double) date.getTime()); } - public static long secondsToNanos(final @NotNull long seconds) { + public static long secondsToNanos(final long seconds) { return seconds * (1000L * 1000L * 1000L); } diff --git a/sentry/src/main/java/io/sentry/DefaultSpanFactory.java b/sentry/src/main/java/io/sentry/DefaultSpanFactory.java index f664360f49b..71dd40843a4 100644 --- a/sentry/src/main/java/io/sentry/DefaultSpanFactory.java +++ b/sentry/src/main/java/io/sentry/DefaultSpanFactory.java @@ -21,7 +21,7 @@ public final class DefaultSpanFactory implements ISpanFactory { final @NotNull SpanOptions spanOptions, final @NotNull SpanContext spanContext, @Nullable ISpan parentSpan) { - /** + /* * Be careful here when executing something like parentSpan.startChild() as that might cause a * loop and a stack overflow. This can happen, e.g. when OpenTelemetry is creating spans that * use OtelSpanWrapper which calls this createSpan method that then in turn calls startChild diff --git a/sentry/src/main/java/io/sentry/DirectoryProcessor.java b/sentry/src/main/java/io/sentry/DirectoryProcessor.java index 17f65bb8c76..d9f0f32c40c 100644 --- a/sentry/src/main/java/io/sentry/DirectoryProcessor.java +++ b/sentry/src/main/java/io/sentry/DirectoryProcessor.java @@ -120,7 +120,7 @@ private static final class SendCachedEnvelopeHint private final @NotNull String filePath; private final @NotNull Queue processedEnvelopes; - public SendCachedEnvelopeHint( + SendCachedEnvelopeHint( final long flushTimeoutMillis, final @NotNull ILogger logger, final @NotNull String filePath, diff --git a/sentry/src/main/java/io/sentry/ExternalOptions.java b/sentry/src/main/java/io/sentry/ExternalOptions.java index 272cf1c13a9..810130416aa 100644 --- a/sentry/src/main/java/io/sentry/ExternalOptions.java +++ b/sentry/src/main/java/io/sentry/ExternalOptions.java @@ -242,7 +242,8 @@ public final class ExternalOptions { String profileLifecycleString = propertiesProvider.getProperty("profile-lifecycle"); if (profileLifecycleString != null && !profileLifecycleString.isEmpty()) { - options.setProfileLifecycle(ProfileLifecycle.valueOf(profileLifecycleString.toUpperCase())); + options.setProfileLifecycle( + ProfileLifecycle.valueOf(profileLifecycleString.toUpperCase(Locale.ROOT))); } return options; diff --git a/sentry/src/main/java/io/sentry/Hint.java b/sentry/src/main/java/io/sentry/Hint.java index 1e09dca5541..9281d41fa91 100644 --- a/sentry/src/main/java/io/sentry/Hint.java +++ b/sentry/src/main/java/io/sentry/Hint.java @@ -60,7 +60,7 @@ public void set(@NotNull String name, @Nullable Object hint) { } @SuppressWarnings("unchecked") - public @Nullable T getAs(@NotNull String name, @NotNull Class clazz) { + public @Nullable T getAs(@NotNull String name, @NotNull Class clazz) { try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) { Object hintValue = internalStorage.get(name); diff --git a/sentry/src/main/java/io/sentry/SamplingContext.java b/sentry/src/main/java/io/sentry/SamplingContext.java index 17ce111d0c2..7a9c69b0739 100644 --- a/sentry/src/main/java/io/sentry/SamplingContext.java +++ b/sentry/src/main/java/io/sentry/SamplingContext.java @@ -20,7 +20,7 @@ public final class SamplingContext { @Deprecated @SuppressWarnings("InlineMeSuggester") - /** + /* * @deprecated creating a SamplingContext is something only the SDK should do */ public SamplingContext( diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java index 42aef2821ac..ec98cc5fcaf 100644 --- a/sentry/src/main/java/io/sentry/Scope.java +++ b/sentry/src/main/java/io/sentry/Scope.java @@ -463,10 +463,10 @@ public Queue getBreadcrumbs() { */ private @Nullable Breadcrumb executeBeforeBreadcrumb( final @NotNull SentryOptions.BeforeBreadcrumbCallback callback, - @NotNull Breadcrumb breadcrumb, + final @NotNull Breadcrumb breadcrumb, final @NotNull Hint hint) { try (final @NotNull ISentryLifecycleToken ignored = SentryCallbackReentrancyGuard.enter()) { - breadcrumb = callback.execute(breadcrumb, hint); + return callback.execute(breadcrumb, hint); } catch (Throwable e) { options .getLogger() @@ -476,7 +476,6 @@ public Queue getBreadcrumbs() { e); return null; } - return breadcrumb; } /** diff --git a/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java b/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java index 2a7f06968dc..d1858c02767 100644 --- a/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java +++ b/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java @@ -691,11 +691,12 @@ private static class CachedItem { private @Nullable byte[] bytes; private final @Nullable Callable dataFactory; - public CachedItem(final @Nullable Callable dataFactory) { + CachedItem(final @Nullable Callable dataFactory) { this.dataFactory = dataFactory; } - public @NotNull byte[] getBytes() throws Exception { + @NotNull + byte[] getBytes() throws Exception { if (bytes == null && dataFactory != null) { bytes = dataFactory.call(); } diff --git a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java index cd4ab1cc0e9..3c07ec38b91 100644 --- a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java +++ b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java @@ -11,6 +11,7 @@ import java.util.Deque; import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -141,7 +142,7 @@ Deque extractExceptionQueue(final @NotNull Throwable throwable) Deque extractExceptionQueueInternal( final @NotNull Throwable throwable, final @NotNull AtomicInteger exceptionId, - final @NotNull HashSet circularityDetector, + final @NotNull Set circularityDetector, final @NotNull Deque exceptions, @Nullable String mechanismTypeOverride) { Mechanism exceptionMechanism; diff --git a/sentry/src/main/java/io/sentry/SentryTracer.java b/sentry/src/main/java/io/sentry/SentryTracer.java index d60187cb4d5..781cf51417e 100644 --- a/sentry/src/main/java/io/sentry/SentryTracer.java +++ b/sentry/src/main/java/io/sentry/SentryTracer.java @@ -154,7 +154,7 @@ private void onDeadlineTimeoutReached() { } @Override - public @NotNull void forceFinish( + public void forceFinish( final @NotNull SpanStatus status, final boolean dropIfNoChildren, final @Nullable Hint hint) { if (isFinished()) { return; diff --git a/sentry/src/main/java/io/sentry/TraceContext.java b/sentry/src/main/java/io/sentry/TraceContext.java index 1bb5508f85b..957bda79f49 100644 --- a/sentry/src/main/java/io/sentry/TraceContext.java +++ b/sentry/src/main/java/io/sentry/TraceContext.java @@ -30,7 +30,7 @@ public final class TraceContext implements JsonUnknown, JsonSerializable { } @SuppressWarnings("InlineMeSuggester") - /** + /* * @deprecated please use the constructor than also takes sampleRand */ @Deprecated diff --git a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java index 5df6d473f78..6479ed49671 100644 --- a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java +++ b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java @@ -14,9 +14,16 @@ public final class ExceptionMechanismException extends RuntimeException { private static final long serialVersionUID = 142345454265713915L; + // TODO Fix for JDK21: Never serialized. + @SuppressWarnings("serial") private final @NotNull Mechanism exceptionMechanism; + private final @NotNull Throwable throwable; + + // TODO Fix for JDK21: Never serialized. + @SuppressWarnings("serial") private final @Nullable Thread thread; + private final boolean snapshot; /** diff --git a/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java b/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java index 5a02a911ace..84448878196 100644 --- a/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java +++ b/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java @@ -233,13 +233,14 @@ private static class FeatureFlagEntry { private final boolean result; private final long nanos; - public FeatureFlagEntry(final @NotNull String flag, final boolean result, final long nanos) { + FeatureFlagEntry(final @NotNull String flag, final boolean result, final long nanos) { this.flag = flag; this.result = result; this.nanos = nanos; } - public @NotNull FeatureFlag toFeatureFlag() { + @NotNull + FeatureFlag toFeatureFlag() { return new FeatureFlag(flag, result); } } diff --git a/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java b/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java index 1f7ac93950e..fc1c313ec43 100644 --- a/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java +++ b/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java @@ -93,7 +93,7 @@ private static final class Module { private final @NotNull String name; private final @NotNull String version; - public Module(final @NotNull String name, final @NotNull String version) { + Module(final @NotNull String name, final @NotNull String version) { this.name = name; this.version = version; } diff --git a/sentry/src/main/java/io/sentry/logger/LoggerApi.java b/sentry/src/main/java/io/sentry/logger/LoggerApi.java index 139ac615394..77de6902614 100644 --- a/sentry/src/main/java/io/sentry/logger/LoggerApi.java +++ b/sentry/src/main/java/io/sentry/logger/LoggerApi.java @@ -151,7 +151,7 @@ private void captureLog( } } - private @NotNull HashMap createAttributes( + private @NotNull Map createAttributes( final @NotNull SentryLogParameters params, final @NotNull String message, final @Nullable Object... args) { @@ -246,8 +246,7 @@ private void captureLog( return attributes; } - private void setServerName( - final @NotNull HashMap attributes) { + private void setServerName(final @NotNull Map attributes) { final @NotNull SentryOptions options = scopes.getOptions(); final @Nullable String optionsServerName = options.getServerName(); if (optionsServerName != null) { @@ -264,7 +263,7 @@ private void setServerName( } } - private void setUser(final @NotNull HashMap attributes) { + private void setUser(final @NotNull Map attributes) { final @Nullable User user = scopes.getCombinedScopeView().getUser(); if (user == null) { // In case no user is set, we should fallback to the distinct id, known as installation id, diff --git a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java index 93564e4ddac..fa78511d224 100644 --- a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java +++ b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java @@ -155,7 +155,7 @@ private void captureMetrics( } } - private @NotNull HashMap createAttributes( + private @NotNull Map createAttributes( final @NotNull SentryMetricsParameters params) { final @NotNull HashMap attributes = new HashMap<>(); @@ -231,8 +231,7 @@ private void captureMetrics( return attributes; } - private void setServerName( - final @NotNull HashMap attributes) { + private void setServerName(final @NotNull Map attributes) { final @NotNull SentryOptions options = scopes.getOptions(); final @Nullable String optionsServerName = options.getServerName(); if (optionsServerName != null) { @@ -249,7 +248,7 @@ private void setServerName( } } - private void setUser(final @NotNull HashMap attributes) { + private void setUser(final @NotNull Map attributes) { final @Nullable User user = scopes.getCombinedScopeView().getUser(); if (user == null) { // In case no user is set, we should fallback to the distinct id, known as installation id, diff --git a/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java b/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java index fc9bc75aa3f..4e5f9be90e5 100644 --- a/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java +++ b/sentry/src/main/java/io/sentry/util/JsonSerializationUtils.java @@ -129,7 +129,7 @@ public void close() { // Nothing to close } - public long getByteCount() { + long getByteCount() { return byteCount; } diff --git a/sentry/src/main/java/io/sentry/util/Platform.java b/sentry/src/main/java/io/sentry/util/Platform.java index ad2a4e7f3c3..bad0f214db3 100644 --- a/sentry/src/main/java/io/sentry/util/Platform.java +++ b/sentry/src/main/java/io/sentry/util/Platform.java @@ -1,7 +1,6 @@ package io.sentry.util; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @ApiStatus.Internal @@ -27,7 +26,7 @@ public final class Platform { try { final @Nullable String javaStringVersion = System.getProperty("java.specification.version"); if (javaStringVersion != null) { - final @NotNull double javaVersion = Double.parseDouble(javaStringVersion); + final double javaVersion = Double.parseDouble(javaStringVersion); isJavaNinePlus = javaVersion >= 9.0; } else { isJavaNinePlus = false; diff --git a/sentry/src/main/java/io/sentry/util/UUIDGenerator.java b/sentry/src/main/java/io/sentry/util/UUIDGenerator.java index 1da7b4feee1..0402190c851 100644 --- a/sentry/src/main/java/io/sentry/util/UUIDGenerator.java +++ b/sentry/src/main/java/io/sentry/util/UUIDGenerator.java @@ -56,7 +56,7 @@ public static UUID randomUUID() { // clear variant randomBytes[8] &= 0x3f; // set to IETF variant - randomBytes[8] |= 0x80; + randomBytes[8] = (byte) (randomBytes[8] | 0x80); long msb = 0; long lsb = 0; for (int i = 0; i < 8; i++) { diff --git a/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java b/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java index 42df5ca35b9..0cdcad833f8 100644 --- a/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java +++ b/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java @@ -34,6 +34,9 @@ private NetworkBodyParser() {} * @param logger Optional logger * @return A NetworkBody or null if bytes are null/empty */ + // TODO Fix for JDK21: The charset is a name from the Content-Type header; unsupported names are + // handled below. + @SuppressWarnings("JdkObsolete") public static @Nullable NetworkBody fromBytes( @Nullable final byte[] bytes, @Nullable final String contentType, @@ -131,6 +134,8 @@ private static NetworkBody parseJson( } /** Parses URL-encoded form data into a JsonObject NetworkBody. */ + // TODO Fix for JDK21: The Charset overload requires Java 10. + @SuppressWarnings("JdkObsolete") @NotNull private static NetworkBody parseFormUrlEncoded( @NotNull final String content, final boolean isPartial, @Nullable final ILogger logger) { @@ -206,7 +211,7 @@ private static class Result { private SaferJsonParser() {} @NotNull - public static SaferJsonParser.Result parse(final @NotNull JsonReader reader) { + static SaferJsonParser.Result parse(final @NotNull JsonReader reader) { final SaferJsonParser parser = new SaferJsonParser(); parser.result.data = parser.parse(reader, 0); return parser.result; From 61c435202890907b2eb4fe783e9ad4b847f836a6 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Thu, 15 Oct 2026 11:30:01 +0200 Subject: [PATCH 18/22] build: Move the JDK and bytecode level decisions into the io.sentry.compilation plugin --- build-logic/build.gradle.kts | 10 ++- .../kotlin/io.sentry.jvm-targets.gradle.kts | 55 ------------ .../sentry/gradle/SentryCompilationPlugin.kt | 86 +++++++++++++++++++ build.gradle.kts | 22 +---- gradle/libs.versions.toml | 4 + .../build.gradle.kts | 9 -- .../sentry-samples-android/build.gradle.kts | 8 -- 7 files changed, 100 insertions(+), 94 deletions(-) delete mode 100644 build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts create mode 100644 build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 2688055085e..b88cf83d89c 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -4,17 +4,25 @@ plugins { repositories { gradlePluginPortal() + // AGP is only published to Google's repository. + google() } dependencies { implementation(libs.animalsniffer.gradle.plugin) implementation(libs.spotlessLib) - // Only for the Kotlin task types the jvm-targets plugin configures. + // Only for the Kotlin task types the android-compilation plugin configures. compileOnly(libs.kotlin.gradle.plugin) + // Only for the AGP extension types the android-compilation plugin configures. + compileOnly(libs.android.gradle.plugin) } gradlePlugin { plugins { + register("sentryCompilation") { + id = "io.sentry.compilation" + implementationClass = "io.sentry.gradle.SentryCompilationPlugin" + } register("sentryAnimalSniffer") { id = "io.sentry.animalsniffer" implementationClass = "io.sentry.gradle.SentryAnimalSnifferPlugin" diff --git a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts b/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts deleted file mode 100644 index 806c1db290b..00000000000 --- a/build-logic/src/main/kotlin/io.sentry.jvm-targets.gradle.kts +++ /dev/null @@ -1,55 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile - -// Compilation and tests run on this JDK whatever JDK runs Gradle, so a contributor on a newer JDK -// gets the same output as CI. Error Prone 2.50 ships Java 21 bytecode and needs javac 21 as well. -// This picks the JDK only - every module pins the bytecode level it publishes itself. -val buildJdk = JavaLanguageVersion.of(21) - -plugins.withType { - extensions.configure { toolchain { languageVersion.set(buildJdk) } } -} - -/** - * Targets [buildJdk] in the compile tasks that [taskFilter] selects. Both languages move together, - * because the Kotlin plugin rejects a Java/Kotlin target mismatch. - */ -fun Project.applyToolchainToCompileTasks(taskFilter: (Task) -> Boolean) { - // AGP assigns these task properties while it creates the variants, so this has to run later. - afterEvaluate { - tasks.withType().matching(taskFilter).configureEach { - sourceCompatibility = buildJdk.toString() - targetCompatibility = buildJdk.toString() - } - tasks.withType().matching(taskFilter).configureEach { - compilerOptions.jvmTarget.set(JvmTarget.fromTarget(buildJdk.toString())) - } - } -} - -listOf("com.android.library", "com.android.application").forEach { pluginId -> - plugins.withId(pluginId) { - // Mockito 5 and mockito-kotlin 6 are built for Java 11, so test code (never published) can't - // share the Java 8 target of the published code. Other modules pin main compilation only, which - // leaves their test tasks on the toolchain; AGP has no such split, as compileOptions applies to - // every variant, so its unit tests need this. - applyToolchainToCompileTasks { it.name.contains("UnitTest") } - } -} - -// Published code targets Java 8. release compiles against that version's class library instead of -// the build JDK's, so newer JDK APIs (e.g. List.getFirst()) can't leak into published bytecode. -// Modules that publish a higher level override this; test code and samples are never published and -// follow the toolchain. -// Keep this in sync with the publication filter in the root build script. -val isPublished = - !name.contains("sample") && - !name.contains("integration-tests") && - name != "sentry-system-test-support" && - name != "sentry-test-support" - -if (isPublished) { - plugins.withId("java-library") { - tasks.named("compileJava") { options.release.set(8) } - } -} diff --git a/build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt b/build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt new file mode 100644 index 00000000000..a608110cb98 --- /dev/null +++ b/build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt @@ -0,0 +1,86 @@ +package io.sentry.gradle + +import com.android.build.gradle.BaseExtension +import org.gradle.api.JavaVersion +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.jvm.toolchain.JavaLanguageVersion +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile + +/** The JDK every module compiles and tests with, whatever JDK runs Gradle. */ +private val BUILD_JDK = JavaLanguageVersion.of(21) + +/** The level the SDK publishes, so that Java 8 consumers can still use it. */ +private val PUBLISHED_JAVA_VERSION = JavaVersion.VERSION_1_8 + +/** + * Holds every toolchain, bytecode level decision and compilation option of a module. It does the + * following + * - sample apps target the build JDK (21) + * - unit test code will target the build JDK (21) (required for Mockito 5) + * - published JVM modules main code pins the Java 1.8 release + * - published Android modules main code targets Java 1.8 + * - minSdk is set for Android libraries + */ +class SentryCompilationPlugin : Plugin { + override fun apply(project: Project) { + project.plugins.withType(JavaBasePlugin::class.java) { + project.extensions.getByType(JavaPluginExtension::class.java).toolchain { + languageVersion.set(BUILD_JDK) + } + } + + // Only works for non-android modules + // See https://issuetracker.google.com/issues/278800528 + project.plugins.withId("com.vanniktech.maven.publish") { + project.plugins.withId("java-library") { + project.tasks.named("compileJava", JavaCompile::class.java) { + options.release.set(PUBLISHED_JAVA_VERSION.majorVersion.toInt()) + } + } + } + + project.plugins.withId("com.android.library") { + val android = project.extensions.getByType(BaseExtension::class.java) + android.compileOptions { + sourceCompatibility = PUBLISHED_JAVA_VERSION + targetCompatibility = PUBLISHED_JAVA_VERSION + } + android.defaultConfig { aarMetadata { minCompileSdk = project.minSdk() } } + } + + listOf("com.android.library", "com.android.application").forEach { pluginId -> + project.plugins.withId(pluginId) { project.targetBuildJdkForUnitTests() } + } + } + + private fun Project.minSdk(): Int = + extensions + .getByType(VersionCatalogsExtension::class.java) + .named("libs") + .findVersion("minSdk") + .orElseThrow { IllegalStateException("libs.versions.minSdk is missing") } + .requiredVersion + .toInt() + + private fun Project.targetBuildJdkForUnitTests() { + // AGP assigns these task properties when it creates the compile tasks, as they can be + // variant aware, so right now there's no way around using afterEvaluate + afterEvaluate { + val unitTestTask = { task: Task -> task.name.contains("UnitTest") } + tasks.withType(JavaCompile::class.java).matching(unitTestTask).configureEach { + sourceCompatibility = BUILD_JDK.toString() + targetCompatibility = BUILD_JDK.toString() + } + tasks.withType(KotlinJvmCompile::class.java).matching(unitTestTask).configureEach { + compilerOptions.jvmTarget.set(JvmTarget.fromTarget(BUILD_JDK.toString())) + } + } + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 7957f948d1b..e28218d6989 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -115,7 +115,7 @@ allprojects { subprojects { apply { plugin("io.sentry.spotless") } - apply { plugin("io.sentry.jvm-targets") } + apply { plugin("io.sentry.compilation") } plugins.withId(Config.QualityPlugins.detektPlugin) { configure { @@ -170,26 +170,6 @@ subprojects { } } - // AGP 9 defaults Android modules to Java 11. Pin the published library modules back - // to Java 8 so their bytecode stays consumable by Java 8 projects, mirroring the - // java-library pin in the io.sentry.jvm-targets plugin. AGP compiles against android.jar, - // so it has no release equivalent. - plugins.withId("com.android.library") { - configure { - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - // AGP 9 defaults the AAR metadata minCompileSdk to the library's compileSdk, - // which would force every consumer onto that compile SDK. Pin it to our minSdk - // so consumers remain free to compile against any SDK we support, as before. - defaultConfig { - aarMetadata { minCompileSdk = libs.versions.minSdk.get().toInt() } - } - } - } - apply() afterEvaluate { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4feeebbb952..b356ebfd4da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -38,6 +38,9 @@ retrofit = "2.9.0" room2 = "2.8.4" room3 = "3.0.0-rc01" sagp = "6.13.0" +# Compile-time only, for the AGP types the build-logic convention plugins use. The AGP that +# actually runs the build comes from the root buildscript (Config.AGP, overridable via VERSION_AGP). +agp = "9.4.0" sqlite = "2.6.2" sqliteRc = "2.7.0-rc01" # Required by Room3 3.0.0-rc* slf4j = "1.7.30" @@ -153,6 +156,7 @@ leakcanary = { module = "com.squareup.leakcanary:leakcanary-android", version = lottie-compose = { module = "com.airbnb.android:lottie-compose", version = "6.7.1" } logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } nopen-annotations = { module = "com.jakewharton.nopen:nopen-annotations", version.ref = "nopen" } nopen-checker = { module = "com.jakewharton.nopen:nopen-checker", version.ref = "nopen" } nullaway = { module = "com.uber.nullaway:nullaway", version = "0.14.2" } diff --git a/sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build.gradle.kts index 18a5b6cb7f5..cab7c28f934 100644 --- a/sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build.gradle.kts +++ b/sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build.gradle.kts @@ -1,5 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 - plugins { id("com.android.test") alias(libs.plugins.kotlin.android) @@ -28,13 +26,6 @@ android { } } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } - - kotlin { compilerOptions.jvmTarget = JVM_11 } - targetProjectPath = ":sentry-samples:sentry-samples-android" // Run the test in its own process so it measures the target app cold, not itself. experimentalProperties["android.experimental.self-instrumenting"] = true diff --git a/sentry-samples/sentry-samples-android/build.gradle.kts b/sentry-samples/sentry-samples-android/build.gradle.kts index 4fee4a1b92a..cf4b054e354 100644 --- a/sentry-samples/sentry-samples-android/build.gradle.kts +++ b/sentry-samples/sentry-samples-android/build.gradle.kts @@ -129,14 +129,6 @@ android { } } - // Java 11 b/c androidx.room3 requires it. - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } - - kotlin { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 } - androidComponents.onVariants { variant -> variant.buildConfigFields?.put( "USE_SAGP", From c667f662b7135476a80201558f51223abde03fea Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Thu, 15 Oct 2026 12:57:49 +0200 Subject: [PATCH 19/22] Address PR comments --- build-logic/build.gradle.kts | 2 -- sentry-system-test-support/build.gradle.kts | 2 -- sentry-test-support/build.gradle.kts | 2 -- settings.gradle.kts | 2 -- 4 files changed, 8 deletions(-) diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index b88cf83d89c..25702008619 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -11,9 +11,7 @@ repositories { dependencies { implementation(libs.animalsniffer.gradle.plugin) implementation(libs.spotlessLib) - // Only for the Kotlin task types the android-compilation plugin configures. compileOnly(libs.kotlin.gradle.plugin) - // Only for the AGP extension types the android-compilation plugin configures. compileOnly(libs.android.gradle.plugin) } diff --git a/sentry-system-test-support/build.gradle.kts b/sentry-system-test-support/build.gradle.kts index daea0bca4b3..ecfdc6011f8 100644 --- a/sentry-system-test-support/build.gradle.kts +++ b/sentry-system-test-support/build.gradle.kts @@ -7,8 +7,6 @@ plugins { id("com.apollographql.apollo") version "4.1.1" } -// Not published and test-only, so it keeps the toolchain's JVM target instead of pinning Java 8 -// like the published modules do. tasks.withType().configureEach { compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/sentry-test-support/build.gradle.kts b/sentry-test-support/build.gradle.kts index 4f5ab04b21f..ce6325fe1ba 100644 --- a/sentry-test-support/build.gradle.kts +++ b/sentry-test-support/build.gradle.kts @@ -6,8 +6,6 @@ plugins { alias(libs.plugins.gradle.versions) } -// Not published and test-only, so it keeps the toolchain's JVM target instead of pinning Java 8 -// like the published modules do. tasks.withType().configureEach { compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 diff --git a/settings.gradle.kts b/settings.gradle.kts index 97eaa4dd000..413ab5fd59b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,8 +20,6 @@ pluginManagement { plugins { id("com.gradle.develocity") version "4.5.0" id("com.gradle.common-custom-user-data-gradle-plugin") version "2.8.0" - // Downloads the JDK of the toolchain configured in build.gradle.kts when no local one matches. - id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } develocity { From 4d4654d5eaf15341e350c132a80f1237ad8b402b Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Thu, 15 Oct 2026 13:16:04 +0200 Subject: [PATCH 20/22] test(android): Make the flush timeout verifies match the real log call --- .../test/java/io/sentry/android/core/AnrV2IntegrationTest.kt | 2 +- .../sentry/android/core/ApplicationExitIntegrationTestBase.kt | 4 ++-- .../java/io/sentry/android/core/TombstoneIntegrationTest.kt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AnrV2IntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AnrV2IntegrationTest.kt index cd21f92fd28..e41d5778a7f 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/AnrV2IntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/AnrV2IntegrationTest.kt @@ -121,7 +121,7 @@ class AnrV2IntegrationTest : ApplicationExitIntegrationTestBase() { } shadowActivityManager.addApplicationExitInfo(exitInfo) }, - flushLogPrefix = "Timed out waiting to flush ANR event to disk.", + flushLogPrefix = "Timed out waiting to flush %s event to disk.", ) override fun assertEnrichedEvent(event: SentryEvent) { diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt index 3fd6140f41c..7db354ea64c 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt @@ -172,7 +172,7 @@ abstract class ApplicationExitIntegrationTestBase { verify(fixture.scopes).captureEvent(any(), anyOrNull()) verify(fixture.logger, never()) - .log(any(), argThat { startsWith(config.flushLogPrefix) }, any()) + .log(any(), argThat { startsWith(config.flushLogPrefix) }, anyVararg()) } @Test @@ -185,7 +185,7 @@ abstract class ApplicationExitIntegrationTestBase { verify(fixture.scopes).captureEvent(any(), anyOrNull()) verify(fixture.logger, never()) - .log(any(), argThat { startsWith(config.flushLogPrefix) }, any()) + .log(any(), argThat { startsWith(config.flushLogPrefix) }, anyVararg()) } @Test diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/TombstoneIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/TombstoneIntegrationTest.kt index bc05f3b23fd..39a63148a17 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/TombstoneIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/TombstoneIntegrationTest.kt @@ -65,7 +65,7 @@ class TombstoneIntegrationTest : ApplicationExitIntegrationTestBase Date: Thu, 15 Oct 2026 13:55:28 +0200 Subject: [PATCH 21/22] chore(core): Reword the JDK 21 suppression comments --- sentry/src/main/java/io/sentry/Baggage.java | 6 +++--- sentry/src/main/java/io/sentry/Breadcrumb.java | 4 ++-- sentry/src/main/java/io/sentry/DiagnosticLogger.java | 2 +- sentry/src/main/java/io/sentry/MonitorContexts.java | 2 +- sentry/src/main/java/io/sentry/ReplayRecording.java | 2 +- sentry/src/main/java/io/sentry/SentryOptions.java | 2 +- sentry/src/main/java/io/sentry/SentryThreadFactory.java | 2 +- sentry/src/main/java/io/sentry/SpanContext.java | 2 +- sentry/src/main/java/io/sentry/SynchronizedCollection.java | 4 ++-- .../java/io/sentry/UncaughtExceptionHandlerIntegration.java | 2 +- .../main/java/io/sentry/cache/PersistingScopeObserver.java | 2 +- .../io/sentry/exception/ExceptionMechanismException.java | 4 ++-- sentry/src/main/java/io/sentry/protocol/Contexts.java | 4 ++-- sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java | 4 ++-- .../java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java | 4 ++-- .../main/java/io/sentry/rrweb/RRWebInteractionEvent.java | 4 ++-- sentry/src/main/java/io/sentry/time/Deadline.java | 2 +- sentry/src/main/java/io/sentry/util/HttpUtils.java | 2 +- sentry/src/main/java/io/sentry/util/InitUtil.java | 2 +- sentry/src/main/java/io/sentry/util/Objects.java | 2 +- .../main/java/io/sentry/util/network/NetworkBodyParser.java | 4 ++-- .../main/java/io/sentry/vendor/gson/stream/JsonReader.java | 2 +- 22 files changed, 32 insertions(+), 32 deletions(-) diff --git a/sentry/src/main/java/io/sentry/Baggage.java b/sentry/src/main/java/io/sentry/Baggage.java index 980b6cf8061..a4ef2c9e859 100644 --- a/sentry/src/main/java/io/sentry/Baggage.java +++ b/sentry/src/main/java/io/sentry/Baggage.java @@ -257,7 +257,7 @@ public String getThirdPartyHeader() { return thirdPartyHeader; } - // TODO Fix for JDK21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, + // temp fix for JDK 21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, // which crashes on Android // < 24. @SuppressWarnings("JdkObsolete") @@ -329,13 +329,13 @@ public String getThirdPartyHeader() { return sb.toString(); } - // TODO Fix for JDK21: The Charset overload requires Java 10. + // temp fix for JDK 21: The Charset overload requires Java 10. @SuppressWarnings("JdkObsolete") private String encode(final @NotNull String value) throws UnsupportedEncodingException { return URLEncoder.encode(value, CHARSET).replaceAll("\\+", "%20"); } - // TODO Fix for JDK21: The Charset overload requires Java 10. + // temp fix for JDK 21: The Charset overload requires Java 10. @SuppressWarnings("JdkObsolete") private static String decode(final @NotNull String value) throws UnsupportedEncodingException { return URLDecoder.decode(value, CHARSET); diff --git a/sentry/src/main/java/io/sentry/Breadcrumb.java b/sentry/src/main/java/io/sentry/Breadcrumb.java index 040652eb791..24ac5561d10 100644 --- a/sentry/src/main/java/io/sentry/Breadcrumb.java +++ b/sentry/src/main/java/io/sentry/Breadcrumb.java @@ -630,7 +630,7 @@ public void setType(@Nullable String type) { this.type = type; } - // TODO Fix for JDK21: EMPTY_DATA is a sentinel, so identity comparison is intended. + // temp fix for JDK 21: EMPTY_DATA is a sentinel, so identity comparison is intended. @SuppressWarnings("ReferenceEquality") private @NotNull Map getOrCreateData() { Map currentData = data; @@ -693,7 +693,7 @@ public void setData(@Nullable String key, @Nullable Object value) { * * @param key the key */ - // TODO Fix for JDK21: EMPTY_DATA is a sentinel, so identity comparison is intended. + // temp fix for JDK 21: EMPTY_DATA is a sentinel, so identity comparison is intended. @SuppressWarnings("ReferenceEquality") public void removeData(@Nullable String key) { if (key == null) { diff --git a/sentry/src/main/java/io/sentry/DiagnosticLogger.java b/sentry/src/main/java/io/sentry/DiagnosticLogger.java index 83cd0e56e69..1f067cd6f1b 100644 --- a/sentry/src/main/java/io/sentry/DiagnosticLogger.java +++ b/sentry/src/main/java/io/sentry/DiagnosticLogger.java @@ -29,7 +29,7 @@ public DiagnosticLogger(final @NotNull SentryOptions options, final @Nullable IL * @param level The SentryLevel to test against. * @return True if a log message would be recorded for the level. Otherwise false. */ - // TODO Fix for JDK21: SentryLevel is declared in ascending severity order. + // temp fix for JDK 21: SentryLevel is declared in ascending severity order. @SuppressWarnings("EnumOrdinal") @Override public boolean isEnabled(final @Nullable SentryLevel level) { diff --git a/sentry/src/main/java/io/sentry/MonitorContexts.java b/sentry/src/main/java/io/sentry/MonitorContexts.java index 2883a2d6134..73db50ea4ca 100644 --- a/sentry/src/main/java/io/sentry/MonitorContexts.java +++ b/sentry/src/main/java/io/sentry/MonitorContexts.java @@ -43,7 +43,7 @@ public void setTrace(final @NotNull SpanContext traceContext) { // region json - // TODO Fix for JDK21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, + // temp fix for JDK 21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, // which crashes on Android // < 24. @SuppressWarnings("JdkObsolete") diff --git a/sentry/src/main/java/io/sentry/ReplayRecording.java b/sentry/src/main/java/io/sentry/ReplayRecording.java index f5aee98e71b..0688ce38f0a 100644 --- a/sentry/src/main/java/io/sentry/ReplayRecording.java +++ b/sentry/src/main/java/io/sentry/ReplayRecording.java @@ -102,7 +102,7 @@ public void setUnknown(@Nullable Map unknown) { public static final class Deserializer implements JsonDeserializer { - // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + // temp fix for JDK 21: The rrweb protocol encodes these enums by ordinal. @SuppressWarnings({"unchecked", "EnumOrdinal"}) @Override public @NotNull ReplayRecording deserialize( diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index 6c15a89bd3a..e3dbc6b22b7 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -58,7 +58,7 @@ import org.jetbrains.annotations.TestOnly; /** Sentry SDK options */ -// TODO Fix for JDK21: Constructors call overridable methods; making them final would break the +// temp fix for JDK 21: Constructors call overridable methods; making them final would break the // public API. @SuppressWarnings("this-escape") @Open diff --git a/sentry/src/main/java/io/sentry/SentryThreadFactory.java b/sentry/src/main/java/io/sentry/SentryThreadFactory.java index e5123f24910..552ab1ed5c7 100644 --- a/sentry/src/main/java/io/sentry/SentryThreadFactory.java +++ b/sentry/src/main/java/io/sentry/SentryThreadFactory.java @@ -78,7 +78,7 @@ List getCurrentThreads( * crashed. This is the case for e.g. watchdog threads which are not the one erroring. * @return a list of SentryThread or null if none */ - // TODO Fix for JDK21: Identifies the current thread by identity. + // temp fix for JDK 21: Identifies the current thread by identity. @SuppressWarnings("ReferenceEquality") @TestOnly @Nullable diff --git a/sentry/src/main/java/io/sentry/SpanContext.java b/sentry/src/main/java/io/sentry/SpanContext.java index 890eea026fe..ebbeb56cd6e 100644 --- a/sentry/src/main/java/io/sentry/SpanContext.java +++ b/sentry/src/main/java/io/sentry/SpanContext.java @@ -16,7 +16,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -// TODO Fix for JDK21: Constructors call overridable methods; making them final would break the +// temp fix for JDK 21: Constructors call overridable methods; making them final would break the // public API. @SuppressWarnings("this-escape") @Open diff --git a/sentry/src/main/java/io/sentry/SynchronizedCollection.java b/sentry/src/main/java/io/sentry/SynchronizedCollection.java index 9d34b255c45..6e8e6b76c6c 100644 --- a/sentry/src/main/java/io/sentry/SynchronizedCollection.java +++ b/sentry/src/main/java/io/sentry/SynchronizedCollection.java @@ -50,13 +50,13 @@ class SynchronizedCollection implements Collection, Serializable { private static final long serialVersionUID = 2412805092710877986L; /** The collection to decorate */ - // TODO Fix for JDK21: Serializable only if the decorated collection is, as in Apache Commons + // temp fix for JDK 21: Serializable only if the decorated collection is, as in Apache Commons // Collections. @SuppressWarnings("serial") private final Collection collection; /** The object to lock on, needed for List/SortedSet views */ - // TODO Fix for JDK21: Not Serializable either; the SDK never serializes these collections. + // temp fix for JDK 21: Not Serializable either; the SDK never serializes these collections. @SuppressWarnings("serial") final AutoClosableReentrantLock lock; diff --git a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java index 3eb0bfabdb9..07e9b6357d7 100644 --- a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java +++ b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java @@ -47,7 +47,7 @@ public UncaughtExceptionHandlerIntegration() { this.threadAdapter = threadAdapter; } - // TODO Fix for JDK21: Both integrations must share the same global scope instance. + // temp fix for JDK 21: Both integrations must share the same global scope instance. @SuppressWarnings("ReferenceEquality") @Override public final void register(final @NotNull IScopes scopes, final @NotNull SentryOptions options) { diff --git a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java index c469d005773..8ebf494dc99 100644 --- a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java +++ b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java @@ -265,7 +265,7 @@ private void flush() { } } - // TODO Fix for JDK21: DELETE_MARKER and CLEAR_MARKER are sentinels, so identity comparison is + // temp fix for JDK 21: DELETE_MARKER and CLEAR_MARKER are sentinels, so identity comparison is // intended. @SuppressWarnings("ReferenceEquality") private void writePending() { diff --git a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java index 6479ed49671..f3e8cbd4744 100644 --- a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java +++ b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java @@ -14,13 +14,13 @@ public final class ExceptionMechanismException extends RuntimeException { private static final long serialVersionUID = 142345454265713915L; - // TODO Fix for JDK21: Never serialized. + // temp fix for JDK 21: Never serialized. @SuppressWarnings("serial") private final @NotNull Mechanism exceptionMechanism; private final @NotNull Throwable throwable; - // TODO Fix for JDK21: Never serialized. + // temp fix for JDK 21: Never serialized. @SuppressWarnings("serial") private final @Nullable Thread thread; diff --git a/sentry/src/main/java/io/sentry/protocol/Contexts.java b/sentry/src/main/java/io/sentry/protocol/Contexts.java index 6f7e793b566..0ca6d77ec8d 100644 --- a/sentry/src/main/java/io/sentry/protocol/Contexts.java +++ b/sentry/src/main/java/io/sentry/protocol/Contexts.java @@ -36,7 +36,7 @@ public class Contexts implements JsonSerializable { public Contexts() {} - // TODO Fix for JDK21: Constructors call overridable methods; making them final would break the + // temp fix for JDK 21: Constructors call overridable methods; making them final would break the // public API. @SuppressWarnings("this-escape") public Contexts(final @NotNull Contexts contexts) { @@ -255,7 +255,7 @@ public void clear() { internalStorage.clear(); } - // TODO Fix for JDK21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, + // temp fix for JDK 21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView, // which crashes on Android // < 24. @SuppressWarnings("JdkObsolete") diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java b/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java index b243f29ae6d..9532998df28 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebEventType.java @@ -17,7 +17,7 @@ public enum RRWebEventType implements JsonSerializable { Custom, Plugin; - // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + // temp fix for JDK 21: The rrweb protocol encodes these enums by ordinal. @SuppressWarnings("EnumOrdinal") @Override public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger) @@ -26,7 +26,7 @@ public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger } public static final class Deserializer implements JsonDeserializer { - // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + // temp fix for JDK 21: The rrweb protocol encodes these enums by ordinal. @SuppressWarnings("EnumOrdinal") @Override public @NotNull RRWebEventType deserialize( diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java b/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java index d8efdfb9148..9c224bbbdd1 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebIncrementalSnapshotEvent.java @@ -30,7 +30,7 @@ public enum IncrementalSource implements JsonSerializable { AdoptedStyleSheet, CustomElement; - // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + // temp fix for JDK 21: The rrweb protocol encodes these enums by ordinal. @SuppressWarnings("EnumOrdinal") @Override public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) @@ -39,7 +39,7 @@ public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) } public static final class Deserializer implements JsonDeserializer { - // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + // temp fix for JDK 21: The rrweb protocol encodes these enums by ordinal. @SuppressWarnings("EnumOrdinal") @Override public @NotNull IncrementalSource deserialize( diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java b/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java index e3e8028010f..21d5be90ab3 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebInteractionEvent.java @@ -30,7 +30,7 @@ public enum InteractionType implements JsonSerializable { TouchEnd, TouchCancel; - // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + // temp fix for JDK 21: The rrweb protocol encodes these enums by ordinal. @SuppressWarnings("EnumOrdinal") @Override public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) @@ -39,7 +39,7 @@ public void serialize(@NotNull ObjectWriter writer, @NotNull ILogger logger) } public static final class Deserializer implements JsonDeserializer { - // TODO Fix for JDK21: The rrweb protocol encodes these enums by ordinal. + // temp fix for JDK 21: The rrweb protocol encodes these enums by ordinal. @SuppressWarnings("EnumOrdinal") @Override public @NotNull InteractionType deserialize( diff --git a/sentry/src/main/java/io/sentry/time/Deadline.java b/sentry/src/main/java/io/sentry/time/Deadline.java index a4f7d0f5416..68f65ba5f69 100644 --- a/sentry/src/main/java/io/sentry/time/Deadline.java +++ b/sentry/src/main/java/io/sentry/time/Deadline.java @@ -79,7 +79,7 @@ public long remaining(final @NotNull TimeUnit unit) { * @throws IllegalArgumentException if the two were created from different tickers, whose origins * are unrelated and whose ticks are therefore not comparable. */ - // TODO Fix for JDK21: Deadlines are only comparable when they share the same ticker instance. + // temp fix for JDK 21: Deadlines are only comparable when they share the same ticker instance. @SuppressWarnings("ReferenceEquality") public boolean isAfter(final @NotNull Deadline other) { if (ticker != other.ticker) { diff --git a/sentry/src/main/java/io/sentry/util/HttpUtils.java b/sentry/src/main/java/io/sentry/util/HttpUtils.java index bae17006d44..73da7808056 100644 --- a/sentry/src/main/java/io/sentry/util/HttpUtils.java +++ b/sentry/src/main/java/io/sentry/util/HttpUtils.java @@ -125,7 +125,7 @@ public static boolean containsSensitiveHeader(final @NotNull String header) { return filteredHeaders; } - // TODO Fix for JDK21: The Charset overload requires Java 10. + // temp fix for JDK 21: The Charset overload requires Java 10. @SuppressWarnings("JdkObsolete") private static @NotNull String decodeQueryParamName(final @NotNull String name) { try { diff --git a/sentry/src/main/java/io/sentry/util/InitUtil.java b/sentry/src/main/java/io/sentry/util/InitUtil.java index b45e68c6808..6c1787474fa 100644 --- a/sentry/src/main/java/io/sentry/util/InitUtil.java +++ b/sentry/src/main/java/io/sentry/util/InitUtil.java @@ -16,7 +16,7 @@ @ApiStatus.Internal public final class InitUtil { - // TODO Fix for JDK21: InitPriority is declared in ascending priority order. + // temp fix for JDK 21: InitPriority is declared in ascending priority order. @SuppressWarnings("EnumOrdinal") public static boolean shouldInit( final @Nullable SentryOptions previousOptions, diff --git a/sentry/src/main/java/io/sentry/util/Objects.java b/sentry/src/main/java/io/sentry/util/Objects.java index 3a3885ec105..340d31c3857 100644 --- a/sentry/src/main/java/io/sentry/util/Objects.java +++ b/sentry/src/main/java/io/sentry/util/Objects.java @@ -14,7 +14,7 @@ public static T requireNonNull(final @Nullable T obj, final @NotNull String return obj; } - // TODO Fix for JDK21: Identity short-circuit, same as java.util.Objects.equals (Java 7+). + // temp fix for JDK 21: Identity short-circuit, same as java.util.Objects.equals (Java 7+). @SuppressWarnings("ReferenceEquality") public static boolean equals(@Nullable Object a, @Nullable Object b) { return (a == b) || (a != null && a.equals(b)); diff --git a/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java b/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java index 0cdcad833f8..a7195c0462d 100644 --- a/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java +++ b/sentry/src/main/java/io/sentry/util/network/NetworkBodyParser.java @@ -34,7 +34,7 @@ private NetworkBodyParser() {} * @param logger Optional logger * @return A NetworkBody or null if bytes are null/empty */ - // TODO Fix for JDK21: The charset is a name from the Content-Type header; unsupported names are + // temp fix for JDK 21: The charset is a name from the Content-Type header; unsupported names are // handled below. @SuppressWarnings("JdkObsolete") public static @Nullable NetworkBody fromBytes( @@ -134,7 +134,7 @@ private static NetworkBody parseJson( } /** Parses URL-encoded form data into a JsonObject NetworkBody. */ - // TODO Fix for JDK21: The Charset overload requires Java 10. + // temp fix for JDK 21: The Charset overload requires Java 10. @SuppressWarnings("JdkObsolete") @NotNull private static NetworkBody parseFormUrlEncoded( diff --git a/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java b/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java index bf94c6c31d6..e09b768bf24 100644 --- a/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java +++ b/sentry/src/main/java/io/sentry/vendor/gson/stream/JsonReader.java @@ -1502,7 +1502,7 @@ public String getPath() { * @throws NumberFormatException if any unicode escape sequences are * malformed. */ - // TODO Fix for JDK21: Vendored from Gson, kept identical to upstream. + // temp fix for JDK 21: Vendored from Gson, kept identical to upstream. @SuppressWarnings("lossy-conversions") private char readEscapeCharacter() throws IOException { if (pos == limit && !fillBuffer(1)) { From 38288e8f7fbb42c97618c59817f8cb581e116d97 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Fri, 16 Oct 2026 09:06:02 +0200 Subject: [PATCH 22/22] build: Keep only the javac unit test targets inside afterEvaluate --- build-logic/build.gradle.kts | 1 - .../io/sentry/gradle/SentryCompilationPlugin.kt | 14 ++++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 25702008619..baf7ea7be89 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -4,7 +4,6 @@ plugins { repositories { gradlePluginPortal() - // AGP is only published to Google's repository. google() } diff --git a/build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt b/build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt index a608110cb98..11c8e47ac94 100644 --- a/build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt +++ b/build-logic/src/main/kotlin/io/sentry/gradle/SentryCompilationPlugin.kt @@ -70,17 +70,19 @@ class SentryCompilationPlugin : Plugin { .toInt() private fun Project.targetBuildJdkForUnitTests() { - // AGP assigns these task properties when it creates the compile tasks, as they can be - // variant aware, so right now there's no way around using afterEvaluate + val unitTestTask = { task: Task -> task.name.contains("UnitTest") } + // jvmTarget is a Property, so this set wins over the AGP convention whenever it runs. + tasks.withType(KotlinJvmCompile::class.java).matching(unitTestTask).configureEach { + compilerOptions.jvmTarget.set(JvmTarget.fromTarget(BUILD_JDK.toString())) + } + // source/targetCompatibility are plain fields, so the last write wins, and AGP writes its + // compileOptions while it creates the compile tasks. Registering earlier - at apply time or + // in onVariants - is silently overwritten, so right now there's no way around afterEvaluate. afterEvaluate { - val unitTestTask = { task: Task -> task.name.contains("UnitTest") } tasks.withType(JavaCompile::class.java).matching(unitTestTask).configureEach { sourceCompatibility = BUILD_JDK.toString() targetCompatibility = BUILD_JDK.toString() } - tasks.withType(KotlinJvmCompile::class.java).matching(unitTestTask).configureEach { - compilerOptions.jvmTarget.set(JvmTarget.fromTarget(BUILD_JDK.toString())) - } } } }