一、内存太高通常有两种状况:内存溢出和内存泄漏html
(1)内存溢出:程序分配的内存超出物理机的内存大小,致使没法继续分配内存,出现OOM报错java
(2)内存泄漏:再也不使用的对象一直占据着内存不释放,致使这块内存浪费掉,长此以往,内存泄漏的对象堆积起来,也会致使物理机的内存被耗尽,出现OOM报错数组
二、内存太高的检测办法:一般咱们的Java服务器部署在Linux机器上面,能够经过jvm自带的命令进行一些检测服务器
(1)查看对象的数目和占用内存大小eclipse
①参数为Java程序的进程号,将结果导出到指定目录中,jvm
jmap -histo:live <进程号> > <导出目录+文件名>
②示例以下,能够看到程序中各个对象所占用内存的状况,根据占用字节数大小降序显示,这里只能看出哪些对象占用内存高,可是还不能具体定位到问题代码,须要进一步排查工具
③一些特殊的标识的含义测试
num #instances #bytes class name ---------------------------------------------- 1: 585152 75635896 [C 2: 66541 71446496 [B 3: 1141734 36535488 java.util.HashMap$Entry 4: 176622 26086840 <constMethodKlass> 5: 176622 24034208 <methodKlass> 6: 17717 19584560 <constantPoolKlass> 7: 174454 18375128 [Ljava.util.HashMap$Entry; 8: 571222 13709328 java.lang.String 9: 832783 13324528 java.lang.Integer 10: 17717 13198840 <instanceKlassKlass> 11: 15092 11237440 <constantPoolCacheKlass> 12: 46779 10429728 [I 13: 191501 7660040 java.util.LinkedHashMap$Entry 14: 12599 6567592 <methodDataKlass> 15: 113526 6357456 java.util.HashMap 16: 197998 6335936 java.util.Hashtable$Entry
(2)若是须要进一步定位问题代码,那么就须要把Java程序的内存镜像导出,再具体分析了,经过以下命令导出程序的内存镜像spa
jmap -dump:format=b,file=<导出目录+文件名> <进程号>
(3)下载Memory Analyzer工具来分析内存镜像线程
http://www.eclipse.org/mat/
(4)打开软件后,File-->Open Heap Dump...,打开刚才导出的镜像文件,选择Leak Suspects Report,Finish,进入分析页面
右键对象-->show objects by class能够查看对象的具体状况
by incomming reference:显示引用该对象/线程的其余对象
by outgoing reference:显示当前对象/线程引用的其余对象
(5)点击Leak Suspects,程序会分析出可能存在内存问题的地方,继续点击Detail能够看到具体有哪些对象和线程,接下来就要根据具体状况具体分析了
一、当程序发现CPU太高的状况时,可使用Windows系统的Process Explorer工具来找到CPU高消耗的线程,因此须要在Windows机器上面搭建好服务器的测试环境,尽可能模拟出线上CPU飙升的状况
二、模拟好环境后,经过任务管理器,在进程一栏中找到Java程序的进程号
三、下载Process Explorer工具
https://docs.microsoft.com/zh-cn/sysinternals/downloads/process-explorer
四、打开工具后,根据刚才的进程号找到进程
五、而后右键-->Properties,再选择Threads选项卡,点进CPU排序,能够找到消耗CPU最多的那个线程的十进制线程ID
一、咱们的Java服务器通常都是部署在Linux系统上面的,当出现CPU太高时,能够先用top命令找到CPU太高的Java进程的进程号
二、而后进一步使用进程号来查看线程的状况
top -H -p <PID>
一、上面咱们找到了CPU太高的具体十进制线程号,使用科学计算器,将十进制的线程号转成十六进制,好比493620-->78834
二、到此已经拿到了可能出问题的进程号和线程号,接下来使用jvm内置的命令来导出Java的堆栈信息
jstack -l <进程号> > <导出目录+文件名>
三、打开导出的堆栈信息,并全文搜索刚刚拿到的十六进制的线程号,就能够找到出问题的代码具体位置了
一、查看Java进程中GC的状况,能够看到新生代老年代等的GC次数和GC时间等参数
jstat -gc <PID>
二、待补充
原文出处:https://www.cnblogs.com/orange911/p/10414056.html