一、监控技术简介
- JVM是什么?
- 项目里面有JVM吗?
- JVM跟Tomcat有什么关系?
- 为什么需要去分析JVM?
1. JVM(全称:Java Virtual Machine),Java虚拟机
是Java程序运行的环境,它是一个虚构的计算机,相当于电脑安装系统一样,可以运行应用程序,很多应用使用java语言开发,java最大特点跨平台(windows、linux),真正的java程序在java虚拟机上运行
如上图:JDK、JRE、JVM:JDK(开发工具包)包含了JRE(运行环境),运行时类、库,JRE包含了JVM(java虚拟机)
2. 项目里面有JVM吗?
让tomcat运行起来,就需要有JRE,而JRE自带了JVM
3. JVM跟Tomcat有什么关系?
- 一个tomcat是一个java进程,其中有很多线程(与有多少个app无关)
- 一个tomcat启动一个JVM,其中可以有很多APP
- 一个tomcat中部署的多个APP,虽然同处一个JVM,但是由于无法相互调用,可以认为是分布式的
4. 为什么需要去分析JVM?
JVM对于tomcat来说就相当于运行系统
二、JVM的生命周期
- JVM实例诞生:
当启动一个java程序时,一个JVM实例就诞生了,任何一个拥有public void main(String[] args)函数的class都可以作为JVM实例运行的起点 - JVM实例运行:
main()作为该程序初始线程的起点,任何其他线程均有该线程启动,JVM内部有两种线程,守护线程和非守护线程,main()属于非守护线程,守护线程通常由JVM自己使用,java程序也可以标明自己创建的线程是守护线程 - JVM实例的消亡:
当程序中的所有非守护线程都终止时,JVM才退出
三、JVM的GC机制
-
GC概述
- garbage collection是进程查看堆内存,分辨哪些对象还在被使用中,哪些对象已经不再使用,并删除不再使用的对象的过程
- 被使用:指程序中的某些部分仍然由对对象的引用
- 不再被使用:就是指没有任何部分持有该对象的引用,对于不再被使用的对象,其消耗的内存可以被回收重用,(没有保护(守护线程)就回收掉,释放掉更多的内存给需要的线程使用)
- garbage collection是进程查看堆内存,分辨哪些对象还在被使用中,哪些对象已经不再使用,并删除不再使用的对象的过程
-
GC分代回收机制:
- GC分代回收机制(java8 HotSpot分代)
- 上图是JAVA8的HotSpot的分代策略
- eden+S0+S1合起来称为年轻代(Young Generation),GC非常频繁
- S0+S1 称为幸存区(Survivor Space)
- Tenured称为老年代(Old Generation)
- metasnace:元空间(存放不回收的东西)
- GC分代回收机制(java8 HotSpot分代)
年轻代(Young Generation):
- Java应用在分配Java对象时,这些对象会被分配到年轻代堆空间中去
- . 这个空间大多是小对象并且频繁回收
老年代(Old Generation):
- 年轻代堆空间的长期存活对象会转移到(也许是永久性转移)年老代堆空间
- 这个堆空间通常比年轻代的堆空间大,并且其空间增长速度较缓
持久代(metasnace):JDK8之后叫元空间
- 存放JVM和Java类的元数据(metadata),以及interned字符串和类的静态变量
GC的回收过程:刚开始对象都会被分配到年轻代中,在年轻代中的对象会被进行计数,被频繁使用的对象会被调到幸存区(S0,S1)中,当对象经历多次GC仍然没有被清理,该对象会被认为有一个较长的生命周期,从而被移到年老代中,当年老代中对象到达一定数量时会自动fullgc一次清理掉。当然堆的大小都是可以修改的,结合当前机器的资源修改。
GC频率:当内存达到一定阈值的时候,触发阈值后自动回收(内存小很快到达阈值就会触发GC,内存大,需要很久才达到阈值)
Tips:eden被GC,如果没有被回收掉(进程还没释放,还有守护线程),就+1次,最高15之后被放到S0或S1继续GC,S0和S1互斥,eden要么分给SO,要么分S1,同样如果在S0或S1没有被GC掉,达到15次就会进入Tenured(老年代),到了老年代就不怎么GC或者GC很慢很慢
四、内存回收策略
-
回收策略:Mark-Sweep 标记清除,copying算法,Mark-Compact 标记压缩
内存回收策略 优点 缺点 Mark-Sweep 标记清除 清除较快 删除时会产生碎片,不够放大对象 copying算法 清理的同时进行整理,可以存放大对象 浪费一半的空间 Mark-Compact 标记压缩 标记的时候进行整理,可以存放大对象 速度慢,效率较低 -
Mark-Sweep 标记清除如下图:适合老年代(只管回收,不管整理)
Tips:例如餐厅吃饭有空余的桌子空出来了,未使用的空间腾出来了,不做整理,只做标记
-
copying算法 如下图:适合年轻代,S0和S1(浪费空间),如图要么使用上面一半,要么使用下面一半
要么使用S0,要么使用S1,不会两个都用
-
Mark-Compact 标记压缩:JC不频繁,适合老年代
Tips:
了解JAVA自己的回收机制,更有助于压测,内存如果不用了需要回收释放掉,如果不释放,就会报内存溢出
堆内存:先进先出(例如:进餐厅吃饭,先来的吃完先走)
栈内存:先进后出(例如:有一叠盘子,先放在最下面的最后使用)
五、查看项目使用的jdk版本
- 命令:java -version
- 通过tomcat项目内查看
进入到tomcat的bin目录下:cd /usr/local/tomcat7-8083/bin
执行如下:./version.sh
- 还可以通过tomcat的bin目录下的配置文件查看
执行命令:cat catalina.sh
- 设置如下
Xms 起始堆内存
Xmx 最大堆内存
PermSize 永久代,在1.8之后称之为元空间
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/tomcat7-8083/bin/dushi.hprof
如果出现内存溢出,在对应的路径生成一个hprof文件
-XX:NewRatio=2 新生代和老年代的比例(不写默认1:2),2代表年轻代占1,老年代占2
六:JVM性能监测工具visualvm安装及配置
-
下载地址 https://visualvm.github.io/download.html
JDK1.8之前自带JvisualVM,不需要下载,直接使用.在java的bin目录下,可以找到JvisualVM.exe
JDK比较新的版本,不自带这个工具,那么需要下载并安装.工具的名字也变为了VisualVM
默认在C盘:C:\Program Files\Java\jdk1.8.0_211\bin
-
双击打开,如果需要监控GC,那么要配置一个GC插件,工具→插件→可用插件,选择visual GC,点击左下角的安装
如果自行安装的版本,需要在运行之前进行配置,进入viusalvm的etc目录,打开visualvm.conf,在大约72行的位置添加一行jdk的路径:visualvm_jdkhome="你的jdk的路径"
-
JVM性能监测工具visualvm远程连接服务器的两种方式
-
JMX方式连接(这种方式没有GC监控),能看线程死锁
复制一个catalina-jmx-remote.jar到tomcat服务器的/usr/local/tomcat7-8083/lib然后重启tomcat,就可以连接上了,如果仍然不能连接,那么大多数情况是防火墙拒绝访问,此时可以关闭防火墙,或者将10001添加到白名单
systemctl stop firewalld #关闭防火墙
firewall-cmd --add-port=10001/tcp --permanent #将10001端口添加到白名单
catalina-jmx-remote.jar:支持jmx方式连接的一个扩展包
-
进入 cd /usr/local/tomcat7-8083/bin,打开catlina.sh
加入以下几句代码
-Djava.rmi.server.hostname=192.168.197.132
-Dcom.sun.management.jmxremote.port=10001
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false'
-Djava.rmi.server.hostname=192.168.197.160 填写你的都市商城的IP
-Dcom.sun.management.jmxremote.port=10001 jmx的端口
-Dcom.sun.management.jmxremote.ssl=false 不使用SSL连接
-Dcom.sun.management.jmxremote.authenticate=false 不进行用户验证
之后保存并退出
重启tomcat,就可以访问了
-
jstatd方式连接(这种方式没有CPU监控)
参考之前博客:JVisuaIVM监控Jstatd启动时报错
-