无法使字段最终瞬态 java.lang.Class java.util.EnumSet.elementType 可访问:模块 java.base 不会 "opens java.util" 未命名

Unable to make field final transient java.lang.Class java.util.EnumSet.elementType accessible: module java.base does not "opens java.util" to unnamed

当我 运行 这个测试使用 JDK 17:

时出现这个错误
java.lang.reflect.InaccessibleObjectException: Unable to make field final transient java.lang.Class java.util.EnumSet.elementType accessible: module java.base does not "opens java.util" to unnamed module @60addb54
    @Test
    public void testThatDeepCopyCopiesEmptySet() {
        SetOfEnumUserType setOfEnumUserType = createSetOfEnumUserType();
        EnumSet<PaymentMethodType> src = EnumSet.noneOf(PaymentMethodType.class);
        EnumSet<?> dest = (EnumSet<?>) setOfEnumUserType.deepCopy(src);
        assertThat(dest, (is(src)));
        assertThat(dest, not(isSameInstanceAs(src)));
        Class<?> srcType = (Class<?>) ReflectionTestUtils.getField(src, "elementType");
        Class<?> destType = (Class<?>) ReflectionTestUtils.getField(dest, "elementType");
        assertThat(srcType, (is(destType)));
    }

我尝试根据其他答案将此添加到我的 pom.xml:

           <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                    <compilerArgs>
                        <arg>--add-opens java.base/java.lang=ALL-UNNAMED</arg>
                        <arg>--add-opens java.base/java.util=ALL-UNNAMED</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${surefire.plugin.version}</version>
                <configuration>
                    <argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine>
                    <argLine>--add-opens java.base/java.util=ALL-UNNAMED</argLine>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <inherited />
                    </execution>
                </executions>
            </plugin>

但是当我构建时,我现在得到这个错误:

Fatal error compiling: error: invalid flag: --add-opens java.base/java.lang=ALL-UNNAMED

@Holger 是对的,你不应该侵入 JDK 内部。他还正确地解释了 --add-opens 不是有效的 Maven 编译器选项。因为他没有写答案而是评论,所以我写了一个。功劳是他的。

至于源版本和目标版本1.8的恼人评论,这当然不是你问题的根本原因。在符合级别 1.8 的 JDK 17 下编译是完全合法的。

这是一个 MCVE - 您应该首先提供一个,而不是不可编译的代码片段和不完整的 POM:

Maven POM:

请注意:

  • --add-opens现在只存在于它所属的Surefire配置中,不再存在于编译器配置中。
  • 我从配置中删除了非法选项 <inherited />
  • 我依赖于默认的 Surefire 执行,而不是指定另一个。在您的用例中,这可能不是您想要的,但对于 MCVE,这是最简单的选择。
  • 您必须在同一个标​​签中指定两个 --add-opens 选项,而不是两个 <argLine> 标签,只有其中一个会被 Surefire 选中。您可以方便地用换行符将它们分开。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>SO_Java_AddOpens_69753263</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <surefire.plugin.version>2.22.2</surefire.plugin.version>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${surefire.plugin.version}</version>
        <configuration>
          <argLine>
            --add-opens java.base/java.lang=ALL-UNNAMED
            --add-opens java.base/java.util=ALL-UNNAMED
          </argLine>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

</project>

测试代码和助手枚举:

package org.example;

public enum PaymentMethodType {
  FOO, BAR, ZOT
}

我将你的测试用例简化如下:

package org.example;

import org.junit.Test;

import java.lang.reflect.Field;
import java.util.EnumSet;

import static org.junit.Assert.assertEquals;

public class MyTest {
  @Test
  public void testThatDeepCopyCopiesEmptySet() throws NoSuchFieldException, IllegalAccessException {
    EnumSet<PaymentMethodType> src = EnumSet.noneOf(PaymentMethodType.class);
    Field elementType = EnumSet.class.getDeclaredField("elementType");
    elementType.setAccessible(true);
    Class<?> srcType = (Class<?>) elementType.get(src);
    assertEquals(PaymentMethodType.class, srcType);
  }
}