JVM history of the whole practice optimization no one

1.jvm operating parameters

There are many parameters can be set, which would allow jvm can run efficiently in a variety of environments in the jvm. Most of the parameters remain default.

1.1 three kinds of argument types

jvm的参数类型分为三类,分别是 :
    标准参数 :
        -help
        -version
    -X参数(非标准参数)
        -Xint
        -Xcomp
    -XX参数(使用率较高)
        -XX:newSize
        -XX:+UseSerialGC        

1.1.1 -server argument with -clinet

可以通过-server或-client设置jvm的运行参数。
    (1)它们的区别是Server VM的初始堆空间会大一些,默认使用的是并行垃圾回收器,启动慢运行快。
    (2)Client VM相对来讲会保守一些,初始堆空间会小一些,使用串行的垃圾回收器,它的目标是为了让JVM的启动速度更快,但运行速度会比Server VM模式慢些。
    (3)JVM在启动的时候会根据硬件和操作系统自动选择使用Server还是Client类型的JVM。
    (4)32位操作系统
            1)如果是Windows系统,不论硬件配置如何,都默认使用Client类型的JVM。
            2)如果是其他操作系统上,机器配置有2GB以上的内存同时有2个以上CPU的话默认使用server模式,否则使用client模式。
    (5)64位操作系统
            1)只有server类型,不支持client类型。       

2.1 -X parameters

jvm的-X参数是非标准参数,在不同版本的jvm中,参数可能会有所不同,可以通过java -X查看非标准参数。     
    -Xmixed:混合模式执行(默认)
    -Xint:仅解释模式执行
    -Xbootclasspath:(用;分隔的目录和zip/jar文件)设置搜索路径以引导类和资源
    -Xbootcalsspath/a:(用;分隔的目录和zip/jar文件)   附加在引导类路径末尾
    -Xbootcalsspath/p:(用;分隔的目录和zip/jar文件)置于引导类路径之前
    -Xdiag :显示附加诊断消息
    -Xnoclassgc :禁用类垃圾收集
    -Xincgc : 启用增量垃圾收集
    -Xloggc:<file> : 将GC状态记录在文件中(带时间戳)
    -Xbatch :禁用后台编译
    -Xms<size> : 设置初始java堆大小
    -Xmx<size> : 设置最大java堆大小
    -Xss<size> : 设置java线程堆栈大小
    -Xprof : 输出cpu配置文件数据
    -Xfuture : 启用最严格的检查,预期将来的默认值
    -Xrs : 减少java/VM 对操作系统信号的使用(请参阅文档)
    -Xcheck:jni : 对JNI函数执行其他检查
    -Xshare:off : 不尝试使用共享类数据
    -Xshare:auto : 在可能的情况下使用共享类数据(默认)
    -Xshare:on : 要求使用共享类数据,否则将失败
    -XshowSettings:all : 显示所有设置并继续
    -XshowSettings:vm : 显示所有与vm相关的设置并继续
    -XshowSettings:properties : 显示所有属性设置并继续
    -XshowSetting:locale : 显示所有与区域设置相关的设置并继续

2.1.1 -Xint、-Xcomp、-Xmixed

在解释模式(interpreted mode)下,-Xint标记会强制JVM执行所有的字节码,当然这会降低运行速度,通常低10倍或更多。
    (编译比较快,运行比较慢)
-Xcomp参数与它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。
    然而,很多应用在使用-Xcomp也会有一些性能损失,当然这比使用-Xint损失的少,原因是-Xcomp没有让JVM启用JIT编译器的全部功能。
    JIT编译器可以对是否需要编译做判断,如果所有代码都进行编译的话,对于一些只执行一次的代码就没有意义了。
    (
-Xmixed是混合模式,将解释模式与编译模式进行混合使用,由jvm自己决定,这是jvm默认的模式,也是推荐使用的模式。            

3.1 -XX parameters

-xx参数也是非标准参数,主要用于jvm的调优和debug操作。
-xx参数的使用有2种方式,一种是boolean类型,一种是非boolean类型:
    boolean类型
        格式 :-xx:[+-]<name> 表示启用或禁用<name>属性
        如 :-xx:+DisableExplicitGC 表示禁用手动调用gc操作,也就是说调用System.gc()无效
    非boolean类型
        格式 :-xx:<name>=<value> 表示<name>属性的值为<value>
        如 :-xx:NewRatio=1 表示新生代和老年代的比值          

4.1 -Xms and -Xmx parameters

-Xms与-Xmx分别是设置jvm的堆内存的初始大小和最大大小。
-Xmx2048m : 等价于-XX:MaxHeapSize,设置JVM最大堆内存为2048M。
-Xms512m :等价于-XX:InitialHeapSize,设置JVM初始堆内存为512M。
适当的调整jvm的内存大小,可以充分利用服务器资源,让程序跑的更快。

5.1 View operating parameters of jvm

有时候我们需要查看jvm的运行参数,这个需求可能会存在2中情况:
第一,运行java命令时打印出运行参数;
第二,查看正在运行的java进程的参数;

Print run the java command parameters 5.1.1

运行java命令时打印参数,需要添加-XX:+PrintFlagsFinal参数即可。 其中参数有boolean类型和数字类型,值的操作符是=或:=,分别
代表默认值和被修改的值。
查看所有的参数,用法 :jinfo -flags <进程id>
通过jps 或者 jps -l 查看java进程
查看某一参数的值,用法 :jinfo -flag <参数名> <进程id>

6.1 jdk1.7 heap memory model

JVM history of the whole practice optimization no one

Young年轻区(代)
    Young区被划分为三部分,Eden区和两个大小严格相同的Survivor区,其中,Survivor区间中,某一时刻只有其中一个是被
    使用的,另外一个留做垃圾收集时复制对象用,在Eden区间变满的时候,GC就会将存活的对象移到空闲的Survivor区间中
    ,根据JVM的策略,在经过几次垃圾收集后,任然存活于Survivor的对象将被移动到Tenured区间。
Tenured年老区
    Tenured区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在Young复制转移一定的次数以后,  对象就会被
    转移到Tenured区,一般如果系统中用了application级别的缓存,缓存中的对象往往会被转移到这一区间。
Perm 永久区
    Perm代主要保存class,method,filed对象,这部分的空间一般不会溢出,除非一次性加载了很多的类,不过在涉及到热部
    署的应用服务器的时候,有时候会遇到java.lang.OutOfMemoryError : PermGen space的错误,造成这个错误的很大原因就
    有可能是每次都重新部署,但是重新部署后,类的class没有被卸载掉,这样就造成了大量的class对象保存在了perm中,这
    种情况下,一般重新启动应用服务器可以解决问题。
Virtual区
    最大内存和初始内存的差值,就是Virtual区。

6.2 jdk1.8 heap memory model

JVM history of the whole practice optimization no one

Can be seen from FIG, jdk1.8 memory model is composed of two parts, the young generation + old generation.
The young generation : Eden + 2 * Survivor
old generation : OldGen
greatest change in Perm region jdk1.8, was replaced with Metaspace (metadata space).
Of particular note are: Metaspace occupied by the virtual memory space is not inside the machine, but in the local memory space, which is the permanent generation of 1.7 the biggest difference lies.
JVM history of the whole practice optimization no one

6.3 Why waste permanently in the 1.7 area?

移除永久代是为融合HotSpot JVM与JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代。
现实使用中,由于永久代内存经常不够用或发生内存泄漏,爆出异常java.lang.OutOfMemoryError : PermGen.
基于此,将永久区废弃,而改元空间,改为了使用本地内存空间。

6.4 view heap memory usage by jstat command

jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。命令的格式如下 :
jstat[-命令选项][vmid][间隔时间/毫秒][查询次数]
6.4.1 View class load statistics

JVM history of the whole practice optimization no one

Description:
Loaded : load class number
Bytes : size of the space occupied by
Unloaded : Quantity is not loaded
Bytes : not loaded space
Time : Time

6.4.2 Checking compile statistics

jstat -compiler 
JVM history of the whole practice optimization no one

Description:
the Compiled : Number compiling
the Failed : the number of failed
Invalid : not quantifiable
Time : Time
FailedType : Failure Type
FailedMethod : Method failure

6.4.3 garbage collection statistics

jstat -gc
JVM history of the whole practice optimization no one

Interval and you may specify the number of prints, the print time per second, a total of five print
jstat -gc 1000 5
JVM history of the whole practice optimization no one

Description:
S0C : Size (KB) of the first Survivor areas
S1C : Size (KB) Survivor second region
S0U : using Size (KB) of the first Survivor areas
SlU : using the size of the second region Survivor ( KB)
EC : size Eden region (KB)
the EU : use size Eden region (KB)
-OC : Old area size (KB)
the OU : Old using size (KB)
the MC : method area size (KB)
a MU : method region using size (KB)
CCSC : compression of space using the size (KB)
CCSU : compression of space using the size (KB)
YGC : the young generation garbage recycle numbers
YGCT : the young generation garbage collection time-consuming
FGC : the number of garbage recycling old's
FGCT : old's garbage collection time-consuming
GCT : total time consuming garbage collection

7.1 query memory usage

前面通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内容,如 :内存使用情况的汇总、对内存溢出的定位与分析。
查看内存使用情况 :
jmap -heap <vmid>

JVM history of the whole practice optimization no one

JVM history of the whole practice optimization no one

JVM history of the whole practice optimization no one

7.2 Check the number and size of objects in memory

查看所有对象,包括活跃以及非活跃的
jmap -histo <pid> | more
查看活跃对象
jmap -histo:live <pid> | more

JVM history of the whole practice optimization no one

Object Description:
B: byte
C: char
D: Double
F.: A float
the I: int
J: Long
the Z: Boolean
[: array, such as [I represents int []
[L + Class Name: Other objects

7.3 The memory usage dump to a file

有些时候我们需要将jvm当前内存中的情况dump到文件中,然后对它进行分析,jmap也是支持dump到文件中的。
用法 :
jmap -dump:format=b,file=dumpFileName <pid>
其中b是代表二进制
示例 :
jmap -dump:format=b,file=/tmp/dump.dat 6219     

7.4 analysis of the dump file by jhat

用法 :
jhat -port <port> <file>
例如 :
jhat -port 9999 /test/dump.dat
这个时候就可以打开浏览器访问 :127.0.0.2:9999  
-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError : 设置初始堆大小和当发生内存溢出时,给内存一个快照并导出一个dump文件 
用MAT进行文件分析

Use of 8 jstack

有些时候我们需要查看下jvm中的线程执行情况,比如,发现服务器的CPU的负载突然增高了、出现了死锁、死循环等,我们
如何分析呢?
由于程序是正常运行的,没有任何的输出,从日志方面也看不出什么问题,所以就需要看下jvm的内部线程的执行情况,然后
再进行分析查找出原因。
这个时候,就需要借助于jstack命令了,jstack的作用是将正在运行的jvm的线程情况进行快照,并且打印出来 :
用法 :jstack <pid>

JVM history of the whole practice optimization no one

8.1 thread state

JVM history of the whole practice optimization no one

在java中线程的状态一共被分成6种 :
    初始态(NEW)
        创建一个Thread对象,但还未调用start()启动线程时,线程处于初始态。
    运行态(RUNNABLE),在java中,运行态包括就绪态和运行态。  
        就绪态
            该状态下的线程已经获得执行所需的所有资源,只要CPU分配执行权就能运行。
            所有就绪态的线程存放在就绪队列中。
        运行态
            获得CPU执行权,正在执行的线程。
            由于一个CPU同一时刻只能执行一条线程,因此每个CPU每个时刻只有一条运行态的线程。
    阻塞态(BLOCKED)
            当一条正在执行的线程请求某一资源失败时,就会进入阻塞态。
            而在java中,阻塞态专指请求锁失败时进入的状态。
            由一个阻塞队列存放所有阻塞态的线程。
            处于阻塞态的线程会不断请求资源,一旦请求成功,就会进入就绪队列,等待执行。
    等待态(WAITING)
            当前线程中调用wait、join、park函数时,当前线程就会进入等待态。
            也有一个等待队列存放所有等待态的线程。
            线程处于等待态表示它需要等待其他线程的指示才能继续运行。
            进入等待态的线程会释放CPU执行权,并释放资源(如 :锁)。
    超时等待态(TIMED_WAITING)
            当运行中的线程调用sleep(time)、wait、join、parkNanos、parkUntil时,就会进入该状态;
            它和等待态一样,并不是因为请求不到资源,而是主动进入,并且进入后需要其他线程唤醒;
            进入该状态后释放CPU执行权和占有的资源。
            与等待态的区别:到了超时时间后自动进入阻塞队列,开始竞争锁。
    终止态(TERMINATED)
            线程执行结束后的状态。

8.2 Analysis of Deadlock

在运行的程序中,通过命令窗口查看当前正在执行的线程id         
jps
同通过jstack进行分析 :
jstack <vmid>

JVM history of the whole practice optimization no one

JVM history of the whole practice optimization no one

In the information output, it has been seen, discovered a deadlock, the key to this:
JVM history of the whole practice optimization no one

可以清晰的看到 :
    Thread2 获取了<0x00000000f655dc50>的锁,等待获取<0x00000000f655dc40>这个锁
    Thread1 获取了<0x00000000f655dc40>的锁,等待获取<0x00000000f655dc50>这个锁
    由此可见,发生了死锁。
可以使用VisualVM工具进行JVM问题的排查

8.3 Monitoring remote jvm

VisualJVM不仅是可以监控本地jvm进程,还可以监控远程的jvm进程,需要借助于JMX技术实现。
8.3.1 What is JMX?
JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序、设备、系统等植入管理功能的框架,JMX可以跨越一系列操作
平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。
8.3.2 Remote monitoring of tomcat
想要监控远程的tomcat,就需要在远程的tomcat进行对JMX配置,方法如下 :
#在tomcat的bin目录下,修改catalina.sh,添加如下的参数
JAVA_OPTS="
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9999 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmremote.ssl=false"                                                                
这几个参数的意思是 :
#-Dcom.sun.management.jmxremote : 允许使用JMX远程管理
#-Dcom.sun.management.jmxremote.port=9999  : JMX远程连接端口
#-Dcom.sun.management.jmxremote.authenticate=false : 不进行身份认证,任何用户都可以连接
#-Dcom.sun.management.jmremote.ssl=false : 不使用ssl
设置好以后保存,并重启tomcat
./startup.sh && tail -f ../logs/catalina.out  :  重启tomcat并显示启动日志
通过VisualVM进行远程连接。
SpringBoot项目是内嵌的tomcat配置方式查看http://www.360doc.com/content/17/1018/20/16915_696185383.shtml

Guess you like

Origin blog.51cto.com/14230003/2417346