HHH-18011 Extract reusable constants from EnhancerImpl

This commit is contained in:
Sanne Grinovero 2024-04-27 22:40:03 +01:00 committed by Sanne Grinovero
parent a92bf606a9
commit 85364a2c53
3 changed files with 107 additions and 21 deletions

View File

@ -113,6 +113,7 @@ public class EnhancerImpl implements Enhancer {
private final Advice adviceInitializeLazyAttributeLoadingInterceptor = Advice.to( CodeTemplates.InitializeLazyAttributeLoadingInterceptor.class, adviceLocator ); private final Advice adviceInitializeLazyAttributeLoadingInterceptor = Advice.to( CodeTemplates.InitializeLazyAttributeLoadingInterceptor.class, adviceLocator );
private final Implementation implementationSetOwner = Advice.to( CodeTemplates.SetOwner.class, adviceLocator ).wrap( StubMethod.INSTANCE ); private final Implementation implementationSetOwner = Advice.to( CodeTemplates.SetOwner.class, adviceLocator ).wrap( StubMethod.INSTANCE );
private final Implementation implementationClearOwner = Advice.to( CodeTemplates.ClearOwner.class, adviceLocator ).wrap( StubMethod.INSTANCE ); private final Implementation implementationClearOwner = Advice.to( CodeTemplates.ClearOwner.class, adviceLocator ).wrap( StubMethod.INSTANCE );
private final EnhancerImplConstants constants;
/** /**
* Constructs the Enhancer, using the given context. * Constructs the Enhancer, using the given context.
@ -136,6 +137,7 @@ public class EnhancerImpl implements Enhancer {
this.enhancementContext = new ByteBuddyEnhancementContext( enhancementContext ); this.enhancementContext = new ByteBuddyEnhancementContext( enhancementContext );
this.byteBuddyState = Objects.requireNonNull( byteBuddyState ); this.byteBuddyState = Objects.requireNonNull( byteBuddyState );
this.typePool = Objects.requireNonNull( classLocator ); this.typePool = Objects.requireNonNull( classLocator );
this.constants = byteBuddyState.getEnhancerConstants();
} }
/** /**
@ -262,18 +264,18 @@ public class EnhancerImpl implements Enhancer {
.annotateField( TRANSIENT_ANNOTATION ) .annotateField( TRANSIENT_ANNOTATION )
.defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC )
.withParameters( String.class ) .withParameters( String.class )
.intercept( implementationTrackChange ) .intercept( constants.implementationTrackChange )
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
.intercept( implementationGetDirtyAttributesWithoutCollections ) .intercept( constants.implementationGetDirtyAttributesWithoutCollections )
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
.intercept( implementationAreFieldsDirtyWithoutCollections ) .intercept( constants.implementationAreFieldsDirtyWithoutCollections )
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
.intercept( implementationClearDirtyAttributesWithoutCollections ) .intercept( constants.implementationClearDirtyAttributesWithoutCollections )
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
.withParameters( boolean.class ) .withParameters( boolean.class )
.intercept( implementationSuspendDirtyTracking ) .intercept( constants.implementationSuspendDirtyTracking )
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC )
.intercept( implementationGetCollectionTrackerWithoutCollections ); .intercept( constants.implementationGetCollectionTrackerWithoutCollections );
} }
else { else {
//TODO es.enableInterfaceExtendedSelfDirtinessTracker ? Careful with consequences.. //TODO es.enableInterfaceExtendedSelfDirtinessTracker ? Careful with consequences..
@ -284,16 +286,16 @@ public class EnhancerImpl implements Enhancer {
.annotateField( TRANSIENT_ANNOTATION ) .annotateField( TRANSIENT_ANNOTATION )
.defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC )
.withParameters( String.class ) .withParameters( String.class )
.intercept( implementationTrackChange ) .intercept( constants.implementationTrackChange )
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
.intercept( implementationGetDirtyAttributes ) .intercept( constants.implementationGetDirtyAttributes )
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
.intercept( implementationAreFieldsDirty ) .intercept( constants.implementationAreFieldsDirty )
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
.intercept( implementationClearDirtyAttributes ) .intercept( constants.implementationClearDirtyAttributes )
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
.withParameters( boolean.class ) .withParameters( boolean.class )
.intercept( implementationSuspendDirtyTracking ) .intercept( constants.implementationSuspendDirtyTracking )
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC )
.intercept( FieldAccessor.ofField( EnhancerConstants.TRACKER_COLLECTION_NAME ) ); .intercept( FieldAccessor.ofField( EnhancerConstants.TRACKER_COLLECTION_NAME ) );
@ -318,17 +320,17 @@ public class EnhancerImpl implements Enhancer {
isDirty = Advice.withCustomMapping() isDirty = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName ) .bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, fieldDescription ) .bind( CodeTemplates.FieldValue.class, fieldDescription )
.to( adviceIsDirty, adviceLocator ) .to( adviceIsDirty, constants.adviceLocator )
.wrap( isDirty ); .wrap( isDirty );
getDirtyNames = Advice.withCustomMapping() getDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName ) .bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, fieldDescription ) .bind( CodeTemplates.FieldValue.class, fieldDescription )
.to( adviceGetDirtyNames, adviceLocator ) .to( adviceGetDirtyNames, constants.adviceLocator )
.wrap( getDirtyNames ); .wrap( getDirtyNames );
clearDirtyNames = Advice.withCustomMapping() clearDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName ) .bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, fieldDescription ) .bind( CodeTemplates.FieldValue.class, fieldDescription )
.to( adviceClearDirtyNames, adviceLocator ) .to( adviceClearDirtyNames, constants.adviceLocator )
.wrap( clearDirtyNames ); .wrap( clearDirtyNames );
} }
else { else {
@ -337,23 +339,23 @@ public class EnhancerImpl implements Enhancer {
isDirty = Advice.withCustomMapping() isDirty = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName ) .bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, getterMapping ) .bind( CodeTemplates.FieldValue.class, getterMapping )
.to( adviceIsDirty, adviceLocator ) .to( adviceIsDirty, constants.adviceLocator )
.wrap( isDirty ); .wrap( isDirty );
getDirtyNames = Advice.withCustomMapping() getDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName ) .bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, getterMapping ) .bind( CodeTemplates.FieldValue.class, getterMapping )
.to( adviceGetDirtyNames, adviceLocator ) .to( adviceGetDirtyNames, constants.adviceLocator )
.wrap( getDirtyNames ); .wrap( getDirtyNames );
clearDirtyNames = Advice.withCustomMapping() clearDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName ) .bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, getterMapping ) .bind( CodeTemplates.FieldValue.class, getterMapping )
.to( adviceClearDirtyNames, adviceLocator ) .to( adviceClearDirtyNames, constants.adviceLocator )
.wrap( clearDirtyNames ); .wrap( clearDirtyNames );
} }
} }
if ( enhancementContext.hasLazyLoadableAttributes( managedCtClass ) ) { if ( enhancementContext.hasLazyLoadableAttributes( managedCtClass ) ) {
clearDirtyNames = adviceInitializeLazyAttributeLoadingInterceptor.wrap( clearDirtyNames ); clearDirtyNames = constants.adviceInitializeLazyAttributeLoadingInterceptor.wrap( clearDirtyNames );
} }
builder = builder.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME, boolean.class, Visibility.PUBLIC ) builder = builder.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
@ -363,7 +365,7 @@ public class EnhancerImpl implements Enhancer {
.intercept( getDirtyNames ) .intercept( getDirtyNames )
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME, void.class, Visibility.PUBLIC ) .defineMethod( EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME, void.class, Visibility.PUBLIC )
.intercept( Advice.withCustomMapping() .intercept( Advice.withCustomMapping()
.to( CodeTemplates.ClearDirtyCollectionNames.class, adviceLocator ) .to( CodeTemplates.ClearDirtyCollectionNames.class, constants.adviceLocator )
.wrap( StubMethod.INSTANCE ) ) .wrap( StubMethod.INSTANCE ) )
.defineMethod( ExtendedSelfDirtinessTracker.REMOVE_DIRTY_FIELDS_NAME, void.class, Visibility.PUBLIC ) .defineMethod( ExtendedSelfDirtinessTracker.REMOVE_DIRTY_FIELDS_NAME, void.class, Visibility.PUBLIC )
.withParameters( LazyAttributeLoadingInterceptor.class ) .withParameters( LazyAttributeLoadingInterceptor.class )
@ -395,14 +397,14 @@ public class EnhancerImpl implements Enhancer {
Visibility.PUBLIC Visibility.PUBLIC
) )
.withParameters( String.class, CompositeOwner.class ) .withParameters( String.class, CompositeOwner.class )
.intercept( implementationSetOwner ) .intercept( constants.implementationSetOwner )
.defineMethod( .defineMethod(
EnhancerConstants.TRACKER_COMPOSITE_CLEAR_OWNER, EnhancerConstants.TRACKER_COMPOSITE_CLEAR_OWNER,
void.class, void.class,
Visibility.PUBLIC Visibility.PUBLIC
) )
.withParameters( String.class ) .withParameters( String.class )
.intercept( implementationClearOwner ); .intercept( constants.implementationClearOwner );
} }
return createTransformer( managedCtClass ).applyTo( builder ); return createTransformer( managedCtClass ).applyTo( builder );

View File

@ -0,0 +1,77 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.enhance.internal.bytebuddy;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.StubMethod;
/**
* Extracts constants used by EnhancerImpl.
* This allows integrators to choose reusing this state for multiple enhancement processes,
* as these are fairly expensive to initialize, or rather choose to free memory by
* not retaining this.
*/
public final class EnhancerImplConstants {
final ClassFileLocator adviceLocator;
final Implementation implementationTrackChange;
final Implementation implementationGetDirtyAttributesWithoutCollections;
final Implementation implementationAreFieldsDirtyWithoutCollections;
final Implementation implementationClearDirtyAttributesWithoutCollections;
final Implementation implementationSuspendDirtyTracking;
final Implementation implementationGetDirtyAttributes;
final Implementation implementationAreFieldsDirty;
final Implementation implementationGetCollectionTrackerWithoutCollections;
final Implementation implementationClearDirtyAttributes;
//In this case we just extract the Advice:
final Advice adviceInitializeLazyAttributeLoadingInterceptor;
final Implementation implementationSetOwner;
final Implementation implementationClearOwner;
public EnhancerImplConstants() {
this.adviceLocator = ClassFileLocator.ForClassLoader.of( CodeTemplates.class.getClassLoader() );
this.implementationTrackChange = Advice.to( CodeTemplates.TrackChange.class, adviceLocator )
.wrap( StubMethod.INSTANCE );
this.implementationGetDirtyAttributesWithoutCollections = Advice.to(
CodeTemplates.GetDirtyAttributesWithoutCollections.class,
adviceLocator
).wrap( StubMethod.INSTANCE );
this.implementationAreFieldsDirtyWithoutCollections = Advice.to(
CodeTemplates.AreFieldsDirtyWithoutCollections.class,
adviceLocator
).wrap( StubMethod.INSTANCE );
this.implementationClearDirtyAttributesWithoutCollections = Advice.to(
CodeTemplates.ClearDirtyAttributesWithoutCollections.class,
adviceLocator
).wrap( StubMethod.INSTANCE );
this.implementationSuspendDirtyTracking = Advice.to( CodeTemplates.SuspendDirtyTracking.class, adviceLocator )
.wrap( StubMethod.INSTANCE );
this.implementationGetDirtyAttributes = Advice.to( CodeTemplates.GetDirtyAttributes.class, adviceLocator ).wrap(
StubMethod.INSTANCE );
this.implementationAreFieldsDirty = Advice.to( CodeTemplates.AreFieldsDirty.class, adviceLocator ).wrap(
StubMethod.INSTANCE );
this.implementationGetCollectionTrackerWithoutCollections = Advice.to(
CodeTemplates.GetCollectionTrackerWithoutCollections.class,
adviceLocator
).wrap( StubMethod.INSTANCE );
this.implementationClearDirtyAttributes = Advice.to( CodeTemplates.ClearDirtyAttributes.class, adviceLocator )
.wrap( StubMethod.INSTANCE );
//In this case we just extract the Advice:
this.adviceInitializeLazyAttributeLoadingInterceptor = Advice.to(
CodeTemplates.InitializeLazyAttributeLoadingInterceptor.class,
adviceLocator
);
this.implementationSetOwner = Advice.to( CodeTemplates.SetOwner.class, adviceLocator )
.wrap( StubMethod.INSTANCE );
this.implementationClearOwner = Advice.to( CodeTemplates.ClearOwner.class, adviceLocator )
.wrap( StubMethod.INSTANCE );
}
}

View File

@ -28,6 +28,7 @@ import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImplConstants;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants; import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.bytecode.spi.BasicProxyFactory; import org.hibernate.bytecode.spi.BasicProxyFactory;
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes; import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
@ -72,6 +73,8 @@ public final class ByteBuddyState {
private final ClassRewriter classRewriter; private final ClassRewriter classRewriter;
final EnhancerImplConstants enhancerConstants = new EnhancerImplConstants();
/** /**
* It will be easier to maintain the cache and its state when it will no longer be static * It will be easier to maintain the cache and its state when it will no longer be static
* in Hibernate ORM 6+. * in Hibernate ORM 6+.
@ -254,6 +257,10 @@ public final class ByteBuddyState {
return unloadedClass; return unloadedClass;
} }
public EnhancerImplConstants getEnhancerConstants() {
return this.enhancerConstants;
}
private static class GetDeclaredMethodAction implements PrivilegedAction<Method> { private static class GetDeclaredMethodAction implements PrivilegedAction<Method> {
private final Class<?> clazz; private final Class<?> clazz;
private final String methodName; private final String methodName;