diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java index 386e1574a64c..22b550f55adb 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImpl.java @@ -262,18 +262,18 @@ private DynamicType.Builder doEnhance(Supplier> 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.. @@ -284,16 +284,16 @@ private DynamicType.Builder doEnhance(Supplier> 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 ) ); @@ -318,17 +318,17 @@ private DynamicType.Builder doEnhance(Supplier> 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 { @@ -337,23 +337,23 @@ private DynamicType.Builder doEnhance(Supplier> 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 ) @@ -363,7 +363,7 @@ private DynamicType.Builder doEnhance(Supplier> 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 ) @@ -395,14 +395,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 ); diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImplConstants.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImplConstants.java new file mode 100644 index 000000000000..79ec6eb9fcec --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/EnhancerImplConstants.java @@ -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 . + */ +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 ); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/ByteBuddyState.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/ByteBuddyState.java index bc3b0779da8a..f513da85af17 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/ByteBuddyState.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/ByteBuddyState.java @@ -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; @@ -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 @@ private Unloaded make(TypePool typePool, DynamicType.Builder builder) { return unloadedClass; } + public EnhancerImplConstants getEnhancerConstants() { + return this.enhancerConstants; + } + private static class GetDeclaredMethodAction implements PrivilegedAction { private final Class clazz; private final String methodName;