HHH-15809 Secondary super-type cache pollution mitigations for HibernateBasicProxy
This commit is contained in:
parent
ded4c433ac
commit
8ebf3c8507
|
@ -6,14 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.bytecode.internal.bytebuddy;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.bytecode.spi.BasicProxyFactory;
|
||||
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.proxy.ProxyConfiguration;
|
||||
|
||||
|
@ -44,15 +42,19 @@ public class BasicProxyFactoryImpl implements BasicProxyFactory {
|
|||
final Class<?> superClassOrMainInterface = superClass != null ? superClass : interfaceClass;
|
||||
final TypeCache.SimpleKey cacheKey = new TypeCache.SimpleKey( superClassOrMainInterface );
|
||||
|
||||
this.proxyClass = byteBuddyState.loadBasicProxy( superClassOrMainInterface, cacheKey, byteBuddy -> byteBuddy
|
||||
.with( new NamingStrategy.SuffixingRandom( PROXY_NAMING_SUFFIX, new NamingStrategy.SuffixingRandom.BaseNameResolver.ForFixedValue( superClassOrMainInterface.getName() ) ) )
|
||||
.subclass( superClass == null ? Object.class : superClass, ConstructorStrategy.Default.DEFAULT_CONSTRUCTOR )
|
||||
.implement( interfaceClass == null ? NO_INTERFACES : new Class[]{ interfaceClass } )
|
||||
.defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE )
|
||||
.method( byteBuddyState.getProxyDefinitionHelpers().getVirtualNotFinalizerFilter() )
|
||||
.intercept( byteBuddyState.getProxyDefinitionHelpers().getDelegateToInterceptorDispatcherMethodDelegation() )
|
||||
.implement( ProxyConfiguration.class )
|
||||
.intercept( byteBuddyState.getProxyDefinitionHelpers().getInterceptorFieldAccessor() )
|
||||
ByteBuddyState.ProxyDefinitionHelpers helpers = byteBuddyState.getProxyDefinitionHelpers();
|
||||
|
||||
this.proxyClass = byteBuddyState.loadBasicProxy( superClassOrMainInterface, cacheKey, byteBuddy ->
|
||||
helpers.appendIgnoreAlsoAtEnd( byteBuddy
|
||||
.with( new NamingStrategy.SuffixingRandom( PROXY_NAMING_SUFFIX, new NamingStrategy.SuffixingRandom.BaseNameResolver.ForFixedValue( superClassOrMainInterface.getName() ) ) )
|
||||
.subclass( superClass == null ? Object.class : superClass, ConstructorStrategy.Default.DEFAULT_CONSTRUCTOR )
|
||||
.implement( interfaceClass == null ? NO_INTERFACES : new Class[]{ interfaceClass } )
|
||||
.defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE )
|
||||
.method( byteBuddyState.getProxyDefinitionHelpers().getVirtualNotFinalizerFilter() )
|
||||
.intercept( byteBuddyState.getProxyDefinitionHelpers().getDelegateToInterceptorDispatcherMethodDelegation() )
|
||||
.implement( ProxyConfiguration.class )
|
||||
.intercept( byteBuddyState.getProxyDefinitionHelpers().getInterceptorFieldAccessor() )
|
||||
)
|
||||
);
|
||||
this.interceptor = new PassThroughInterceptor( proxyClass.getName() );
|
||||
try {
|
||||
|
@ -65,29 +67,23 @@ public class BasicProxyFactoryImpl implements BasicProxyFactory {
|
|||
|
||||
@Override
|
||||
public Object getProxy() {
|
||||
final PrimeAmongSecondarySupertypes instance;
|
||||
try {
|
||||
final ProxyConfiguration proxy = (ProxyConfiguration) proxyClassConstructor.newInstance();
|
||||
proxy.$$_hibernate_set_interceptor( this.interceptor );
|
||||
return proxy;
|
||||
instance = (PrimeAmongSecondarySupertypes) proxyClassConstructor.newInstance();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw new HibernateException( "Unable to instantiate proxy instance", t );
|
||||
}
|
||||
final ProxyConfiguration proxyConfiguration = instance.asProxyConfiguration();
|
||||
if ( proxyConfiguration == null ) {
|
||||
throw new HibernateException( "Produced proxy does not correctly implement ProxyConfiguration" );
|
||||
}
|
||||
proxyConfiguration.$$_hibernate_set_interceptor( this.interceptor );
|
||||
return instance;
|
||||
}
|
||||
|
||||
public boolean isInstance(Object object) {
|
||||
return proxyClass.isInstance( object );
|
||||
}
|
||||
|
||||
private TypeCache.SimpleKey getCacheKey(Class<?> superClass, Class<?>[] interfaces) {
|
||||
Set<Class<?>> key = new HashSet<>();
|
||||
if ( superClass != null ) {
|
||||
key.add( superClass );
|
||||
}
|
||||
if ( interfaces != null ) {
|
||||
Collections.addAll( key, interfaces );
|
||||
}
|
||||
|
||||
return new TypeCache.SimpleKey( key );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ public final class ByteBuddyState {
|
|||
for ( Method m : PrimeAmongSecondarySupertypes.class.getMethods() ) {
|
||||
//We need to ignore both the match of each default method on PrimeAmongSecondarySupertypes
|
||||
toFullyIgnore.add( isDeclaredBy( PrimeAmongSecondarySupertypes.class ).and( named( m.getName() ) ).and( takesNoArguments() ) );
|
||||
//And the override in the interface it belong to - which we happen to have in the return type
|
||||
//And the override in the interface it belongs to - which we happen to have in the return type
|
||||
toFullyIgnore.add( isDeclaredBy( m.getReturnType() ).and( named( m.getName() ) ).and( takesNoArguments() ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.engine.spi;
|
|||
|
||||
import org.hibernate.engine.internal.ManagedTypeHelper;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.ProxyConfiguration;
|
||||
|
||||
/**
|
||||
* For a full explanation of the purpose of this interface
|
||||
|
@ -58,4 +59,8 @@ public interface PrimeAmongSecondarySupertypes {
|
|||
return null;
|
||||
}
|
||||
|
||||
default ProxyConfiguration asProxyConfiguration() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ package org.hibernate.proxy;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
|
||||
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.FieldValue;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
|
@ -23,7 +25,7 @@ import net.bytebuddy.implementation.bind.annotation.This;
|
|||
* suppressed by the runtime if they are not available on a class loader. This allows using this interceptor
|
||||
* and configuration with for example OSGi without any export of Byte Buddy when using Hibernate.
|
||||
*/
|
||||
public interface ProxyConfiguration {
|
||||
public interface ProxyConfiguration extends PrimeAmongSecondarySupertypes {
|
||||
|
||||
/**
|
||||
* The canonical field name for an interceptor object stored in a proxied object.
|
||||
|
@ -37,6 +39,11 @@ public interface ProxyConfiguration {
|
|||
*/
|
||||
void $$_hibernate_set_interceptor(Interceptor interceptor);
|
||||
|
||||
@Override
|
||||
default ProxyConfiguration asProxyConfiguration() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An interceptor object that is responsible for invoking a proxy's method.
|
||||
*/
|
||||
|
|
|
@ -89,11 +89,13 @@ public class ByteBuddyProxyFactory implements ProxyFactory, Serializable {
|
|||
overridesEquals
|
||||
);
|
||||
|
||||
final HibernateProxy proxy = getHibernateProxy();
|
||||
( (ProxyConfiguration) proxy ).$$_hibernate_set_interceptor( interceptor );
|
||||
|
||||
return proxy;
|
||||
|
||||
final HibernateProxy instance = getHibernateProxy();
|
||||
final ProxyConfiguration proxyConfiguration = instance.asProxyConfiguration();
|
||||
if ( proxyConfiguration == null ) {
|
||||
throw new HibernateException( "Produced proxy does not correctly implement ProxyConfiguration" );
|
||||
}
|
||||
proxyConfiguration.$$_hibernate_set_interceptor( interceptor );
|
||||
return instance;
|
||||
}
|
||||
|
||||
private HibernateProxy getHibernateProxy() {
|
||||
|
|
|
@ -6,10 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.proxy.pojo.bytebuddy;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.anyOf;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy;
|
||||
import static org.hibernate.internal.CoreLogging.messageLogger;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -23,15 +19,7 @@ import java.util.function.Function;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState;
|
||||
import org.hibernate.engine.spi.CompositeOwner;
|
||||
import org.hibernate.engine.spi.CompositeTracker;
|
||||
import org.hibernate.engine.spi.Managed;
|
||||
import org.hibernate.engine.spi.ManagedComposite;
|
||||
import org.hibernate.engine.spi.ManagedEntity;
|
||||
import org.hibernate.engine.spi.ManagedMappedSuperclass;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
|
||||
import org.hibernate.engine.spi.SelfDirtinessTracker;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
@ -46,7 +34,6 @@ import net.bytebuddy.description.type.TypeDescription;
|
|||
import net.bytebuddy.description.type.TypeList;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
|
||||
import net.bytebuddy.implementation.DefaultMethodCall;
|
||||
import net.bytebuddy.implementation.SuperMethodCall;
|
||||
import net.bytebuddy.pool.TypePool;
|
||||
|
||||
|
@ -129,9 +116,17 @@ public class ByteBuddyProxyHelper implements Serializable {
|
|||
serializableProxy.getPersistentClass(),
|
||||
serializableProxy.getInterfaces()
|
||||
);
|
||||
final HibernateProxy proxy = asHibernateProxy( proxyClass.newInstance() );
|
||||
( (ProxyConfiguration) proxy ).$$_hibernate_set_interceptor( interceptor );
|
||||
return proxy;
|
||||
PrimeAmongSecondarySupertypes instance = (PrimeAmongSecondarySupertypes) proxyClass.getDeclaredConstructor().newInstance();
|
||||
final ProxyConfiguration proxyConfiguration = instance.asProxyConfiguration();
|
||||
if ( proxyConfiguration == null ) {
|
||||
throw new HibernateException( "Produced proxy does not correctly implement ProxyConfiguration" );
|
||||
}
|
||||
proxyConfiguration.$$_hibernate_set_interceptor( interceptor );
|
||||
final HibernateProxy hibernateProxy = instance.asHibernateProxy();
|
||||
if ( hibernateProxy == null ) {
|
||||
throw new HibernateException( "Produced proxy does not correctly implement HibernateProxy" );
|
||||
}
|
||||
return hibernateProxy;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
final String message = LOG.bytecodeEnhancementFailed( serializableProxy.getEntityName() );
|
||||
|
|
Loading…
Reference in New Issue