jvm性能调优--初探

随着业务规模的扩大,掌握jvm调优成为一门必修课。


一、什么是jvm
JVM是Java Virtual Machine(Java虚拟机)的缩写
JVM定义了控制Java代码解释执行和具体实现的五种规格,它们是:
- JVM指令系统
- JVM寄存器
- JVM 碎片回收堆
- JVM 存储区
- JVM 栈结构
JVM执行程序的过程 :
1. 加载.class文件
2. 管理并分配内存
3. 执行垃圾收集
二、堆内存
堆内存分配
JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。
例如:
JAVA_OPTIONS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/www/logs/ -Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxPermSize=512m"
这里写图片描述
1.JVM运行时堆的大小
-Xms堆的最小值
-Xmx堆空间的最大值
2.新生代堆空间大小调整
-XX:NewSize新生代的最小值
-XX:MaxNewSize新生代的最大值
-XX:NewRatio设置新生代与老年代在堆空间的大小
-XX:SurvivorRatio新生代中Eden所占区域的大小
3.永久代大小调整
-XX:MaxPermSize
4.其他
-XX:MaxTenuringThreshold,

三、常用命令
Jmap是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。
-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.
-finalizerinfo 打印正等候回收的对象的信息
-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
-permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.
Jstat可以实时显示本地或远程JVM进程中类装载、内存、垃圾收集、JIT编译等数据(如果要显示远程JVM信息,需要远程主机开启RMI支持)。
注:如果在服务启动时没有指定启动参数-verbose:gc,则可以用jstat实时查看gc情况。
命令格式:jstat [option vmid [interval[s|ms] [count]]]
参数解释:
Options — 选项,我们一般使用 -gcutil 查看gc情况
vmid — VM的进程号,即当前运行的java进程号
interval– 间隔时间,单位为秒或者毫秒
count — 打印次数,如果缺省则打印无数次
实例使用:
这里写图片描述
很明显发现垃圾回收出现问题
需要使用jstack

jstack命令的语法格式: jstack -l 。可以用jps查看java进程id。
简单流程:
top -Hp pid 假设pid为21742
printf “%x\n” 21742
jstack 21711 | grep 54ee
就可以查找了

注意:
OOM(“Outof Memory”)异常一般主要有如下2种原因:
1. 年老代溢出,表现为:java.lang.OutOfMemoryError:Javaheapspace
这是最常见的情况,产生的原因可能是:设置的内存参数Xmx过小或程序的内存泄露及使用不当问题。
例如循环上万次的字符串处理、创建上千万个对象、在一段代码内申请上百M甚至上G的内存。还有的时候虽然不会报内存溢出,却会使系统不间断的垃圾回收,也无法处理其它请求。这种情况下除了检查程序、打印堆内存等方法排查,还可以借助一些内存分析工具,比如MAT就很不错。

  1. 持久代溢出,表现为:java.lang.OutOfMemoryError:PermGenspace
    通常由于持久代设置过小,动态加载了大量Java类而导致溢出,解决办法唯有将参数 -XX:MaxPermSize 调大(一般256m能满足绝大多数应用程序需求)。将部分Java类放到容器共享区(例如Tomcatshare lib)去加载的办法也是一个思路,但前提是容器里部署了多个应用,且这些应用有大量的共享类库。

猜你喜欢

转载自blog.csdn.net/qq_36464836/article/details/78434612