前言:
此时大家对“java运行环境内存不足”大体比较注意,兄弟们都需要分析一些“java运行环境内存不足”的相关知识。那么小编同时在网上网罗了一些关于“java运行环境内存不足””的相关资讯,希望你们能喜欢,大家一起来了解一下吧!原创声明
本公众号所有文章均原创,未经许可不得转载(本公众号已与维权骑士签约)。为了容易理解和记忆,文章以图解为主、代码为辅。如果您感兴趣,欢迎关注!
文:吴潇/Java高级工程师
最近又接手一个千疮百孔的项目,遇到一个棘手问题:这个项目里面用到了2套id系统,分别叫做did和mid。这个项目用于处理用户请求,有的时候请求传入的是did,需要把它转换成mid;另外一些时候,请求中携带的是mid,需要把它转换为did。问题在于,这两套id系统之间没有任何联系,即不存在一个转换函数、用计算的方式把did转换成mid或者把mid转换成did,如下图所示。
为了在did与mid之间互相转换,这个老项目用到了2个HashMap,第一个HashMap把did作为key,mid作为value保存;第二个HashMap把mid作为key,did作为value保存。每一个did或mid都与一个用户对应。应用刚发布的时候,这2个Map是空的,每当遇到一个did或mid,就把两id之间的对应关系存入以上两个HashMap。
随着时间推移,这两个HashMap占用的内存越来越来大。而且因为是强引用,GC也不能干掉这2个Map中的数据。内存占用量逐渐增大,导致该项目每一个星期都会遇到一次大规模fullgc报警。很明显这种情况应该用有淘汰策略的本地缓存,比如Guava。因为很多id使用一次之后,在接下来的很长一段时间内都基本不再使用了。
假如我们觉得Guava用起来还是很麻烦,有没有更简单的解决方案呢?比如,我们也不清楚到底应该过2分钟、5分钟还是10分钟作为淘汰时间,只是想在JVM内存不足的时候触发GC,让GC帮我们把这2个HashMap中的id都清理一下,不至于让暂时没用的id长期占用内存(效果等同于内存泄露),有没有比较简单的方法呢?
其实,可以考虑使用WeakHashMap,直接替换掉HashMap就可以了,当key不再引用时,保存在WeakHashMap中的key,value对会自动删除。WeakHashMap是一个被人遗忘的java工具类。Oracle考虑到用这个class的人少,在JDK 8优化HashMap实现方式的过程中甚至都没有把WeakHashMap一起改掉。不过这对我们使用WeakHashMap并没有影响。
注意,WeakHashMap<K, V> 与 HashMap<WeakReference<K>, V> 不一样,后面这种用法是错误的。WeakHashMap中的entry[]数组,每个数组元素本身都是一个WeakReference,当key不再引用时,entry数组弱引用的entry项会被GC回收;而对于HashMap<WeakReference<K>, V>,其内部的entry[]数组元素是强引用,entry中的key才是WeakReference,当key被GC,entry还是存在的。所以要特别注意,不能用HashMap<WeakReference<K>, V>的写法,这样会引发意想不到的问题。
使用WeakHashMap的时候还要注意,因为GC一直在后台执行,所以其中的key-value一直处在动态变化中,这对于使用它来说有一定影响。例如,可能前一毫秒,它的size()方法还返回了10个,再调用一次size()就只返回8个了,诸如此类。遍历WeakHashMap的时候,也要考虑这一点。
希望以上对WeakHashMap的初步介绍对你有帮助。如果对互联网编程、前端、后端、客户端、架构、分布式、高可用、高并发、高实时、电商、Redis、MySQL、Zookeeper、Spring、Android、浏览器插件、Java、Java虚拟机、Java Script、C/C++、Linux、个性化推荐、社区发现、机器学习、深度学习、强化学习、数据挖掘、论文、Gnuplot、LaTeX等感兴趣的话,欢迎关注本公众号。
标签: #java运行环境内存不足 #java内存不足怎么办 #jvm内存不足