回顾:jvm组成—堆(内存)和非堆(栈)
堆:解决数据如何存放、运行过程中的数据。
堆分为—年轻代、老年代
栈:业务逻辑处理如何调用,栈是干活的。
ygc:edem满了触发ygc,寻根判断进行标记,进行垃圾回收。
fgc:老年代满了触发fgc,代码调用、持久代满、jmap dump 、空间担保原则、RMI框架。
jmap -histo 打印当前堆的情况相当于一个快照,包含对象占用的大小、实例数如果内存泄漏可以看。
如果jmap -histo分析不出来,里面打印了int、char等等,我们就要分析这些是谁调用的。
操作:
jmap dump heap.bin //会触发fgc线上不能用此命令。
下载下来用mat分析
jstat -gcutil pid //打印jc的活动情况 //年轻代、老年代、edem看看是否占满或者是不是在频繁的gc
工具jconsole 可以看堆内存使用情况,图形化查看、还可以看栈、cpu
工具jvisualvm 看内存抽样,看谁导致内存泄漏。
程序如何调度运行—代码运行的地方,栈去读代码,读方法。
堆:内存泄漏、频繁的gc、gc时间很久
栈:保存当前运行的快照信息,能看到方法和每行能定位正在做什么,例如相应时间比较长—看栈当前调用什么东西、和等待什么东西。
发送请求没有相应了:要看栈
jstack pid //如何查看栈
基本概念
线程堆栈也称线程调用堆栈,是虚拟机中线程(包括锁)状态的一个瞬间状态的快照,即系统在某一个时刻所有线程的运行状态,包括每一个线程的调用堆栈,锁的持有情况。虽然不同的虚拟机打印出来的格式有些不同,但是线程堆栈的信息都包含:
1、线程名字,id,线程的数量等。
2、线程的运行状态,锁的状态(锁被哪个线程持有,哪个线程在等待锁等)
3、调用堆栈(即函数的调用层次关系)调用堆栈包含完整的类名,所执行的方法,源代码的行数。
线程作用
因为线程栈是瞬时快照包含线程状态以及调用关系,所以借助堆栈信息可以帮助分析很多问题,比如线程死锁,锁争用,死循环,识别耗时操作等等。线程栈是瞬时记录,所以没有历史消息的回溯,一般我们都需要结合程序的日志进行跟踪,一般线程栈能分析如下性能问题:
1、系统无缘无故的cpu过高
2、系统挂起,无响应
3、系统运行越来越慢
4、性能瓶颈(如无法充分利用cpu等)
5、线程死锁,死循环等
6、由于线程数量太多导致的内存溢出(如无法创建线程等)
线程栈状态
线程栈状态有如下几种:
1、NEW
2、RUNNABLE
3、BLOCKED
4、WAITING
5、TIMED_WAITING
6、TERMINATED
下面依次对6种线程栈状态进行介绍。
线程栈状态详解
1、NEW
线程刚刚被创建,也就是已经new过了,但是还没有调用start()方法,这个状态我们使用jstack进行线程栈dump的时候基本看不到,因为是线程刚创建时候的状态。
2、RUNNABLE
从虚拟机的角度看,线程正在运行状态,状态是线程正在正常运行中, 当然可能会有某种耗时计算/IO等待的操作/CPU时间片切换等, 这个状态下发生的等待一般是其他系统资源, 而不是锁, Sleep等。
处于RUNNABLE状态的线程是不是一定会消耗cpu呢,不一定,像socket IO操作,线程正在从网络上读取数据,尽管线程状态RUNNABLE,但实际上网络io,线程绝大多数时间是被挂起的,只有当数据到达后,线程才会被唤起,挂起发生在本地代码(native)中,虚拟机根本不一致,不像显式的调用sleep和wait方法,虚拟机才能知道线程的真正状态,但在本地代码中的挂起,虚拟机无法知道真正的线程状态,因此一概显示为RUNNABLE。
原文:https://www.cnblogs.com/njq666/p/11003928.html