Sun JDK: Hashmap.get非法使用的挂起分析

from:http://sdh5724.javaeye.com/blog/619130
最近在查看生产环境时候, 发现了一个很奇怪的现象, 某个群集的一台机器8个CPU 被100%吃完。 拿到Java的线程栈的时候, 满满一大片, 几乎都停在了Hashmap.get/put 方法上。 刚开始, 我以为是velocity的bug(也的确是他的bug). 但是, 为什么会挂起来的呢, 令我很难明白。
Java stack代码
  1. "pool-2-thread-1" prio=10 tid=0x007b0d88 nid=0x25 runnable [0xb0bff000..0xb0c01688]
  2. at java.util.HashMap.put(HashMap.java:420)
  3. at org.apache.velocity.util.introspection.ClassMap$MethodCache.get(ClassMap.java:271)
  4. at org.apache.velocity.util.introspection.ClassMap.findMethod(ClassMap.java:102)
  5. at org.apache.velocity.util.introspection.IntrospectorBase.getMethod(IntrospectorBase.java:105)
  6. at org.apache.velocity.util.introspection.Introspector.getMethod(Introspector.java:94)
  7. at org.apache.velocity.runtime.parser.node.PropertyExecutor.discover(PropertyExecutor.java:118)
  8. at org.apache.velocity.runtime.parser.node.PropertyExecutor.<init>(PropertyExecutor.java:56)
  9. at org.apache.velocity.util.introspection.UberspectImpl.getPropertyGet(UberspectImpl.java:246)
"pool-2-thread-1" prio=10 tid=0x007b0d88 nid=0x25 runnable [0xb0bff000..0xb0c01688]
at java.util.HashMap.put(HashMap.java:420)
at org.apache.velocity.util.introspection.ClassMap$MethodCache.get(ClassMap.java:271)
at org.apache.velocity.util.introspection.ClassMap.findMethod(ClassMap.java:102)
at org.apache.velocity.util.introspection.IntrospectorBase.getMethod(IntrospectorBase.java:105)
at org.apache.velocity.util.introspection.Introspector.getMethod(Introspector.java:94)
at org.apache.velocity.runtime.parser.node.PropertyExecutor.discover(PropertyExecutor.java:118)
at org.apache.velocity.runtime.parser.node.PropertyExecutor.<init>(PropertyExecutor.java:56)
at org.apache.velocity.util.introspection.UberspectImpl.getPropertyGet(UberspectImpl.java:246)
前阵子, 在查阅 JDK bug 库的时候, 曾经看到过关于非正确使用Hashmap导致jvm的挂起 的问题。具体有如下解释:
This is a classic symptom of an incorrectly synchronized use of HashMap. Clearly, the submitters need to use a thread-safe HashMap. If they upgraded to Java 5, they could just use ConcurrentHashMap. If they can't do this yet, they can use either the pre-JSR166 version, or better, the unofficial backport as mentioned by Martin. If they can't do any of these, they can use Hashtable or synchhronizedMap wrappers, and live with poorer performance. In any case, it's not a JDK or JVM bug.
我们知道Hashmap不是读写线程安全的, 如果仅仅是全部只读才是线程安全的。 这是JDK文档的解释:
Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be "wrapped" using the  Collections.synchronizedMap method.
虽然, 我们知道Hashmap在被并发读写使用的时候, 会跑出ConcurrentModificationException这个异常, 但是JDK文档明确指出, 这个异常抛出是属于 fail-fast 的一个设计方法, 目的是为了开发者能及早的意识到线程安全问题发生。 但是, 这个fail-fast不是一定会发生, 而是可能会发生的行为。 因此, 在一个不确定状态下的下,jvm线程发生持续100%cpu行为是比较容易理解了(for (Entry<K,V> e = table[i]; e != null; e = e.next), 估计是这个代码进了死循环的状态)。
我对velocity代码比较熟悉,结合了栈的情况, 可以看到velocity错误的使用了Hashmap作为方法cache的数据结构, 在并发处理初始化模板的时候,把机器的CPU 100%吃完的机会是会发生的。我感觉这个问题还是比较容易发生, 在短短的1个星期, 就观察到2次这个现象。
我查阅了下velocity的Bug列表, 果然有人报告过这个问题: https://issues.apache.org/jira/browse/VELOCITY-718  虽然bug已经修复, 但是要修改使用velocity的版本令我很担忧。 velocity在某些细节处理的兼容性上非常糟糕。 曾经升级过一次, 出现过无数的不兼容的行为。 这个bug的大部分因该出现系统的初始化阶段, 要么系统起来, 要么系统启动失败。 基于修改的风险性, 很是纠结。

转载于:https://blog.51cto.com/tianya23/385007

Sun JDK: Hashmap.get非法使用的挂起分析相关推荐

  1. java hprof 分析_[转]Sun JDK自带JVM内存使用分析工具HProf

    Sun JDK自带JVM内存使用分析工具HProf 2008-10-14 11:27 Sun JDK自带JVM内存使用分析工具HProf       使用Sun JDK自带JVM内存使用分析工具HPr ...

  2. Ubuntu 12.04安装Sun JDK 6

    Ubuntu 12.04安装Sun JDK 6 下载 sun jdk 6 bin. 设置权限 chmod +x jdk-6u25-linux-i586.bin 解压文件 ./jdk-6u25-linu ...

  3. 在Fedora 14上安装Sun JDK 6 (转载)

    转自:http://www.icycandy.com/blog/install-sun-jdk-6-on-fedora-14 Fedora 14上默认安装的Java版本是OpenJDK.大多数情况下O ...

  4. IBM JDK,SUN JDK,BEA JDK区别在哪里?

    这是java.sun.com网站上的一张关于JDK构成的图片说明.其中每一个方框(例如AWT,String,IDL,JDBC...)表示JDK的一个"技术领域". 不知道SUN J ...

  5. Ubuntu 12.10使用apt安装Oracle/Sun JDK

    Ubuntu 12.10使用apt安装Oracle/Sun JDK apt-get install python-software-properties sudo add-apt-repository ...

  6. sun jdk 与jdk_Sun过去的世界中的JDK 11和代理

    sun jdk 与jdk 使用JDK 11后,就sun.misc.Unsafe的第一种方法. 其中, defineClass方法已删除. 代码生成框架通常使用此方法在现有的类加载器中定义新的类. 尽管 ...

  7. alpine_glibc 构建sun jdk 8的docker镜像

    2019独角兽企业重金招聘Python工程师标准>>> 构建系统基础镜像 alpine glibc 的Dockerfile内容如下: alpine:3.6 MAINTAINER to ...

  8. 删掉centos原有的openjdk并安装sun jdk

    查看java rpm -qa|grep java 卸载openjdk 使用 rpm -e --nodeps进行强制卸载(PS:将所有的openjdk都nodeps掉,Tab键可以自动补全) 安装sun ...

  9. ubuntu下的jdk环境变量配置(解决sun jdk和open jdk的问题)

    安装好的ubuntu自带的是openjdk,但是对中文支持不是很好,所以我们换用sun jdk为系统默认的jdk,这样在安装netbeans中文版时就不会显示方框! 1.安装jdk-6u20-linu ...

最新文章

  1. Microsoft Bot Framework 上手
  2. ping 原理与ICMP协议---转
  3. sql 统计每月入职离职人数_入职登记表算合同吗?这里面有大学问
  4. 最短无序连续子数组—leetcode581
  5. FBI树-数据结构(二叉树)
  6. JavaScript基础学习(一)—JavaScript简介
  7. mysql 存储过程游标 循环输出select 查询结果
  8. IBM AIX5.3 linux下C/C++实现HTTPS接口
  9. 内网渗透文章CFS三层靶机内网渗透--直接杀到内网
  10. rgba通道转rgb_image – 将RGBA颜色转换为RGB
  11. 临门一脚 | 技术水平一般的程序员如何准备面试
  12. 五金行业:强行业性的进销存系统具体看三项
  13. 用友php漏洞,用友GRP-u8 注入-RCE漏洞复现
  14. These Days
  15. 部分STL_hanhan~
  16. T58 Office开发模式
  17. 使用基于注意力的编码器-解码器实现医学图像描述
  18. 自己架设云游戏服务器需要注意什么?
  19. HIve 删除乱码分区
  20. SPI 机制以及 jdbc 打破双亲委派

热门文章

  1. 微信开发 提示 Redirect_uri参数错误解决方法
  2. Markdown学习测试
  3. citrix xenapp应用保存文件时隐藏服务器上的磁盘
  4. 还珠格格里的尔泰,重现娱乐圈
  5. jmeter--入参为json类型
  6. ZOC7 for Mac连接CentOS7无法输入中文问题
  7. 归并排序(非递归,Java实现)
  8. python提取网页数据
  9. HTML5之Viewport详解
  10. Wait--查看等待