Skip to content

Commit

Permalink
Potential workaround for concurrent enhancement race conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
Sanne committed May 17, 2024
1 parent 2166451 commit 1f41079
Showing 1 changed file with 38 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import io.quarkus.hibernate.orm.deployment.integration.QuarkusClassFileLocator;
import io.quarkus.hibernate.orm.deployment.integration.QuarkusEnhancementContext;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.pool.TypePool;

/**
* Used to transform bytecode by registering to
Expand Down Expand Up @@ -94,21 +96,50 @@ private static class EnhancerHolder {
private volatile Enhancer actualEnhancer;

public Enhancer getEnhancer() {
//Lazily initialized for multiple reasons:
//1)it's expensive: try to skip it if we can; this is actually not unlikely to happen as the transformation is cacheable.
//2)We want the Advice loaders of the Hibernate ORM implementation to be initialized within the scope in which we
//have the transformation classloader installed in the thread's context.
//Lazily initialized as it's expensive and might not be necessary: these transformations are cacheable.
if (actualEnhancer == null) {
synchronized (this) {
if (actualEnhancer == null) {
EnhancerClassLocator modelPool = ModelTypePool.buildModelTypePool(QuarkusClassFileLocator.INSTANCE,
CORE_POOL);
actualEnhancer = PROVIDER.getEnhancer(QuarkusEnhancementContext.INSTANCE, modelPool);
actualEnhancer = PROVIDER.getEnhancer(QuarkusEnhancementContext.INSTANCE, new ThreadsafeLocator());
}
}
}
return actualEnhancer;
}
}

private static final class ThreadsafeLocator implements EnhancerClassLocator {

final CacheProvider sharedCache = TypePool.CacheProvider.Simple.withObjectType();

final ThreadLocal<EnhancerClassLocator> localLocator = ThreadLocal
.withInitial(() -> ModelTypePool.buildModelTypePool(QuarkusClassFileLocator.INSTANCE,
CORE_POOL, sharedCache));

@Override
public void registerClassNameAndBytes(String s, byte[] bytes) {
localLocator.get().registerClassNameAndBytes(s, bytes);
}

@Override
public void deregisterClassNameAndBytes(String s) {
localLocator.get().deregisterClassNameAndBytes(s);
}

@Override
public ClassFileLocator asClassFileLocator() {
return localLocator.get().asClassFileLocator();
}

@Override
public Resolution describe(String s) {
return localLocator.get().describe(s);
}

@Override
public void clear() {
//not useful
}
}

}

0 comments on commit 1f41079

Please sign in to comment.