内存:
今天的内容:
内存溢出了,怎么定位?
步骤:
1、验证环境有没有启动起来:http://192.168.226.149:8080/JvmPertest/pertest1
内存的回收和分配:
内存段:
只读读,数据段,堆,栈
只读段:包括程序的代码和常量,由于只读的,不会再去分配新的内存,所以不会
出现内存泄漏
数据段:包括全局变量和静态变量,这些变量在定义时就已经确定了大小,也不会
出现内存溢出
内存映射段:包括动态链接库和共享内存,其中共享内存由程序动态分配和管理,
所以,如果程序在分配后忘记回收,就会导致跟堆内存类似的泄漏问题
内存泄漏的危险非常大,不仅应用程序自己不能访问,系统也不能把他们再次分配给
其它应用,最终耗尽整个系统的内存
最终系统可以通过oom机制杀死进程,但进程在oom前,可能引发一连串的反映,
比如系统内存被占用,其它需要内存的进程就会无法分配新的内存,导致整个
系统的性能访问都非常很慢
2、配置Tomcat堆栈大小:JAVA_OPTS="-server -Xms128m -Xmx128m -Xmn128m",重启Tomcat
3、用性能测试工具(loadrunner,jmeter)发起请求
4、用vmstat来看内存的变化
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
5 0 8120 699548 108 545268 0 0 0 0 3727 421 88 1 11 0 0
5 0 8120 699548 108 545268 0 0 0 1 3792 457 89 1 10 0 0
4 0 8120 699548 108 545268 0 0 0 7 3811 448 89 1 10 0 0
4 0 8120 699516 108 545272 0 0 0 0 3770 548 88 1 11 0 0
1 0 8120 699548 108 545276 0 0 0 0 3753 451 89 1 10 0 0
4 0 8120 699516 108 545280 0 0 0 3 3738 492 88 1 10 0 0
4 0 8120 699516 108 545280 0 0 0 0 3721 413 89 2 9 0 0
4 0 8120 699500 108 545280 0 0 0 0 3760 463 88 2 10 0 0
4 0 8120 699532 108 545280 0 0 0 0 3743 402 88 2 10 0 0
r:如果超过CPU的个数,说明CPU堵塞
内存的free列在不断的变化,并且是越来越小,而buffer和cache基本保持不变,说明,系统中使用的内存
一直在升高。但是这并不能说明内存泄漏
那怎么来确定是不是内存泄漏呢?
1、观察我们的日志输出,有没有错误信息?
2、你的工具请求的接口返回的信息,或者直接在浏览器访问这个接口
输出的错误信息如下:
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.OutOfMemoryError: Java heap space
org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1305)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:979)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Root Cause
内存泄露错误
性能场景的设计:
1、第一次做,不知道哪些接口有性能问题,就需要把主流程里面所有的接口都做性能测试
2、升级的项目,只要做之前用的多,然后会有性能问题的接口
跑多久:一般30分钟足够了,50个并发
看上面的错误信息,已经oom了(OutOfMemoryError: Java heap space)
这个时候怎么办?
3、jmap:用于生成堆栈快照的信息
jmap [option]
option:
-dump: 生成java堆栈快照
-heap: 显示java堆详细信息,使用了哪种回收器,参数配置,分代情况
-histo:显示堆中对象统计信息,包括类,实例数量和合计容量
-F :当虚拟机进程对-dump选项没有响应时,可使用这个选项生成dump快照
-finalizerinfo:显示在F-queue中等待Finalizeer线程执行finalize方法的对象
用jmap生成heap文件:
//format=b:二进制的格式
[root@localhost ~]# jmap -F -dump:format=b,file=testdump.bin pid(14808)
把这个dump包,下载到本地
4、将dump包在mat中打开
选择默认,点击完成按钮
5、默认打开的饼图中
从上图可以看到它的大部分功能,在饼图上,会发现转储的大小和数量的类,对象和类加载器
在overview中,饼图给出了一个最大的对象转储,我们来看下面的action标签中的信息:
Histogram: Lists number of instances per class,列出内存中的对象,对象的个数以及大小
Dominator Tree: List the biggest objects and what they keep alive.列出哪个线程,以及线程下面
的哪些对象占用的空间
Top Consumers: Print the most expensive objects grouped by class and by package,通过图形列出
最大的object
Leak Suspects: includes leak suspects and a system overview 通过mat自动分析内存泄漏的原因
点击Histogram这个链接,在这个页面中可以直观的看到哪个类导致的,创建了多少个对象
class name:类名,java类名
objects:类的对象的数量,这个对象被创建了多少个
shallow heap:一个对象内存的消耗大小,不包含对其它对象的引用
Retained heap:是shallow heap综合,也就是该对象被GC之后所能回收到内存的总和
一般来说,shallow heap堆中的对象是它的大小和保留内存大小相同的对象,是堆内存的数量时,将释放
对象被垃圾收集
主要关注前面两列信息:哪个类,创建了多少个对象
也可以进行搜索
在heap dump overview是它里面,可以看到全局的内存占用信息(了解一下)
Dominator Tree: List the biggest objects and what they keep alive.列出哪个线程,以及线程下面
的哪些对象占用的空间
可以看到com.pertest.PerTest线程最多
Top Consumers:通过图形列出最大的object
这张图展示的是占用内存比较多的对象的分布,下面是具体的一些类和占用
Biggest Top-Level Dominator Classes (Overview)
Biggest Top-Level Dominator Classes:按等级分布的类使用情况,就是按使用次数查看,
java.lang.String被排在第一
Biggest Top-Level Dominator Packages:按照包名看占用,可以根据哪些公共用的到jar或者自己的包
占用
Leak Suspects: includes leak suspects and a system overview:通过mat自动分析内存泄漏的原因
The classloader/component “org.apache.catalina.loader.ParallelWebappClassLoader @ 0xf8280d80”
occupies 83,306,344 (84.71%) bytes. The memory is accumulated in one instance of
“java.lang.Object[]” loaded by “”.
Keywords
java.lang.Object[]
org.apache.catalina.loader.ParallelWebappClassLoader @ 0xf8280d80
从这份报告,看到该图深色区域被怀疑有内存泄漏,可以发现整个heap只有93.8M的内存,但是深色区域就
占用了79.4M,描述信息告诉们主线程占用了大量内存,并且明确指出system class loader加载的
“java.lang.Object[]”实例有内存聚集,并建议用关键字java.lang.Object[]进行检查,mat通过简单的说明
了问题所在,就算使用者没什么处理内存问题的经验,可以点击“details”链接
Accumulated Objects in Dominator Tree
可以看到上面有20 个线程在作业
从图中,可以看到队列中保存了大量的com.pertest.PerTest对象,占用了79兆左右的内存
继续往下看:
ccumulated Objects by Class in Dominator Tree:队列中保存了4,100,056个com.pertest.PerTest,总共
占用了60多兆