jpa - eclipselink 静态编织与 Java 9 上的最终字段

标签 jpa eclipselink java-9 compile-time-weaving

我有一些 JPA 注释字段声明为 final,如下所示:

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

当实体插入数据库时​​,这些字段存储在数据库中。它们无法进一步更新。对于 Java 编程语言,此类字段可被视为最终字段。

使用 EclipseLink 静态编织插件,由于一些字节码检测,可以延迟加载实体。

我不知道 JPA 中是否正式允许此类构造(最终字段),但我喜欢使用它们,因为它们在编译时强制执行这些字段不打算更新。

在 Java 8 中,使用此类构造构建的程序运行良好。但是在 Java 9 中,当涉及 EclipseLink 静态编织时,我得到以下运行时异常:
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> 

这样的错误似乎是由于以下 JVM 规范造成的:

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.



因此,我觉得有些编织工具需要一些更新才能满足此 JVM 规范。 EclipseLink 静态编织工具似乎就是其中之一。

问题 :
  • JPA 中是否允许使用最终字段构造,例如此处介绍的那些构造?
  • 除了仅在类的实例初始化 method() 中(作为临时解决方法)之外,是否有 JDK 9 选项可以禁用对最终字段分配的检查?

  • 编辑 :

    根据 JPA 规范,JPA 中不允许使用最终字段:

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

    最佳答案

    JPA 中是否允许使用最终字段构造,例如此处介绍的那些构造?

    如发行说明 JDK-8157181 中所述还有一个变化是限制编译器接受初始化方法之外的最终字段的修改。

    根据 Java VM 规范,putstatic允许字节码修改 final仅限字段

  • 如果该字段在当前类(声明当前方法的类)中声明,并且
  • 如果putstatic指令出现在 classinterface初始化方法 <clinit>当前类(class)的。

  • 否则,一个 IllegalAccessError必须扔。

    同样,putfield允许字节码修改 final仅限字段
  • 如果该字段在当前类中声明并且
  • 如果指令出现在当前类的实例初始化方法中。

  • 否则,一个 IllegalAccesError必须扔。

    不满足条件 (2) 的方法违反了编译器的假设。并且一直在检查以使用 Java 9 实现所需的条件。

    您可以关注 BugReport相同的详细解释。

    除了仅在类的实例初始化 method() 中(作为临时解决方法)之外,是否有 JDK 9 选项可以禁用对最终字段分配的检查?

    With the JDK 9 release, the HotSpot VM fully enforces the previously mentioned restrictions, but only for class files with version number >= 53(Java 9). For class files with version numbers < 53, restrictions are only partially enforced (as it is done by releases preceding JDK 9). That is, for class files with version number < 53 final fields can be modified in any method of the class declaring the field (not only class/instance initializers).



    因此,您可以尝试使用源代码和目标版本 1.8 编译代码,以检查是否可以暂时解决问题。这应该可以通过 --release 8 实现选项使用最新的 javac tool .

    关于jpa - eclipselink 静态编织与 Java 9 上的最终字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46376045/

    相关文章:

    java - 无法执行“ALTER TABLE”,因为表不存在

    java - 映射错误 : More than one row with the given identifier was found

    java - JPA - InheritanceType.Joined 生成错误的表

    hibernate - 一对多多关系

    java - 如何在 JAXB(Eclipse MOXy) 中标记第 3 方不可变对象(immutable对象)

    java - 实体管理器提交中的更多信息

    jpa - 如何为 Spring Data JPA 存储库管理数据库连接?

    java - 使用自定义类加载器从分解模块加载类

    java - 使用 Java 9 的 wildfly swarm 部署崩溃

    javafx - 在 Java 9 或 10 中创建 FXML 成员的正确做法是什么?