Skip to content

Commit

Permalink
HHH-18011 Extract reusable constants from EnhancerImpl
Browse files Browse the repository at this point in the history
  • Loading branch information
Sanne committed Apr 28, 2024
1 parent c166b90 commit e340b09
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public Class<? extends Annotation> annotationType() {
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.
Expand All @@ -136,6 +137,7 @@ public EnhancerImpl(final EnhancementContext enhancementContext, final ByteBuddy
this.enhancementContext = new ByteBuddyEnhancementContext( enhancementContext );
this.byteBuddyState = Objects.requireNonNull( byteBuddyState );
this.typePool = Objects.requireNonNull( classLocator );
this.constants = byteBuddyState.getEnhancerConstants();
}

/**
Expand Down Expand Up @@ -262,18 +264,18 @@ private DynamicType.Builder<?> doEnhance(Supplier<DynamicType.Builder<?>> builde
.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..
Expand All @@ -284,16 +286,16 @@ private DynamicType.Builder<?> doEnhance(Supplier<DynamicType.Builder<?>> builde
.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 ) );

Expand All @@ -318,17 +320,17 @@ private DynamicType.Builder<?> doEnhance(Supplier<DynamicType.Builder<?>> builde
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 {
Expand All @@ -337,23 +339,23 @@ private DynamicType.Builder<?> doEnhance(Supplier<DynamicType.Builder<?>> builde
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 )
Expand All @@ -363,7 +365,7 @@ private DynamicType.Builder<?> doEnhance(Supplier<DynamicType.Builder<?>> builde
.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 )
Expand Down Expand Up @@ -395,14 +397,14 @@ else if ( enhancementContext.isCompositeClass( managedCtClass ) ) {
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 );
Expand Down
Original file line number Diff line number Diff line change
@@ -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 );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
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;
Expand Down Expand Up @@ -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+.
Expand Down Expand Up @@ -254,6 +257,10 @@ private Unloaded<?> make(TypePool typePool, DynamicType.Builder<?> builder) {
return unloadedClass;
}

public EnhancerImplConstants getEnhancerConstants() {
return this.enhancerConstants;
}

private static class GetDeclaredMethodAction implements PrivilegedAction<Method> {
private final Class<?> clazz;
private final String methodName;
Expand Down

0 comments on commit e340b09

Please sign in to comment.