原因

公司某生产环境在Tomcat启动时,报如下错误:

java.lang.NoSuchMethodError: java.util.concurrent.ConcurrentHashMap.keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView;

然后 Google 了下,发现在Github上也有在讨论:

gist.github.com

导致原因:

因为开发人员在本地使用的JDK版本为1.8,但生产环境中使用的JDK版本为1.7,虽然也在项目的Maven里,添加了sourcetarget的级别都为1.7,但是,当放到生产环境启动的时候,还是会报这个错误。

重现

所以,在本机测试了下。按gist上面的步骤来重现:

在1.8的环境下编译,也将项目的级别设置为1.7,然后使用JDK1.7的JVM来运行:

java代码:

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class HelloConvariance {
  public static void main(String[] args) {
    ConcurrentHashMap<String, String> properties = new ConcurrentHashMap<>();
    Set<String> keySet = properties.keySet();
  }
}
└─[1] <> /ihome/java/jdk/jdk1.7.0_79/bin/java com.github.emacsist.App
Exception in thread "main" java.lang.NoSuchMethodError: java.util.concurrent.ConcurrentHashMap.keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView;
	at com.github.emacsist.App.main(App.java:12)

解决

将开发人员的JDK也设置为1.7

在编译的时候,指定bootclasspath为1.7的,即按上面的gist的处理:

$ /usr/lib/jvm/java-8-oracle/bin/javac -source 1.7 -target 1.7 HelloCovariance.java -bootclasspath /usr/lib/jvm/java-1.7.0-openjdk-amd64/jre/lib/rt.jar