误用WeakHashMap引起的死循环cpu跑满问题
最近使用mvel 2.2.0.Final,出现一次cpu跑满,经过线程栈分析,发现是误用WeakHashMap引起的。
故障现场:
看WeakHashMap源码:
public V get(Object key) {
Object k = maskNull(key);
int h = hash(k);
Entry<K,V>[] tab = getTable();
int index = indexFor(h, tab.length);
Entry<K,V> e = tab[index];
while (e != null) {
if (e.hash == h && eq(k, e.get()))
return e.value;
e = e.next;
}
return null;
}
线程在WeakHashMap的get方法里面出不来了,一直在while循环里面。
多线程并发get和put,fullgc或gc的时候可能会出现。
因为gc会把对象给清理掉,然后get方法内的while循环一直找不到eq的对象,循环出不来。
WeakHashMap类已经说明了这个类不是线程安全的。在[2.1.8.Final,~]以上修复了,除了2.2.0.Final,修复详情。
问题复现:
import java.util.Map;
import java.util.Random;
import java.util.WeakHashMap; public class WeakHashMapTest { Thread thread = new Thread(new Runnable() { @Override
public void run() {
}
}); public static void main(String[] args) throws InterruptedException {
Random random = new Random();
// Map<String, String> weak = Collections.synchronizedMap(new WeakHashMap<>());//OK
Map<String, String> weak = new WeakHashMap<>();
for (int i = 0; i < 10; i++) {
weak.put(new String("" + i), "" + i);
}
for (int i = 0; i < 20; i++) {
new Thread(new Runnable() { @Override
public void run() {
StringBuffer sb = new StringBuffer();
for (int k = 0; k < 200; k++) {
sb.append(weak.get(new String("" + (k) % 10)));
if (k % 17 == 0) {
System.gc();
}
int nextInt = random.nextInt(10);
weak.put(new String("" + nextInt), "" + nextInt);
}
System.out.println("end:" + sb.toString());
}
}).start();
}
System.gc();
System.out.println("sleep");
Thread.sleep(10000);
System.out.println("exit");
System.out.println("exit2");
} static void test1() {
Map<String, String> weak = new WeakHashMap<>();
weak.put(new String("1"), "1");
weak.put(new String("2"), "2");
weak.put(new String("3"), "3");
weak.put(new String("4"), "4");
weak.put(new String("5"), "5");
weak.put(new String("6"), "6");
System.out.println(weak.size());
System.gc(); //手动触发 Full GC
try {
Thread.sleep(50); //我的测试中发现必须sleep一下才能看到不一样的结果
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(weak.size());
} }
误用WeakHashMap引起的死循环cpu跑满问题的更多相关文章
- syslog-ng-3.5.6把容器的单核cpu跑满
Question 最近,偶然,会有人说,其docker容器中syslog-ng把cpu跑满,使用perf,mpstat,strace工具看到是syslog-ng在内核态cpu使用率很高,怀疑是某个系统 ...
- 云计算之路-阿里云上: RDS实例CPU跑满引发的故障
今天上午 10: 40 左右,我们所使用的阿里云 RDS 实例的 CPU 突然飙高到近 100% ,造成大量数据库查询操作缓慢.超时,在这个恶劣条件下大量 memcached 缓存无法建立,这样的雪上 ...
- 追踪CPU跑满 堆栈调试
http://blog.donghao.org/2014/04/24/%E8%BF%BD%E8%B8%AAcpu%E8%B7%91%E6%BB%A1/
- 回某位朋友问题备受phpcgi.exe煎熬现在cpu跑满(解决方案)
(本文原创,但是cgi参数参考一个大神写的针对小服务器的,希望大家积极投票哦) 下面是对php-cgi.ext过多引起服务器cup%的解决方法,希望对大家有帮助;大多数情况是发生在第四项上; 解决 ...
- 追踪CPU跑满
http://blog.donghao.org/2014/04/24/%e8%bf%bd%e8%b8%aacpu%e8%b7%91%e6%bb%a1/
- 记一次w3wp占用CPU过高的解决过程(Dictionary和线程安全)
项目上线以来一直存在一个比较揪心的问题,和一个没有信心处理的BUG,那就是在应用程序启动时有可能会导致cpu跑满99%或持续在一个值如50%左右,这样一来对服务器的压力是非常大的,经常出现服务器无法远 ...
- 把 CPU “玩”起来
前言 从开始学习编程之后,就渐渐痴迷于技术,平时遇到购书满减活动时就忍不住买一堆书.前两天闲着无聊,翻开了去年买的<编程之美>,目录里的“让 CPU 占用率听你指挥”吸引力我的眼球.这一年 ...
- 云计算之路-阿里云上:2014年6月12日14:40出现CPU 100%
这是今天遇到的第2次故障,主站1台云服务器在14:40:33-14:41:09期间出现CPU突然跑满的状况,而CPU跑满之前,请求量并没有明显增长. 向阿里云提交之后,说晚上会对这台云服务器的虚拟机进 ...
- [转]如何根据cpu的processor数来确定程序的并发线程数量
原文:http://blog.csdn.net/kirayuan/article/details/6321967 我们可以在cat 里面发现processor数量,这里的processor可以理解为逻 ...
随机推荐
- 数据库备份和还原(固定IP版)
使用方法: 1.首次使用双击export.bat进行备份数据库:2.以后每次使用双击setup.bat进行还原数据库: 备注:如果数据库内容有变,需要重新执行export.bat进行备份数据库. ex ...
- pta总结2
7-1 币值转换 (20 分) 输入一个整数(位数不超过9位)代表一个人民币值(单位为元),请转换成财务要求的大写中文格式.如23108元,转换后变成"贰万叁仟壹百零捌"元.为了简 ...
- JavaScript我学之一变量类型
本文是网易云课堂金旭亮老师的课程笔记,记录下来,以供备忘. 变量类型 只有6种 : 四种原始数据类型boolean , number, string , undefine, 其他object,fun ...
- Spring Boot mybatis HashMap +layui 通用分页
背景: mybatis 常用数据查询的方法都是先建实体类,再建Mapper,最后写Service,如果只是单纯的去查询数据显示,这样操作太麻烦.本文就以mybatis +layui创建通用分页类,简化 ...
- lxml.etree.HTML(text) 解析HTML文档
0.参考 http://lxml.de/tutorial.html#the-xml-function There is also a corresponding function HTML() for ...
- asp+SqlServer2008开发【第一集:安装SqlServer2008以及登陆】
参考:https://blog.csdn.net/i_likechard/article/details/75299983 1,安装sqlServer2008的具体步骤参考网上其他教程,自己根据注释引 ...
- 项目之初的模型设计与status状态字段
0X01 开始做一个app的时候,要先做的是流程设计与数据库模型设计. 但做的模型设计往往是设置字段满足当前的需求,缺乏足够的经验,即使为以后的功能预留出位置,也无法考虑周全. 比如,刚开始做用户表, ...
- windows控件理论学习
mmp快考试了还在浪 一.对话框编辑器创建控件 1.使用new在堆上创建,系统结束时我们需要使用delete去销毁控件 2.对话框编辑器控件,程序结束,自动销毁 二.控件类的基类 CWnd类和消息映射 ...
- Python中何时使用断言
这个问题是如何在一些场景下使用断言表达式,通常会有人误用它,所以我决定写一篇文章来说明何时使用断言,什么时候不用. 为那些还不清楚它的人,Python的assert是用来检查一个条件,如果它为真,就不 ...
- vscode插件安装失败的解决方案
在vscode中点击对应插件的install按钮安装,安装失败,软件提示手动安装(manually install). 手动下载vsix安装包,然后点击install from VSIX...,选择v ...