Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle UnsupportedClassVersionError in ServiceLoader on jdk9 #7090

Merged
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@ public final class SafeServiceLoader {
@SuppressWarnings("ForEachIterable")
public static <T> List<T> load(Class<T> serviceClass) {
List<T> result = new ArrayList<>();
java.util.ServiceLoader<T> services = ServiceLoader.load(serviceClass);
for (Iterator<T> 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<T> services = ServiceLoader.load(serviceClass);
for (Iterator<T> iterator = new SafeIterator<>(services.iterator()); iterator.hasNext(); ) {
T service = iterator.next();
if (service != null) {
result.add(service);
}
}
return result;
Expand All @@ -54,4 +53,43 @@ public static <T extends Ordered> List<T> loadOrdered(Class<T> serviceClass) {
}

private SafeServiceLoader() {}

private static class SafeIterator<T> implements Iterator<T> {
private final Iterator<T> delegate;

SafeIterator(Iterator<T> 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()
Copy link
Member

Choose a reason for hiding this comment

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

oh interesting, so we would have run into this problem on Java 11 if we introduced Java 17-only instrumentation

do you know if the underlying iterator will move on item hasNext when it throws exception, so that we will continue iterating over it from that point?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tested it manually and believe that hasNext will move to the next element on exception. Relevant code is in
https://github.com/openjdk/jdk11u/blob/b928a88fd564fab88f00086a62c0695ed5cc9353/src/java.base/share/classes/java/util/ServiceLoader.java#L1181 pending iterator is advanced before Class.forName

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;
}
}
}
}