伤不起的项目,宕机已成家常便饭

新项目,自己搭建的环境,项目运行一段时间后(一般三天左右),服务器会宕机一次(内存溢出),tomcat设置内存为1024,用户在100左右,dump下了虚拟机的heap dump文件,用memory analyer tool分析了下,无奈英文水平有限,难以理解,特求解决方案,告诉我下哪个对象有问题,还是session有问题,尽量详细

taozilong537
taozilong537 原始的dump太大,有一个G
大约 8 年之前 回复
ximenpiaohua
ximenpiaohua 否则看ThreadWithAttributes 这个类里面有哪些属性,里面存的什么,看看源代码
大约 8 年之前 回复
ximenpiaohua
ximenpiaohua 原始的dump拿出来看看
大约 8 年之前 回复

15个回答

仔细的看了你提供的日志分析文件,我觉得很可能的问题出在你错误的使用了ThreadLocal 上。
你看看你的代码中,是否建立了一个HashMap,然后放入ThreadLocal 对象中了?对HashMap 的操作只是put?
这里你要注意一点的,因为Tomcat 使用的是线程池,线程处理完成之后,该Thread 对象不会销毁,而是放入线程池中,所以与该线程对应的ThreadLocal 对象也不会消亡。而你每次只是往ThreadLocal 对象中put,从来不去主动调用释放的话,你的对象就会越来越大。
你往这方面去查查你的代码吧

taozilong537
taozilong537 代码都是自己写的,前期没考虑完全,我再看看,貌似有点方向了
大约 8 年之前 回复
iteye_16664
iteye_16664 是这个问题。你可以看到,SessionFactory 的Retained Heap 非常大,而且基本就是你的最大内存大小。同时Hibernate 又将session 绑定到了ThreadLocal 中,你是不是配置了一个Filter 来做这个事?是自己写的吗?
大约 8 年之前 回复
taozilong537
taozilong537 我系统中前期确实疏忽,sessionfactory并未采用单例,但是这会是罪魁祸首么?我不太清楚,现在把sessionFactory改成了单例,还没跑起来,不知道能调好么
大约 8 年之前 回复
taozilong537
taozilong537 我的项目中并未使用spring,我现在根本不知道在何时操作了threadLocal
大约 8 年之前 回复
iteye_16664
iteye_16664 spring 会自动使用ThreadLocal 的。比如会将Hibernate 的Session set 入一个ThreadLocal 中,使该Session 与线程绑定。而你对象中,按理SessionFactory 只会有一个,而你的却有20个,与Session 数量相同。所以,你看看Spring 中你配置的SessionFactory 是否是单例的
大约 8 年之前 回复
taozilong537
taozilong537 我感觉自己并未去操作ThreadLocal类
大约 8 年之前 回复
iteye_16664
iteye_16664 每次在ThreadLocal 里面的HashMap 用完后,直接将ThreadLocal 里面将该对象设置成null,脱离引用,就可以正常被GC 回收了。
大约 8 年之前 回复
taozilong537
taozilong537 如何释放ThreadLocal里的对象
大约 8 年之前 回复

看了一下你提供的报告。
20个org.apache.tomcat.util.threads.ThreadWithAttributes,每个占用的内存约30-40。合起来几乎把所有的内存都用掉了。
建议你分几个时间段做一下检查,看这些ThreadWithAttributes是从开始时是多少,过段时间增加了多少。现在看来,这些进程大约占用700-800就会崩溃。
我发现你系统里面有大量的HashMap及其Entry。仔细检查你的代码,看一下和HashMap相关的操作是否有问题吧。应该是内存泄漏了。

taozilong537
taozilong537 先观察观察,谢谢了~
大约 8 年之前 回复
iteye_12540
iteye_12540 SessionFactoryImpl本来应该是单例。你可以看看现在的内存情况,应该至少是有所好转了。
大约 8 年之前 回复
taozilong537
taozilong537 现在改成单例了,这个会影响到现有程序么,我觉得影响不会很大吧?
大约 8 年之前 回复
iteye_12540
iteye_12540 还有,你SessionFactoryImpl怎么有255个对象?这个应该是单例呀。
大约 8 年之前 回复

应该是线程方面的问题

1.看看ThreadWithAttributes里存的是什么
2.检查项目里自己写的线程部分

很可能是你连数据库产生的问题,你可以用连接池试试

原始的dump拿出来看看  

否则看ThreadWithAttributes 这个类里面有哪些属性,里面存的什么,看看源代码

ThreadWithAttributes是从开始时是多少,过段时间增加了多少

Class Name Objects Shallow Heap Retained Heap
org.hibernate.impl.SessionFactoryImpl
All objects 255 32,640 >= 667,074,888

org.hibernate.impl.SessionImpl
All objects 255 22,440 >= 663,130,760

java.lang.ThreadLocal$ThreadLocalMap
All objects 75 1,800 >= 645,165,816

是不是写了什么数据库的工具类, 然后把连接放到ThreadLocal里
这块写的有问题应该。。

看起来像是内存泄露,不过,建议看看编译的版本是否高于tomcat的jdk版本...

去群组 → 编程语言 → 高级语言虚拟机里问下吧,那里或许可以得到答案

共15条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问