diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SafeServiceLoader.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SafeServiceLoader.java index 3d56248387da..4d48918cb704 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SafeServiceLoader.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SafeServiceLoader.java @@ -32,12 +32,11 @@ public final class SafeServiceLoader { @SuppressWarnings("ForEachIterable") public static List load(Class serviceClass) { List result = new ArrayList<>(); - java.util.ServiceLoader services = ServiceLoader.load(serviceClass); - for (Iterator iter = services.iterator(); iter.hasNext(); ) { - try { - result.add(iter.next()); - } catch (UnsupportedClassVersionError e) { - logger.log(FINE, "Unable to load instrumentation class: {0}", e.getMessage()); + ServiceLoader services = ServiceLoader.load(serviceClass); + for (Iterator iterator = new SafeIterator<>(services.iterator()); iterator.hasNext(); ) { + T service = iterator.next(); + if (service != null) { + result.add(service); } } return result; @@ -54,4 +53,43 @@ public static List loadOrdered(Class serviceClass) { } private SafeServiceLoader() {} + + private static class SafeIterator implements Iterator { + private final Iterator delegate; + + SafeIterator(Iterator iterator) { + delegate = iterator; + } + + private static void handleUnsupportedClassVersionError( + UnsupportedClassVersionError unsupportedClassVersionError) { + logger.log( + FINE, + "Unable to load instrumentation class: {0}", + unsupportedClassVersionError.getMessage()); + } + + @Override + public boolean hasNext() { + // jdk9 and newer throw UnsupportedClassVersionError in hasNext() + while (true) { + try { + return delegate.hasNext(); + } catch (UnsupportedClassVersionError unsupportedClassVersionError) { + handleUnsupportedClassVersionError(unsupportedClassVersionError); + } + } + } + + @Override + public T next() { + // jdk8 throws UnsupportedClassVersionError in next() + try { + return delegate.next(); + } catch (UnsupportedClassVersionError unsupportedClassVersionError) { + handleUnsupportedClassVersionError(unsupportedClassVersionError); + return null; + } + } + } }