问题
Error while executing below code,
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
回答1:
This is a compiler bug, related reports are
- JDK-8152643: “Javac compiles method reference that allows results in an IllegalAccessError”
- JDK-8059632: “Method reference compilation uses incorrect qualifying type”
Note that the first report has the status “Fixed in 8u102”, so downloading JDK8u102 could solve the issue. Of course, when using a compiler other than javac
, e.g. ECJ, you have to ensure that that compiler is up to date as well.
In either case, you have to recompile the source code, as it is a compiler issue. But then, the compiled code should even work with older JREs.
To explain the issue, normally, invocations should be encoded into the byte code using the compile-time type of the receiver (or the explicit type in case of static
methods), regardless of the declaring type of the actual method implementation. So if you have a public
class A
inheriting the public
method foo
from the non-public
class B
, an invocation of A.foo
should be encoded as A.foo
rather than B.foo
. For ordinary invocations, the compilers work that way, but for method references, javac
(and afaik also older versions of ECJ) failed to do that correctly. So when encountering a class trying to access B.foo
directly without having access to B
, an IllegalAccessError
is thrown.
It works when using a lambda expression instead, as then, the invocation is compiled into an ordinary invocation instruction, for which the compiler works correctly, within a synthetic method and a reference to that synthetic method is used when constructing an instance of the functional interface at runtime. Since the synthetic method recides within the same class, it’s always accessible.
回答2:
AbstractTable
was introduced in Guava version 15. Take a look at your classpath configuration; you're probably using an earlier library version at runtime.
回答3:
Interesting, i replaced method references with Lambda expression and it worked.
ImmutableTable.copyOf(itemList.parallelStream()
.map(item ->
ProcessorInstanceProvider.get()
.buildImmutableTable(item))
.collect(() -> HashBasedTable.create(),
(a, b) -> a.putAll(b),
(a, b) -> a.putAll(b))
);
来源:https://stackoverflow.com/questions/39112471/java-lang-illegalaccess-on-collecting-guava-immutable-table-via-hashbasedtable-a