Skip to content

Commit 5e542b1

Browse files
yrodiereSanne
authored andcommitted
HHH-14828 Remove final modifier from enhanced fields
We need to remove the final modifier if we want to address the possibility of that field being lazy.
1 parent d35b592 commit 5e542b1

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/PersistentAttributeTransformer.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
package org.hibernate.bytecode.enhance.internal.bytebuddy;
88

9+
import static net.bytebuddy.matcher.ElementMatchers.anyOf;
910
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
1011
import static net.bytebuddy.matcher.ElementMatchers.not;
1112

@@ -25,8 +26,10 @@
2526

2627
import net.bytebuddy.asm.Advice;
2728
import net.bytebuddy.asm.AsmVisitorWrapper;
29+
import net.bytebuddy.asm.ModifierAdjustment;
2830
import net.bytebuddy.description.field.FieldDescription;
2931
import net.bytebuddy.description.method.MethodDescription;
32+
import net.bytebuddy.description.modifier.ModifierContributor;
3033
import net.bytebuddy.description.modifier.Visibility;
3134
import net.bytebuddy.description.type.TypeDefinition;
3235
import net.bytebuddy.description.type.TypeDescription;
@@ -47,6 +50,22 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
4750
private static final CoreMessageLogger log = CoreLogging.messageLogger( PersistentAttributeTransformer.class );
4851

4952
private static final Junction<MethodDescription> NOT_HIBERNATE_GENERATED = not( nameStartsWith( "$$_hibernate_" ) );
53+
private static final ModifierContributor.ForField REMOVE_FINAL_MODIFIER = new ModifierContributor.ForField() {
54+
@Override
55+
public int getMask() {
56+
return EMPTY_MASK; // Do not add any modifier
57+
}
58+
59+
@Override
60+
public int getRange() {
61+
return Opcodes.ACC_FINAL; // Remove the "final" modifier
62+
}
63+
64+
@Override
65+
public boolean isDefault() {
66+
return false;
67+
}
68+
};
5069

5170
private final TypeDescription managedCtClass;
5271

@@ -185,6 +204,16 @@ DynamicType.Builder<?> applyTo(DynamicType.Builder<?> builder) {
185204
boolean compositeOwner = false;
186205

187206
builder = builder.visit( new AsmVisitorWrapper.ForDeclaredMethods().invokable( NOT_HIBERNATE_GENERATED, this ) );
207+
// Remove the final modifier from all enhanced fields, because:
208+
// 1. We sometimes need to write to final fields when they are lazy.
209+
// 2. Those fields are already written to by Hibernate ORM through reflection anyway.
210+
// 3. The compiler already makes sure that final fields are not written to from the user's source code.
211+
List<FieldDescription.InDefinedShape> enhancedFieldsAsDefined = new ArrayList<>();
212+
for ( AnnotatedFieldDescription f : enhancedFields ) {
213+
enhancedFieldsAsDefined.add( f.asDefined() );
214+
}
215+
builder = builder.visit( new ModifierAdjustment().withFieldModifiers( anyOf( enhancedFieldsAsDefined ),
216+
REMOVE_FINAL_MODIFIER ) );
188217
for ( AnnotatedFieldDescription enhancedField : enhancedFields ) {
189218
builder = builder
190219
.defineMethod(

0 commit comments

Comments
 (0)