JVM性能优化

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 及以前的永久代(方法区)空间不足。
小蚊子大人
原文地址:https://www.cnblogs.com/ywsheng/p/14948610.html