Merge pull request #448 from DataDog/ark/parallel-dd-loader

Register Datadog classloader as parallel capable
This commit is contained in:
Andrew Kent 2018-08-20 16:46:30 -07:00 committed by GitHub
commit 962af76bb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 0 deletions

View File

@ -5,6 +5,10 @@ import java.net.URLClassLoader;
/** Classloader used to run the core datadog agent. */
public class DatadogClassLoader extends URLClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
// Calling java.lang.instrument.Instrumentation#appendToBootstrapClassLoaderSearch
// adds a jar to the bootstrap class lookup, but not to the resource lookup.
// As a workaround, we keep a reference to the bootstrap jar
@ -45,6 +49,10 @@ public class DatadogClassLoader extends URLClassLoader {
* <p>This class is thread safe.
*/
public static final class BootstrapClassLoaderProxy extends URLClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
public BootstrapClassLoaderProxy(URL[] urls, ClassLoader parent) {
super(urls, parent);
}

View File

@ -0,0 +1,49 @@
package datadog.trace.bootstrap
import spock.lang.Specification
import spock.lang.Timeout
import java.util.concurrent.Phaser
import java.util.concurrent.TimeUnit
class DatadogClassLoaderTest extends Specification {
@Timeout(value = 60, unit = TimeUnit.SECONDS)
def "DD classloader does not lock classloading around instance" () {
setup:
def className1 = 'some/class/Name1'
def className2 = 'some/class/Name2'
final URL loc = getClass().getProtectionDomain().getCodeSource().getLocation()
final DatadogClassLoader ddLoader = new DatadogClassLoader(loc, loc, (ClassLoader) null)
final Phaser threadHoldLockPhase = new Phaser(2)
final Phaser acquireLockFromMainThreadPhase = new Phaser(2)
when:
final Thread thread1 = new Thread() {
@Override
void run() {
synchronized (ddLoader.getClassLoadingLock(className1)) {
threadHoldLockPhase.arrive()
acquireLockFromMainThreadPhase.arriveAndAwaitAdvance()
}
}
}
thread1.start()
final Thread thread2 = new Thread() {
@Override
void run() {
threadHoldLockPhase.arriveAndAwaitAdvance()
synchronized (ddLoader.getClassLoadingLock(className2)) {
acquireLockFromMainThreadPhase.arrive()
}
}
}
thread2.start()
thread1.join()
thread2.join()
boolean applicationDidNotDeadlock = true
then:
applicationDidNotDeadlock
}
}