Java lang IllegalAccess on collecting Guava Immutable Table via HashBasedTable accumulator

天大地大妈咪最大 提交于 2019-12-17 14:28:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!