HHH-12427 Prevent classloader leak in ByteBuddy based BasicProxyFactoryImpl

This commit is contained in:
Sanne Grinovero 2018-03-23 15:33:36 +00:00
parent 511a5a3618
commit e7bd213c9e
1 changed files with 13 additions and 27 deletions

View File

@ -9,8 +9,6 @@ package org.hibernate.bytecode.internal.bytebuddy;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -28,8 +26,6 @@ import net.bytebuddy.matcher.ElementMatchers;
public class BasicProxyFactoryImpl implements BasicProxyFactory { public class BasicProxyFactoryImpl implements BasicProxyFactory {
private static final ConcurrentMap<Set<Class>, Class> CACHE = new ConcurrentHashMap<Set<Class>, Class>();
private static final Class[] NO_INTERFACES = new Class[0]; private static final Class[] NO_INTERFACES = new Class[0];
private final Class proxyClass; private final Class proxyClass;
@ -47,29 +43,19 @@ public class BasicProxyFactoryImpl implements BasicProxyFactory {
key.addAll( Arrays.asList( interfaces ) ); key.addAll( Arrays.asList( interfaces ) );
} }
Class proxyClass = CACHE.get( key ); this.proxyClass = new ByteBuddy()
.with( TypeValidation.DISABLED )
if ( proxyClass == null ) { .with( new AuxiliaryType.NamingStrategy.SuffixingRandom( "HibernateBasicProxy" ) )
proxyClass = new ByteBuddy() .subclass( superClass == null ? Object.class : superClass )
.with( TypeValidation.DISABLED ) .implement( interfaces == null ? NO_INTERFACES : interfaces )
.with( new AuxiliaryType.NamingStrategy.SuffixingRandom( "HibernateBasicProxy" ) ) .defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE )
.subclass( superClass == null ? Object.class : superClass ) .method( ElementMatchers.isVirtual().and( ElementMatchers.not( ElementMatchers.isFinalizer() ) ) )
.implement( interfaces == null ? NO_INTERFACES : interfaces ) .intercept( MethodDelegation.toField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME ) )
.defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE ) .implement( ProxyConfiguration.class )
.method( ElementMatchers.isVirtual().and( ElementMatchers.not( ElementMatchers.isFinalizer() ) ) ) .intercept( FieldAccessor.ofField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME ).withAssigner( Assigner.DEFAULT, Assigner.Typing.DYNAMIC ) )
.intercept( MethodDelegation.toField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME ) ) .make()
.implement( ProxyConfiguration.class ) .load( BasicProxyFactory.class.getClassLoader() )
.intercept( FieldAccessor.ofField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME ).withAssigner( Assigner.DEFAULT, Assigner.Typing.DYNAMIC ) ) .getLoaded();
.make()
.load( BasicProxyFactory.class.getClassLoader() )
.getLoaded();
Class previousProxy = CACHE.putIfAbsent( key, proxyClass );
if ( previousProxy != null ) {
proxyClass = previousProxy;
}
}
this.proxyClass = proxyClass;
} }
public Object getProxy() { public Object getProxy() {