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 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 EnhancerImplConstants constants;
/**
* Constructs the Enhancer, using the given context.
@ -136,6 +137,7 @@ public class EnhancerImpl implements Enhancer {
this.enhancementContext = new ByteBuddyEnhancementContext( enhancementContext );
this.byteBuddyState = Objects.requireNonNull( byteBuddyState );
this.typePool = Objects.requireNonNull( classLocator );
this.constants = byteBuddyState.getEnhancerConstants();
}
/**
@ -262,18 +264,18 @@ public class EnhancerImpl implements Enhancer {
.annotateField( TRANSIENT_ANNOTATION )
.defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC )
.withParameters( String.class )
.intercept( implementationTrackChange )
.intercept( constants.implementationTrackChange )
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
.intercept( implementationGetDirtyAttributesWithoutCollections )
.intercept( constants.implementationGetDirtyAttributesWithoutCollections )
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
.intercept( implementationAreFieldsDirtyWithoutCollections )
.intercept( constants.implementationAreFieldsDirtyWithoutCollections )
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
.intercept( implementationClearDirtyAttributesWithoutCollections )
.intercept( constants.implementationClearDirtyAttributesWithoutCollections )
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
.withParameters( boolean.class )
.intercept( implementationSuspendDirtyTracking )
.intercept( constants.implementationSuspendDirtyTracking )
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC )
.intercept( implementationGetCollectionTrackerWithoutCollections );
.intercept( constants.implementationGetCollectionTrackerWithoutCollections );
}
else {
//TODO es.enableInterfaceExtendedSelfDirtinessTracker ? Careful with consequences..
@ -284,16 +286,16 @@ public class EnhancerImpl implements Enhancer {
.annotateField( TRANSIENT_ANNOTATION )
.defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC )
.withParameters( String.class )
.intercept( implementationTrackChange )
.intercept( constants.implementationTrackChange )
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
.intercept( implementationGetDirtyAttributes )
.intercept( constants.implementationGetDirtyAttributes )
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
.intercept( implementationAreFieldsDirty )
.intercept( constants.implementationAreFieldsDirty )
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
.intercept( implementationClearDirtyAttributes )
.intercept( constants.implementationClearDirtyAttributes )
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
.withParameters( boolean.class )
.intercept( implementationSuspendDirtyTracking )
.intercept( constants.implementationSuspendDirtyTracking )
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC )
.intercept( FieldAccessor.ofField( EnhancerConstants.TRACKER_COLLECTION_NAME ) );
@ -318,17 +320,17 @@ public class EnhancerImpl implements Enhancer {
isDirty = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, fieldDescription )
.to( adviceIsDirty, adviceLocator )
.to( adviceIsDirty, constants.adviceLocator )
.wrap( isDirty );
getDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, fieldDescription )
.to( adviceGetDirtyNames, adviceLocator )
.to( adviceGetDirtyNames, constants.adviceLocator )
.wrap( getDirtyNames );
clearDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, fieldDescription )
.to( adviceClearDirtyNames, adviceLocator )
.to( adviceClearDirtyNames, constants.adviceLocator )
.wrap( clearDirtyNames );
}
else {
@ -337,23 +339,23 @@ public class EnhancerImpl implements Enhancer {
isDirty = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, getterMapping )
.to( adviceIsDirty, adviceLocator )
.to( adviceIsDirty, constants.adviceLocator )
.wrap( isDirty );
getDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, getterMapping )
.to( adviceGetDirtyNames, adviceLocator )
.to( adviceGetDirtyNames, constants.adviceLocator )
.wrap( getDirtyNames );
clearDirtyNames = Advice.withCustomMapping()
.bind( CodeTemplates.FieldName.class, collectionFieldName )
.bind( CodeTemplates.FieldValue.class, getterMapping )
.to( adviceClearDirtyNames, adviceLocator )
.to( adviceClearDirtyNames, constants.adviceLocator )
.wrap( clearDirtyNames );
}
}
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 )
@ -363,7 +365,7 @@ public class EnhancerImpl implements Enhancer {
.intercept( getDirtyNames )
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME, void.class, Visibility.PUBLIC )
.intercept( Advice.withCustomMapping()
.to( CodeTemplates.ClearDirtyCollectionNames.class, adviceLocator )
.to( CodeTemplates.ClearDirtyCollectionNames.class, constants.adviceLocator )
.wrap( StubMethod.INSTANCE ) )
.defineMethod( ExtendedSelfDirtinessTracker.REMOVE_DIRTY_FIELDS_NAME, void.class, Visibility.PUBLIC )
.withParameters( LazyAttributeLoadingInterceptor.class )
@ -395,14 +397,14 @@ public class EnhancerImpl implements Enhancer {
Visibility.PUBLIC
)
.withParameters( String.class, CompositeOwner.class )
.intercept( implementationSetOwner )
.intercept( constants.implementationSetOwner )
.defineMethod(
EnhancerConstants.TRACKER_COMPOSITE_CLEAR_OWNER,
void.class,
Visibility.PUBLIC
)
.withParameters( String.class )
.intercept( implementationClearOwner );
.intercept( constants.implementationClearOwner );
}
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 org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImplConstants;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.bytecode.spi.BasicProxyFactory;
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
@ -72,6 +73,8 @@ public final class ByteBuddyState {
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
* in Hibernate ORM 6+.
@ -254,6 +257,10 @@ public final class ByteBuddyState {
return unloadedClass;
}
public EnhancerImplConstants getEnhancerConstants() {
return this.enhancerConstants;
}
private static class GetDeclaredMethodAction implements PrivilegedAction<Method> {
private final Class<?> clazz;
private final String methodName;