为什么 Google Guava 的 ArrayListMultimap 清除方法在被方法引用调用时会抛出 IllegalAccessError?
Why does Google Guava's ArrayListMultimap clear method throw IllegalAccessError when called by method reference?
演示失败的示例代码:
package ia.quant.nextgen.entry;
import com.google.common.collect.ArrayListMultimap;
import java.util.function.Consumer;
/**
* Created by arpeke on 2015-12-18.
*/
public final class SampleMain {
public static void main(String[] argArr) {
final ArrayListMultimap<Void, Void> arrayListMultimap = ArrayListMultimap.create();
arrayListMultimap.clear();
final Consumer<ArrayListMultimap> arrayListMultimapConsumer = ArrayListMultimap::clear;
arrayListMultimapConsumer.accept(arrayListMultimap);
}
}
这里是Error
(不是Exception
)我看到了:
Exception in thread "main" java.lang.IllegalAccessError:
tried to access class com.google.common.collect.AbstractMapBasedMultimap
from class ia.quant.nextgen.entry.SampleMain
at ia.quant.nextgen.entry.SampleMain.lambda$main(SampleMain.java:17)
at ia.quant.nextgen.entry.SampleMain.main(SampleMain.java:18)
我正在使用 32 位 Java 8 (v1.8.0_60) 和 Google Guava v19.0。我的 Google-Fu 告诉我 Google Guice 是根本原因,但缺乏可信的解释。 (这是一个更大的项目的一部分,该项目还包括 Google 通过 Apache Maven 的 Guice v3.0。)
样本参考:https://github.com/hierynomus/scannit/issues/7
有谁知道...?
- 根本原因
- 解决方法
(最后,我也尝试了GoogleGuava v18.0,但是没有运气。)
更新
此代码有效,但我不明白为什么。 (我是否误解了非静态方法引用?)
final Consumer<ArrayListMultimap> arrayListMultimapConsumer = x -> x.clear();
arrayListMultimapConsumer.accept(arrayListMultimap);
Lambdas 需要找到方法的最后一个定义。所以当你写 ArrayListMultimap::clear
时,解释器实际上试图找到层次结构的 class 最后定义了方法 clear
。碰巧该方法最后定义在 AbstractMapBasedMultimap
中,这是一个 package-private class.
手头的问题很可能出现在 JRE 中,但存在两个解决方法。
第一个就是你描述的那个。第二种是 Guava 团队要么制作 AbstractMapBasedMultimap
public 要么重新定义 ArrayListMultimap
中的 clear()
方法(并且该方法只需要调用 super.clear()
) .
目前两种解决方法中最简单的就是您尝试过的方法。如果我是你,我仍然会要求 Guava 团队制定自己的解决方法,以免影响更多用户。
关于您的解决方法,它之所以有效,是因为您使用该方法而不是引用它。
演示失败的示例代码:
package ia.quant.nextgen.entry;
import com.google.common.collect.ArrayListMultimap;
import java.util.function.Consumer;
/**
* Created by arpeke on 2015-12-18.
*/
public final class SampleMain {
public static void main(String[] argArr) {
final ArrayListMultimap<Void, Void> arrayListMultimap = ArrayListMultimap.create();
arrayListMultimap.clear();
final Consumer<ArrayListMultimap> arrayListMultimapConsumer = ArrayListMultimap::clear;
arrayListMultimapConsumer.accept(arrayListMultimap);
}
}
这里是Error
(不是Exception
)我看到了:
Exception in thread "main" java.lang.IllegalAccessError:
tried to access class com.google.common.collect.AbstractMapBasedMultimap
from class ia.quant.nextgen.entry.SampleMain
at ia.quant.nextgen.entry.SampleMain.lambda$main(SampleMain.java:17)
at ia.quant.nextgen.entry.SampleMain.main(SampleMain.java:18)
我正在使用 32 位 Java 8 (v1.8.0_60) 和 Google Guava v19.0。我的 Google-Fu 告诉我 Google Guice 是根本原因,但缺乏可信的解释。 (这是一个更大的项目的一部分,该项目还包括 Google 通过 Apache Maven 的 Guice v3.0。)
样本参考:https://github.com/hierynomus/scannit/issues/7
有谁知道...?
- 根本原因
- 解决方法
(最后,我也尝试了GoogleGuava v18.0,但是没有运气。)
更新
此代码有效,但我不明白为什么。 (我是否误解了非静态方法引用?)
final Consumer<ArrayListMultimap> arrayListMultimapConsumer = x -> x.clear();
arrayListMultimapConsumer.accept(arrayListMultimap);
Lambdas 需要找到方法的最后一个定义。所以当你写 ArrayListMultimap::clear
时,解释器实际上试图找到层次结构的 class 最后定义了方法 clear
。碰巧该方法最后定义在 AbstractMapBasedMultimap
中,这是一个 package-private class.
手头的问题很可能出现在 JRE 中,但存在两个解决方法。
第一个就是你描述的那个。第二种是 Guava 团队要么制作 AbstractMapBasedMultimap
public 要么重新定义 ArrayListMultimap
中的 clear()
方法(并且该方法只需要调用 super.clear()
) .
目前两种解决方法中最简单的就是您尝试过的方法。如果我是你,我仍然会要求 Guava 团队制定自己的解决方法,以免影响更多用户。
关于您的解决方法,它之所以有效,是因为您使用该方法而不是引用它。