6
6
*/
7
7
package org .hibernate .bytecode .enhance .internal .bytebuddy ;
8
8
9
+ import static net .bytebuddy .matcher .ElementMatchers .anyOf ;
9
10
import static net .bytebuddy .matcher .ElementMatchers .nameStartsWith ;
10
11
import static net .bytebuddy .matcher .ElementMatchers .not ;
11
12
25
26
26
27
import net .bytebuddy .asm .Advice ;
27
28
import net .bytebuddy .asm .AsmVisitorWrapper ;
29
+ import net .bytebuddy .asm .ModifierAdjustment ;
28
30
import net .bytebuddy .description .field .FieldDescription ;
29
31
import net .bytebuddy .description .method .MethodDescription ;
32
+ import net .bytebuddy .description .modifier .ModifierContributor ;
30
33
import net .bytebuddy .description .modifier .Visibility ;
31
34
import net .bytebuddy .description .type .TypeDefinition ;
32
35
import net .bytebuddy .description .type .TypeDescription ;
@@ -47,6 +50,22 @@ final class PersistentAttributeTransformer implements AsmVisitorWrapper.ForDecla
47
50
private static final CoreMessageLogger log = CoreLogging .messageLogger ( PersistentAttributeTransformer .class );
48
51
49
52
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
+ };
50
69
51
70
private final TypeDescription managedCtClass ;
52
71
@@ -185,6 +204,16 @@ DynamicType.Builder<?> applyTo(DynamicType.Builder<?> builder) {
185
204
boolean compositeOwner = false ;
186
205
187
206
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 ) );
188
217
for ( AnnotatedFieldDescription enhancedField : enhancedFields ) {
189
218
builder = builder
190
219
.defineMethod (
0 commit comments