最多见的缘由为:html
有多是内存分配确实太小,而正常业务使用了大量内存java
某一个对象被频繁申请,却没有释放,内存不断泄漏,致使内存耗尽python
某一个资源被频繁申请,系统资源耗尽,例如:不断建立线程,不断发起网络链接ios
经过jprofer观察全部对象,触发gc后观察变化。获得不断递增的对象找到问题点。web
经过命令排查算法
确认是否是内存自己就分配太小数据库
方法:jmap -heap pid编程
能够查看新生代,老生代堆内存的分配大小以及使用状况,看是否自己分配太小。tomcat
找到最耗内存的对象安全
方法:jmap -histo:live pid | more
输入命令后,会以表格的形式显示存活对象的信息,并按照所占内存大小排序
确认是不是资源耗尽
工具:
pstree
netstat
查看进程建立的线程数,以及网络链接数,若是资源耗尽,也可能出现OOM。
这里介绍另外一种方法,经过
/proc/${PID}/fd
/proc/${PID}/task
能够分别查看句柄详情和线程数。
例如,某一台线上服务器的sshd进程PID是9339,查看
ll /proc/9339/fd
ll /proc/9339/task
https://mp.weixin.qq.com/s/tVvqVVigmvzLfPjnt2oK0g
经过对dump文件分析,jvisualvm查看对象,分析占内存最多的对象,查看对象内容,找到对象引用找到问题点。
http://blog.csdn.net/wilsonpeng3/article/details/70064336
栈溢出彻底解读 (StackOverflowError)
致使栈溢出的缘由不少,提三个主要的:
https://mp.weixin.qq.com/s/1d8W-eyzsnGDr9-uSfag6Q
根据top命令,发现cpu占用高的进程PID,或者经过ps aux | grep PID命令查看。
定位到具体线程: ps -mp pid -o THREAD,tid,time 或者 ps -Lfp pid 或者 top -Hp pid,看到具体线程占用cpu比例和时间
将tid转成16进制数字:printf "%x\n" tid
最后打印出线程栈信息:jstack pid |grep tid -A 30
https://mp.weixin.qq.com/s/fU4i-jDVHgdJfRtWtXaxrQ
https://mp.weixin.qq.com/s/c-KuGjI_VH1dTxIWtxZJEg
https://www.cnblogs.com/ylz8401/p/6170775.html
http://blog.csdn.net/zhouree/article/details/45153417
http://blog.csdn.net/zhanglh046/article/details/50443528
http://www.xitongzhijia.net/xtjc/20141203/31828.html
java查看线程死锁 JConsole,选择监控进程后,选择 查看死锁线程,能够列出死锁/阻塞线程
https://my.oschina.net/u/3705388/blog/1596538
本质是 jstack 获取线程栈,
找出Thread.State:BLOCKED的线程,对比线程waiting to lock<xxx> 和locked<yyy>,
有没有两个线程的xxx和yyy是相反的,即相互等待对方持有的锁。
IO高如何定位
Step1 : iostat 查看IO状况
Step2: iotop定位负载来源进程
iotop的本质是一个python脚本,从proc中获取thread的IO信息,进行汇总。
Step3 pt-ioprofile定位负载来源文件
pt-ioprofile的原理是对某个pid附加一个strace进程进行IO分析。
https://www.cnblogs.com/zengkefu/p/5634306.html
https://blog.csdn.net/aquester/article/details/51557879
线上动态增长接口调用状况方法:
BTrace是Java的安全可靠的动态跟踪工具。 他的工做原理是经过 instrument + asm 来对正在运行的java程序中的class类进行动态加强,能够在不用重启的状况下监控系统运行状况,方便的获取程序运行时的数据信息,如方法参数、返回值、全局变量和堆栈信息等,而且作到最少的侵入,占用最少的系统资源。
https://my.oschina.net/u/3705388/blog/1615376
G1收集器
并行与并发(充分利用多核多CPU缩短STW时间) 分代收集(独立管理整个Java堆,但针对不一样年龄的对象采起不一样的策略) 空间整合(局部看是基于复制算法,从总体来看是基于标记-整理算法,都不会产生内存碎片) 可预测的停顿(能够明确指定在一个长度为M毫秒的时间片内垃圾收集不会超过N毫秒)
初始标记(标记一下GC Roots能直接关联的对象并修改TAMS值,须要STW但耗时很短) 并发标记(从GC Root从堆中对象进行可达性分析找存活的对象,耗时较长但能够与用户线程并发执行) 最终标记(为了修正并发标记期间产生变更的那一部分标记记录,这一期间的变化记录在Remembered Set Log里,而后合并到Remembered Set里,该阶段须要STW可是可并行执行) 筛选回收(对各个Region回收价值排序,根据用户指望的GC停顿时间制定回收计划来回收);
g1 和 cms 区别,吞吐量优先和响应优先的垃圾收集器选择
CMS是一种以最短停顿时间为目标的收集器
响应优先选择CMS,吞吐量高选择G1
http://blog.csdn.net/lk7688535/article/details/51767460
http://blog.csdn.net/u012969412/article/details/76614988
jvm工具命令排查线上问题
http://blog.csdn.net/u010827436/article/details/46564641
-server --启用可以执行优化的编译器,显著提升服务器的性能 -Xmx4000M --堆最大值 -Xms4000M --堆初始大小 -Xmn600M --年轻代大小 -XX:PermSize=200M --持久代初始大小 -XX:MaxPermSize=200M --持久代最大值 -Xss256K --每一个线程的栈大小 -XX:+DisableExplicitGC --关闭System.gc() -XX:SurvivorRatio=1 --年轻代中Eden区与两个Survivor区的比值 -XX:+UseConcMarkSweepGC --使用CMS内存收集 -XX:+UseParNewGC --设置年轻代为并行收集 -XX:+CMSParallelRemarkEnabled --下降标记停顿 -XX:+UseCMSCompactAtFullCollection --在FULL GC的时候,对年老代进行压缩,可能会影响性能,可是能够消除碎片 -XX:CMSFullGCsBeforeCompaction=0 --此值设置运行多少次GC之后对内存空间进行压缩、整理 -XX:+CMSClassUnloadingEnabled --回收动态生成的代理类 SEE:http://stackoverflow.com/questions/3334911/what-does-jvm-flag-cmsclassunloadingenabled-actually-do -XX:LargePageSizeInBytes=128M --内存页的大小不可设置过大, 会影响Perm的大小 -XX:+UseFastAccessorMethods --原始类型的快速优化 -XX:+UseCMSInitiatingOccupancyOnly --使用手动定义初始化定义开始CMS收集,禁止hostspot自行触发CMS GC -XX:CMSInitiatingOccupancyFraction=80 --使用cms做为垃圾回收,使用80%后开始CMS收集 -XX:SoftRefLRUPolicyMSPerMB=0 --每兆堆空闲空间中SoftReference的存活时间 -XX:+PrintGCDetails --输出GC日志详情信息 -XX:+PrintGCApplicationStoppedTime --输出垃圾回收期间程序暂停的时间 -Xloggc:$WEB_APP_HOME/.tomcat/logs/gc.log --把相关日志信息记录到文件以便分析. -XX:+HeapDumpOnOutOfMemoryError --发生内存溢出时生成heapdump文件 -XX:HeapDumpPath=$WEB_APP_HOME/.tomcat/logs/heapdump.hprof --heapdump文件地址
******* http://ginobefunny.com/post/jvm_interview_questions/
OOM定位排查 (用jmap看内存状况,而后用 jstack主要用来查看某个Java进程内的线程堆栈信息)
A.java.lang.OutOfMemoryError: Java heap space
最多见的缘由:
1.应用程序须要的堆空间比JVM提供的大。 经过-Xmx5G 配置增长堆空间大小
2.流量/数据量峰值:应用程序在设计之初均有用户量和数据量的限制,某一时刻,当用户数量或数据量忽然达到一个峰值,而且这个峰值已经超过了设计之初预期的阈值,那么之前正常的功能将会中止,并触发java.lang.OutOfMemoryError: Java heap space
异常。
3.内存泄漏:特定的编程错误会致使你的应用程序不停的消耗更多的内存,每次使用有内存泄漏风险的功能就会留下一些不能被回收的对象到堆空间中,随着时间的推移,泄漏的对象会消耗全部的堆空间,最终触发java.lang.OutOfMemoryError: Java heap space
错误。
2.3经过Debuggers, profilers, heap dump analyzers
等工具,可让你的程序最大程度的避免内存泄漏问题。
B.java.lang.OutOfMemoryError:GC overhead limit exceeded
当应用程序花费超过98%的时间用来作GC而且回收了不到2%的堆内存时,会抛出java.lang.OutOfMemoryError:GC overhead limit exceeded
错误。具体的表现就是你的应用几乎耗尽全部可用内存,而且GC屡次均未能清理干净。解决办法同上面2.3
C.java.lang.OutOfMemoryError: PermGen space
错误就代表持久代所在区域的内存已被耗尽。
缘由是:太多的类或者太大的类被加载到permanent generation
(持久代)。
持久代主要存储的是每一个类的信息,好比:类加载器引用、运行时常量池(全部常量、字段引用、方法引用、属性)、字段(Field)数据、方法(Method)数据、方法代码、方法字节码等等。咱们能够推断出,PermGen
的大小取决于被加载类的数量以及类的大小。
-XX:MaxPermSize参数 设置持久带大小
分析dump文件:首先,找出引用在哪里被持有;其次,给你的web应用程序添加一个关闭的hook,或者在应用程序卸载后移除引用。你可使用以下命令导出dump文件:
jmap -dump:format=b,file=dump.hprof <process-id>
当你拿到生成的堆转储文件,并利用像Eclipse Memory Analyzer Toolkit这样的工具来寻找应该卸载却没被卸载的类加载器,而后对该类加载器加载的类进行排查,找到可疑对象,分析使用或者生成这些类的代码,查找产生问题的根源并解决它。
https://www.jianshu.com/p/2fdee831ed03
https://www.cnblogs.com/itar/p/7424311.html
https://www.cnblogs.com/wbyp/p/7753528.html
http://blog.csdn.net/garfielder007/article/details/55822985