https://www.cnblogs.com/heihaozi/p/14950212.html
思路: 可以说一下jps,top ,jstack这几个命令,再配合一次排查线上问题进行解答。
参考答案:
- 输入jps,获得进程号。
- top -Hp pid 获取本进程中所有线程的CPU耗时性能
- jstack pid命令查看当前java进程的堆栈状态
- 或者 jstack -l > /tmp/output.txt 把堆栈信息打到一个txt文件。
- 可以使用fastthread 堆栈定位,fastthread.io/
虚拟机栈是每个线程私有的,线程在运行时,在执行每个方法的时候都会打包成一个 栈帧,存储了 局部变量表,操作数据栈,动态链接,方法出口等信息,然后放入栈。每个时刻正在执行的当前方法就是虚拟机栈顶的栈桢。方法的执行就对应着栈帧在虚拟机栈中入栈和出栈的过程。
方法区
主要存储类信息、常量池、静态变量、即时编译期编译后的代码等数据。
一、内存溢出
内存溢出的原因:程序在申请内存时,没有足够的空间。
1. 栈溢出
方法死循环递归调用(StackOverflowError)、不断建立线程(OutOfMemoryError)。
2. 堆溢出
不断创建对象,分配对象大于最大堆的大小(OutOfMemoryError)。
3. 直接内存
JVM 分配的本地直接内存大小大于 JVM 的限制,可以通过-XX:MaxDirectMemorySize 来设置(不设置的话默认与堆内存最大值一样,也会出现OOM 异常)。
4. 方法区溢出
一个类要被垃圾收集器回收掉,判定条件是比较苛刻的,在经常动态生产大量 Class 的应用中,CGLIb 字节码增强,动态语言,大量 JSP(JSP 第一次运行需要编译成 Java 类),基于 OSGi 的应用(同一个类,被不同的加载器加载也会设为不同的类),都可能会导致OOM。
三、内存溢出和内存泄漏辨析
- 内存溢出:实实在在的内存空间不足导致。
- 内存泄漏:该释放的对象没有释放,常见于使用容器保存元素的情况下。
如何避免:
- 内存溢出:检查代码以及设置足够的空间。
- 内存泄漏:一定是代码有问题,往往很多情况下,内存溢出往往是内存泄漏造成的。
四、了解MAT
mat是一个内存泄露的分析工具。
1. 浅堆和深堆
- 浅堆(Shallow Heap):是指一个对象所消耗的内存。
- 深堆(Retained Heap):这个对象被 GC 回收后,可以真实释放的内存大小,也就是只能通过对象被直接或间接访问到的所有对象的集合。通俗地说,就是一个对象包含(引用)的所有对象的大小,如图:
参数说明:
- -Xms5m 堆初始大小5M
- -Xmx5m 堆最大大小5M
- -XX:+PrintGCDetails 打印gc日志详情
- -XX:+HeapDumpOnOutOfMemoryError 输出内存溢出文件
- -XX:HeapDumpPath=D:/oomDump/dump.hprof 内存溢出文件保存位置,此文件用于MAT分析
所有的工具都在jdk的安装bin目录下,比如我的在C:My Program FilesJavajdk1.8.0_201in
。
其中一般情况命令行在线上服务器上使用,可视化工具在本地使用,当然如果你的线上服务器允许远程的话也可以使用可视化工具。
https://www.cnblogs.com/itwxe/p/14884361.html
一般有两种方式(引用计数法、可达性分析),JVM使用的是可达性分析。
2. 可达性分析
来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的。
作为 GC Roots 的对象包括下面几种:
- 当前虚拟机栈中局部变量表中的引用的对象
- 方法区中类静态属性引用的对象
- 方法区中的常量引用的对象
3. finalize
Java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize(),可以完成对象的拯救(不被回收),但是不能保证一定不被回收,说白了就是没啥用,一个坑。
三、各种引用(Reference)
Reference 中存储的数据代表的是另一块内存的起始地址。
1. 强引用
一般的 Object obj = new Object() ,就属于强引用。
(如果有 GCroots 的强引用)垃圾回收器绝对不会回收它,当内存不足时宁愿抛出 OOM 错误,使得程序异常停止,也不会回收强引用对象。
2. 软引用
SoftReference垃圾回收器在内存充足的时候不会回收它,而在内存不足时会回收它。
所以软引用一般用来实现一些内存敏感的缓存,只要内存空间足够,对象就会保持不被回收掉
3. 弱引用 WeakReference
垃圾回收器在扫描到该对象时,无论内存充足与否,都会回收该对象的内存
实际应用,如 WeakHashMap、ThreadLocal。
4. 虚引用 PhantomReference
幽灵引用,最弱,被垃圾回收的时候收到一个通知,如果一个对象只具有虚引用,那么它和没有任何引用一样,任何时候都可能被回收。
虚引用主要用来跟踪对象被垃圾回收器回收的活动。
四、GC
1. Minor GC
- 特点: 发生在新生代上,发生的较频繁,执行速度较快。
- 触发条件: Eden 区空间不足/空间分配担保。
1. 复制算法(Copying)
2. 标记-清除算法(Mark-Sweep)
3. 标记-整理算法(Mark-compact)
6. G1
G1相比较CMS的改进
- 基于标记-整理算法, 不会产生空间碎片,分配大对象时不会无法得到连续的空间而提前触发一次full gc 。
- 停顿时间可控: G1可以通过设置预期停顿时间(Pause time)来控制垃圾收集时间,但是这个预期停顿时间G1只能尽量做到,而不是一定能做到。
2. Full GC
- 特点:主要发生在老年代上(新生代也会回收),较少发生,执行速度较慢。
- 触发条件:
- 调用 System.gc() 。
- 老年代区域空间不足。
- 空间分配担保失败。
- JDK 1.7 及以前的永久代(方法区)空间不足。