JRS*_*fty 11 java iteration concurrenthashmap
我今天遇到了一个非常意想不到的错误,虽然我能够找到一种方法来解决整个问题,但我不确定我是否完全理解它为什么会这样做.
我正在使用的代码最初是用JDK 7环境编写的,当然是针对JRE 7.在代码中我使用了一个ConcurrentHashMap并且需要迭代地图中的键.为此,我使用的map.keySet()是根据JavaDocs应该返回的Set<K>.这很好用,直到我们的构建环境切换到JDK8.
当我们转移到JDK8时,我确保在调用javac时调用1.7的目标/源.当代码在想要遍历地图的键时开始失败时,我感到非常惊讶.没有抛出任何错误,没有异常,线程只是停止了.之后做一些研究,我发现Java8的实施ConcurrentHashMap的.keySet()方法返回一个KeySetView<K,V>.
我通过使用开关解决了这一问题map.keySet(),以得到一个Enumeration<K>使用map.keys().
现在我对这个问题的猜测是,虽然项目是针对Java7编译的,因为使用了JDK8,Java8库被包含在内,但为什么在它出现不匹配时它没有抛出错误或异常?
正如这里所要求的是代码片段:
class MapProcessing
{
private ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<String, Object>();
public MapProcessing()
{
map.put("First",new Object());
map.put("Second",new Object());
map.put("Third",new Object());
}
public void processing()
{
// when calling this type of loop causes a freeze on our system.
for(String key : map.keySet())
{
System.out.println(key);
}
}
public void working()
{
// This is what I had to do to fix the problem.
Enumeration<String> keys = map.keys();
while(keys.hasMoreElements())
{
String key = keys.nextElement();
System.out.println(key);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们正在使用Oracle JDK 8 build 40在Windows 2012服务器上的javac中使用1.7和1.7的目标进行编译.
代码使用在Windows 2012服务器上运行的Oracle JVM 7 build 25运行.
sal*_*lyh 14
如果我使用Java 8和javac -source 1.7 -target 1.8编译代码,然后使用Java 7运行它,我得到一个
Exception in thread "main" java.lang.NoSuchMethodError:
java.util.concurrent.ConcurrentHashMap.keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView;
at stackoverflowt.Test.processing(Test.java:20)
at stackoverflowt.Test.main(Test.java:27)
这是因为字节代码看起来像
public void processing();
Code:
0: aload_0
1: getfield #4 // Field map:Ljava/util/concurrent/ConcurrentHashMap;
4: invokevirtual #10 // Method java/util/concurrent/ConcurrentHashMap.keySet:()Ljava/util/concurrent/ConcurrentHashMap$KeySetView;
7: invokevirtual #11 // Method java/util/concurrent/ConcurrentHashMap$KeySetView.iterator:()Ljava/util/Iterator;
10: astore_1
并明确地引用了Java 7中不存在的ConcurrentHashMap $ KeySetView.我在Mac上使用Java 1.7.0_79和1.8.0_45
如果将代码更改为(仅使用Map接口):
private Map<String, Object> map = new ConcurrentHashMap<String, Object>();
Run Code Online (Sandbox Code Playgroud)
然后它对我有用.Bytecode然后看起来像
public void processing();
Code:
0: aload_0
1: getfield #4 // Field map:Ljava/util/Map;
4: invokeinterface #10, 1 // InterfaceMethod java/util/Map.keySet:()Ljava/util/Set;
9: invokeinterface #11, 1 // InterfaceMethod java/util/Set.iterator:()Ljava/util/Iterator;
14: astore_1
| 归档时间: |
|
| 查看次数: |
7026 次 |
| 最近记录: |