Skip to content

Commit

Permalink
Fix possible deadlock (#5585)
Browse files Browse the repository at this point in the history
* Fix possible deadlock

* don't break java 8

* try @laurit's idea

* Update javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/AgentClassLoader.java

Co-authored-by: Lauri Tulmin <tulmin@gmail.com>

Co-authored-by: Lauri Tulmin <tulmin@gmail.com>
  • Loading branch information
trask and laurit authored Mar 17, 2022
1 parent 6497794 commit 531f18f
Showing 1 changed file with 41 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,34 +117,11 @@ public AgentClassLoader(File javaagentFile, String internalJarFileName) {

private static ClassLoader getParentClassLoader() {
if (JAVA_VERSION > 8) {
ClassLoader platformClassLoader = getPlatformLoader();
return new ClassLoader(null) {
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// prometheus exporter uses jdk http server, load it from the platform class loader
if (name != null && name.startsWith("com.sun.net.httpserver.")) {
return platformClassLoader.loadClass(name);
}
return super.loadClass(name, resolve);
}
};
return new JdkHttpServerClassLoader();
}
return null;
}

private static ClassLoader getPlatformLoader() {
/*
Must invoke ClassLoader.getPlatformClassLoader by reflection to remain
compatible with java 8.
*/
try {
Method method = ClassLoader.class.getDeclaredMethod("getPlatformClassLoader");
return (ClassLoader) method.invoke(null);
} catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException exception) {
throw new IllegalStateException(exception);
}
}

private static int getJavaVersion() {
String javaSpecVersion = System.getProperty("java.specification.version");
if ("1.8".equals(javaSpecVersion)) {
Expand Down Expand Up @@ -451,4 +428,44 @@ public long getContentLengthLong() {
return -1;
}
}

private static class JdkHttpServerClassLoader extends ClassLoader {

static {
// this class loader doesn't load any classes, so this is technically unnecessary,
// but included for safety, just in case we every change Class.forName() below back to
// super.loadClass()
registerAsParallelCapable();
}

private final ClassLoader platformClassLoader = getPlatformLoader();

public JdkHttpServerClassLoader() {
super(null);
}

@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// prometheus exporter uses jdk http server, load it from the platform class loader
if (name != null && name.startsWith("com.sun.net.httpserver.")) {
return platformClassLoader.loadClass(name);
}
return Class.forName(name, false, null);
}

private static ClassLoader getPlatformLoader() {
/*
Must invoke ClassLoader.getPlatformClassLoader by reflection to remain
compatible with java 8.
*/
try {
Method method = ClassLoader.class.getDeclaredMethod("getPlatformClassLoader");
return (ClassLoader) method.invoke(null);
} catch (InvocationTargetException
| NoSuchMethodException
| IllegalAccessException exception) {
throw new IllegalStateException(exception);
}
}
}
}

0 comments on commit 531f18f

Please sign in to comment.