Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Fixes

- Disable URL caching when reading `META-INF/MANIFEST.MF` files during version detection so that the SDK no longer keeps jar file handles open for the life of the process ([#6124](https://github.com/getsentry/sentry-java/pull/6124)

## 8.57.0

### Behavioral Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import io.sentry.SentryIntegrationPackageStorage;
import io.sentry.util.AutoClosableReentrantLock;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
Expand Down Expand Up @@ -56,48 +58,55 @@ public void readManifestFiles() {
ClassLoader.getSystemClassLoader().getResources("META-INF/MANIFEST.MF");
while (resources.hasMoreElements()) {
try {
final @NotNull Manifest manifest = new Manifest(resources.nextElement().openStream());

@0xadam-brown 0xadam-brown Sep 16, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard to see what happened b/c the diff realigns the indententation for most of this method. Here's what changed:

Before

final @NotNull Manifest manifest = new Manifest(resources.nextElement().openStream());
...

After

 final @NotNull URLConnection connection = resources.nextElement().openConnection();
     connection.setUseCaches(false);
     try (final @NotNull InputStream inputStream = connection.getInputStream()) {
        ...
     }

Note that simply closing the stream was insufficient to avoid leaking the jars. Verified with my clanker that disabling caches was also needed.

final @Nullable Attributes mainAttributes = manifest.getMainAttributes();
if (mainAttributes != null) {
final @Nullable String name = mainAttributes.getValue("Sentry-Opentelemetry-SDK-Name");
final @Nullable String version = mainAttributes.getValue("Implementation-Version");
final @Nullable String sdkName = mainAttributes.getValue("Sentry-SDK-Name");
final @Nullable String packageName = mainAttributes.getValue("Sentry-SDK-Package-Name");
final @NotNull URLConnection connection = resources.nextElement().openConnection();
connection.setUseCaches(false);
try (final @NotNull InputStream inputStream = connection.getInputStream()) {
final @NotNull Manifest manifest = new Manifest(inputStream);
final @Nullable Attributes mainAttributes = manifest.getMainAttributes();
if (mainAttributes != null) {
final @Nullable String name =
mainAttributes.getValue("Sentry-Opentelemetry-SDK-Name");
final @Nullable String version = mainAttributes.getValue("Implementation-Version");
final @Nullable String sdkName = mainAttributes.getValue("Sentry-SDK-Name");
final @Nullable String packageName =
mainAttributes.getValue("Sentry-SDK-Package-Name");

if (name != null && version != null) {
versionInfo.sdkName = name;
versionInfo.sdkVersion = version;
final @Nullable String otelVersion =
mainAttributes.getValue("Sentry-Opentelemetry-Version-Name");
if (otelVersion != null) {
SentryIntegrationPackageStorage.getInstance()
.addPackage("maven:io.opentelemetry:opentelemetry-sdk", otelVersion);
SentryIntegrationPackageStorage.getInstance().addIntegration("OpenTelemetry");
if (name != null && version != null) {
versionInfo.sdkName = name;
versionInfo.sdkVersion = version;
final @Nullable String otelVersion =
mainAttributes.getValue("Sentry-Opentelemetry-Version-Name");
if (otelVersion != null) {
SentryIntegrationPackageStorage.getInstance()
.addPackage("maven:io.opentelemetry:opentelemetry-sdk", otelVersion);
SentryIntegrationPackageStorage.getInstance().addIntegration("OpenTelemetry");
}
final @Nullable String otelJavaagentVersion =
mainAttributes.getValue("Sentry-Opentelemetry-Javaagent-Version-Name");
if (otelJavaagentVersion != null) {
SentryIntegrationPackageStorage.getInstance()
.addPackage(
"maven:io.opentelemetry.javaagent:opentelemetry-javaagent",
otelJavaagentVersion);
SentryIntegrationPackageStorage.getInstance()
.addIntegration("OpenTelemetry-Agent");
}
if (name.equals("sentry.java.opentelemetry.agentless")) {
SentryIntegrationPackageStorage.getInstance()
.addIntegration("OpenTelemetry-Agentless");
}
if (name.equals("sentry.java.opentelemetry.agentless-spring")) {
SentryIntegrationPackageStorage.getInstance()
.addIntegration("OpenTelemetry-Agentless-Spring");
}
}
final @Nullable String otelJavaagentVersion =
mainAttributes.getValue("Sentry-Opentelemetry-Javaagent-Version-Name");
if (otelJavaagentVersion != null) {
SentryIntegrationPackageStorage.getInstance()
.addPackage(
"maven:io.opentelemetry.javaagent:opentelemetry-javaagent",
otelJavaagentVersion);
SentryIntegrationPackageStorage.getInstance().addIntegration("OpenTelemetry-Agent");
}
if (name.equals("sentry.java.opentelemetry.agentless")) {
SentryIntegrationPackageStorage.getInstance()
.addIntegration("OpenTelemetry-Agentless");
}
if (name.equals("sentry.java.opentelemetry.agentless-spring")) {
SentryIntegrationPackageStorage.getInstance()
.addIntegration("OpenTelemetry-Agentless-Spring");
}
}

if (sdkName != null
&& version != null
&& packageName != null
&& sdkName.startsWith("sentry.java")) {
SentryIntegrationPackageStorage.getInstance().addPackage(packageName, version);
if (sdkName != null
&& version != null
&& packageName != null
&& sdkName.startsWith("sentry.java")) {
SentryIntegrationPackageStorage.getInstance().addPackage(packageName, version);
}
}
}
} catch (Exception e) {
Expand Down
Loading