jpaeclipselinkjava-9compile-time-weaving

eclipselink static weaving with final fields on Java 9


I have some JPA annotated fields declared final like this:

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

Those fields are stored in the database when the entity is inserted in the database. They cannot further be updated. For the Java programming language, such fields can be considered final.

With the EclipseLink static weaving plugin, it's possible to lazy load entities, owing to some byte code instrumentation.

I don't know if such constructs (final fields) are officially allowed in JPA, but I like to use them, since they enforce at compile time that these fields are not meant to be updated.

In Java 8, programs built with such constructs run fine. But in Java 9, when the EclipseLink static weaving is involved, I get the following runtime exception:

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> 

Such an error seems to be due to the following JVM specification:

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

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

Questions:

Edit:

Final fields are not allowed in JPA, as per JPA specifications:

The entity class must not be final. No methods or persistent instance variables of the entity class may be final.


Solution

  • Please read JPA specification - http://download.oracle.com/otndocs/jcp/persistence-2_2-mrel-eval-spec/index.html - Section 2.1 The Entity Class:

    The entity class must not be final. No methods or persistent instance variables of the entity class may be final.

    Method _persistence_set is code added by weaving (bytecode manipulation of entity classes) and is used to initialize values of entity attributes after class was created by default constructor (with no attributes) call. Java 1.8 allowed this even with final fields, but Java 9 does not.

    You should now follow JPA specification and should not put final persistence attributes into your entities.