Eclipselink static weaving with end fields in Java 9

I have JPA annotated fields declared as:

@Column(name = "SOME_FIELD", updatable = false, nullable = false)
private final String someField;

These fields are stored in the database when an object is inserted into the database. They cannot be updated. For the Java programming language, such fields can be considered final.

Using the EclipseLink static weaving plugin, it allows lazy loading objects due to the use of some byte codes.

I don’t know if such constructions (final fields) are officially allowed in JPA, but I like to use them because they compile in time that these fields are not intended for updating.

In Java 8, programs created with such constructs work fine. But in Java 9, when the EclipseLink static weave is involved, I get the following exception at runtime:

Caused by: java.lang.IllegalAccessError: Update to non-static final field xxx.yyy.SomeEntity.someField attempted from a different method (_persistence_set) than the initializer method <init> 

This error is apparently due to the following JVM specification:

Otherwise, if the field is final, it must be declared in the current class, and the instruction must be executed in the initialization of the method () instance of the current class. Otherwise, IllegalAccessError is thrown.

Therefore, I feel that some weaving tools need updating to fulfill this JVM specification. The EclipseLink static weaving tool seems to be one of them.

Questions

  • Are final field constructs, such as those presented here, permitted in JPA?
  • Is there a JDK 9 option to disable checking the final assignment of a field elsewhere, except in the initialization method of the instance () of the class (as a temporary workaround)?

Edit

End fields are not allowed in JPA, in accordance with JPA specifications:

. .

+4
3

, JPA - http://download.oracle.com/otndocs/jcp/persistence-2_2-mrel-eval-spec/index.html - 2.1 :

. .

_persistence_set - , ( - ) , ( ). Java 1.8 , Java 9 .

JPA .

+1

, , JPA?

JDK-8157181, , .


Java VM, - putstatic final

  • (, )
  • putstatic class interface <clinit>.

IllegalAccessError.

, - putfield final

  • .

IllegalAccesError.

, (2), . , Java 9.

BugReport .


JDK 9 , () ( )?

JDK 9 HotSpot >= 53 (Java 9). < 53, ( JDK 9). < 53 final ( /).

, 1.8, , . --release 8, javac.

+5

Eclipselink does not recognize this, however, I wanted this for my project. So I did a dirty “hack” to do it. Basically, I overwrote the eclipselink class org.eclipse.persistence.internal.jpa.weaving.ClassWeaver, and I added this method:

        @Override
public FieldVisitor visitField(
        final int access,
        final String name,
        final String descriptor,
        final String signature,
        final Object value) {
    if (cv != null) {
        int newAccess = access;
        if (!Modifier.isStatic(access) && Modifier.isFinal(access)) {
            newAccess = access & (~Opcodes.ACC_FINAL);
        }
        return cv.visitField(newAccess, name, descriptor, signature, value);
    }
    return null;
}

All final modifiers from non-static fields for objects during plexus will be removed.

I think eclipselink should consider adding this, at least as an option.

0
source

Source: https://habr.com/ru/post/1686259/


All Articles