JVM优化
JVM优化
为什么要对JVM进行优化
JVM优化发生的场景(处理生产环境中发生的问题) 1.当应用布置到生产环境中,时常会出现应用卡退,无日志打印,应用程序没有反应。 2.服务器cpu负载增高。 3.多线程应用下的线程分配问题。
一、JVM运行参数
通过设置JVM参数设置,能让JVM在各种情况下都能高效运行。
参数类型标准
标准类型参数:此类型参数在将来发布的版本中不会发生改变 -help -clinet(设置JVM运行模式,初始空间小,启动快,串行垃圾回收期。适用于32位操作系统_默认,不会在64位操作中出现) java -clinet -showversion target -server(设置JVM运行模式,此模式下的初始空间较大,特点启动慢运行快。并行垃圾回收器,64位操作系统) -version -showversion 输出产品版本并继续执行功能呢 -D<名称>=<值> 设置系统参数 实例:java -Dstring=values -X类型参数(非标准参数) -Xint(在解释模式下执行文件,interpreted mode 此模式下会强制JVM执行所有字节码,一般不建议使用,因为会导致运行速度降低。) java -showversion -Xint target.class -Xcomp(在编译模式下执行,此模式下先编译再执行,JIT编译器对是否编译做判断,一般来说二次执行会快很多,执行时会出现明显卡顿现象,对于只执行一次编译代码就不必要编译到本地。) java -showversion -Xcomp target.class -Xmixed(混合模式下执行,将上面两种解释模式混合使用,JVM的默认模式,是推荐是使用的模式) -XX类型参数(适用与JVM调优和debug操作) -XX:newSize -XX:UserSerialGC -XX使用的两种方式 boolean类型 -XX:[+-]<name> +-表示启用或者禁用操作 非boolean类型 -XX:<name>=<value>
-Xms与-Xmx参数
-Xms设置初始堆内存大小 -XX:initialHeapSize -Xmx设置最大堆内存大小 -XX:MaxHeapSize 这两个命令是-XX类型的
查看jvm的运行参数
1.运行java命令时打印出运行参数 Java -XX:+PrintFlagsFinal target.class 查看之后怎么修改呢 java -XX:+PrintFlagFinal -XX:+ZeroTLAB target.class 修改完成之后会有 :=true/false展示 bool ZeroTLAB :=true {product} 2.查看正在运行的java进程的参数(jinfo) 启动tomcat (tar -xvf apache-tomcat-version.tar.gz ./startup.sh) jinfo -flags <进程id> (输入完成之后就会出现一大串的进程情况) jps 查看正在运行的tomcat进程 jsp -l 查看正在运行的tomcat进程 全目录 jinfo -flag MaxHeapSize 进程id 查看单个的参数情况
二、JVM内存模型
jdk1.7内存模型
young
年轻代young 划分为三个区域 Eden区和两个严格相等的Suvivor区,Suvivor区间中,某一时刻只会有一个被使用,另一个留作垃圾收集时复制对象用。当Eden区放满之后,GC就会将存活的对象移动到空闲的Survivor中去,根据JVM策略,经过几次垃圾回收集,仍然存活与Survivor的对象将会被转移到Tenure区中。
Tenure
Tenure老年区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在young区复制转移一定的次数就会到此区域来,一般如果系统用了application级别的缓存,缓存中的对象一般会转移到此区间中。
Perm
Perm代主要保存class method filed 对象。这一部分空间一般不会溢出,除非一次性加载很多类。但在执行热部署应用服务器的时候,有时候会遇到java.outofMemoryError:PermGen spance 错误。造成的原因可能是每次热部署的时候,class类没有处理掉,这样就造成了大量的class对象保存在Perm中,解决方法是重启服务器。
virtual区
最大内存和初始内存的差值就是virtual
jdk1.8内存模型
![图片说明]
(https://uploadfiles.nowcoder.com/images/20210408/358387792_1617897231511/1FBEE62EAB6FD38AAE0EA11D8FBEA6E0 "图片标题")
为什么要移除永久区
移除永久代是为了融合hotspot JVM与JRockit VM而做的努力,因为JRockit没有永久代,所以不需要配置永久代
,现实使用中,由于永久代内存经常不够用而发生内存泄露,爆出异常Java.lang.OutOfMemorryError.PermGen
基于此将永久区永远废除,而改用元空间,改善的目的是为了使用本地内存。
jstat命令使用 查看堆内存的使用情况
jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]
查看class类加载统计
jstat -class 端口IP
Loaded Bytes Unloaded Bytes times
查看编译统计
jstat -compiler 端口IP
Compiled Failed Invalid Time FailMethod
查看垃圾回收统计
jstat -gc 端口IP
jstat -gc 端口IP 2000 20 每隔两秒打印一次总共打印20此
jmap使用以及内存溢出分析
jmap -heap 端口ip
查看内存的数量以及大小
查看所有的内存对象 包括活跃的与不活跃的
jmap -histo <pid> grep | more
查看所有的内存对象 活跃的
jmap -histo <pid>:live grep | more</pid></pid>
将内存中的使用情况dump到文件中
jmap -dump:format=b,file=dumpFileName <pid>
jmap -dump:format=b,file=/tmp/dum.dat 1111</pid>
使用jhat对dump文件进行分析
jhat -port <port> <file>
jhat -port 1111 /tmp/dum.dat</file></port>
jstack使用
使用场景:某一时间段的cpu负载突然增高了,出现了死锁,死循环等
jstack
这是盗版的菜鸟教程