Java lang IllegalAccess 通过 HashBasedTable 累加器收集 Guava 不可变表

标签 java java-8 guava collectors

执行以下代码时出错,

Caused by: java.lang.IllegalAccessError: tried to access class com.google.common.collect.AbstractTable from class

 ImmutableTable.copyOf(listItemsToProcess.parallelStream()
                    .map(item ->
                            ProcessorInstanceProvider.getInstance()
                            .buildImmutableTable(item))
                    .collect(() -> HashBasedTable.create(),
                            HashBasedTable::putAll,

                            HashBasedTable<Integer, String,    
                            Boolean>::putAll)
                    );

Error in coming on - HashBasedTable::putAll Using Oracle's 1.8 jre

最佳答案

这是一个编译器的bug,相关报告是

  • > JDK-8152643 : “Javac 编译的方法引用允许导致 IllegalAccessError”
  • > JDK-8059632 : “方法引用编译使用了不正确的限定类型”

请注意,第一份报告的状态为“已在 8u102 中修复”,因此下载 JDK8u102可以解决问题。当然,当使用 javac 以外的编译器时,例如欧洲法院,你必须确保编译器也是最新的。

无论哪种情况,您都必须重新编译源代码,因为这是一个编译器问题。但是,编译后的代码甚至应该适用于较旧的 JRE。


为了解释这个问题,通常,无论实际方法的声明类型如何,调用都应该使用接收器的编译时类型(或 static 方法的显式类型)编码到字节码中执行。所以如果你有一个 publicA继承public方法 foo来自非publicB , 调用 A.foo应编码为 A.foo而不是 B.foo .对于普通调用,编译器以这种方式工作,但对于方法引用,javac (和 afaik 也是旧版本的 ECJ)未能正确做到这一点。所以当遇到类试图访问B.foo直接访问B , 一个 IllegalAccessError被抛出。

它在使用 lambda 表达式时起作用,因为这样,调用被编译成一个普通的调用指令,编译器在合成方法中正确地工作,并且在构造一个实例时使用对该合成方法的引用运行时的功能接口(interface)。由于合成方法位于同一个类中,因此始终可以访问。

关于Java lang IllegalAccess 通过 HashBasedTable 累加器收集 Guava 不可变表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39112471/

相关文章:

java - 是否有与 Apache Commons Collections 中的 ArrayIterator 通用的等价物?

java - 像素阵列过于占用 CPU

java - 未从 AsyncTask/onPostExecute 调用重载 ArrayAdapter 的 getView

多个 IntStreams 上的 Java 8 forEach

java - 使用 Jackson 将瞬间序列化为毫秒?

java - 从 Factory 重构中提取 lambda(使用 IDE)?

java - android 项目中的 onTouchListener 方法应该放在哪里?

java - 如何使用 TimeUnit 枚举将纳秒转换为秒?

java - 如何使用 Guava 将可能的空值转换为默认值?

java - 泛型:通配符类型的编译错误