执行以下代码时出错,
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
方法的显式类型)编码到字节码中执行。所以如果你有一个 public
类 A
继承public
方法 foo
来自非public
类 B
, 调用 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/