tomcat6----jvm内存管理及相关设置

tomcat6----jvm内存管理及相关设置

jvm内存管理及相关设置

https://cloud.tencent.com/developer/article/1141496
https://www.cnblogs.com/rsapaper/p/10452541.html
https://juejin.cn/post/6950971239972208647
https://www.cnblogs.com/Jack-Blog/p/14332247.html
https://www.cnblogs.com/Jack-Blog/p/14481982.html
https://www.cnblogs.com/Jack-Blog/p/14853396.html
https://www.cnblogs.com/jichi/p/12580906.html


简化JVM 的逻辑内存模型


java.app --> javac --> java.class --> jvm

类定义:事务操作的接口,可以共享
方法:相同的类属性赋予不同的值,表示不同的对象,调用方法相同

JAVA堆栈
栈:用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程(存放变量,程序运行逻辑
堆:被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存(存放文件的数据,或JAVA运行的对象等

主要分为两部分:JVM 执行引擎、类加载器
JVM运行时,通过类加载器,把所有使用的类加载到内存,将所有使用的类装入内存,类初始化对象实例,并将其置于内存中
JAVA/JVM运行时区域,方法区、堆内存,所有的JAVA线程共享

方法区:是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据(放各个类的方法,共享给对象使用,只能同一类对象,才调用同一类的方法)
堆,各式各样的对象都存放在堆内存空间
JAVA栈:PC寄存器(程序计数器)、本地方法栈都是线程私有
JAVA栈:程序使用的空间主要是堆栈,栈存放全局变量和数据,因此程序逻辑,不同线程逻辑还是有区别的
PC寄存器,程序指针,程序指令切换不同的线程运行
本地方法栈,调用节点自己系统方法接口,以避免JAVA程序的移植性被破坏,并尽量少调用本地方法

Android是JAVA程序,运行在JVM上,运行逻辑和JAVA有一定的区别,但底层差不多
APP --> Android -- > jvm --> 用户空间 --> 内核
性能损耗大约30%
JAVA对程序员只申请内存不用管理释放内存,JAVA会自动释放内存
GC(垃圾收集器) --> 堆

内存算法

引用计数算法

当引用计数为0时清理
每个对象都有引用指针,一个对象被引用几次,引用是有计数器的,如果对象的计数为0,表示可以垃圾回收,这是一种古老的回收算法,有致命的缺陷,没法处理循环应用

标记-清除(Mark-sweep)算法

垃圾回收分两个阶段
第一阶段:整理堆内存中标记所有对象被引用的测试;
第二阶段:在完成标记后遍历整个堆,如果没有引用则释放,释放会产生碎片内存,从而减少内存碎片

复制算法( Copying )算法

堆内存表示将内存划分为两块区域AB,一次仅使用一半,对半分
所有的对象对存放在第一段区域A,当满了或策略变更区域段,找到存活的并复制第二段B,这种算法会额外浪费内存空间,不能充分合理利率资源,且复制也会造成性能损耗

标记-整理(Mark-Compact)算法

两个阶段
第一阶段:整理堆内存中标记所有对象被引用的测试;
第二阶段:在完成标记后遍历整个堆,未标记的对象压缩,移动或交换到一个邻近的内存空间形成一段连续的空间,为了减少内存碎片

无论哪种算法都需要遍历堆内存,这是共性

当一个对象数据发生改变,复制会产生不完成,为了避免这个问题,如何解决?
JAVA:停止所有工作线程,仅运行GC线程,等GC结束,在让线程工作(STP:Stop The World)
每一次Full GC回收都需要一次STP

回收方式

按照内存空间划分处理,如何使用并更方便地清理空间,分割多个内存空间
增量收集:实时垃圾回收,已经过时,1.5版本之前使用
分代收集:当前关注,最广泛

分代垃圾收集器逻辑



1、新生代,新创建的对象 Eden SS1 SS2
2、老年代,存活时间较长的 Old
3、持久代,没必要清理 perm

  • 例:标记复制算法
    App --> Eden --> SS1 --> SS2 --> Old --> Perm(1.8版本后没有持久代的说法)
    1、新生的对象都放入 Eden区,当空间满时,标记存活的应用复制到SS1区,其他Eden区域释放
    2、新生的对象都放入Eden区,当空间满了,这次扫描两个区域Eden、SS1,标记存活的都复制到SS2区,剩下的做释放
    3、新生的对象都放入Eden区,当空间满了,这次扫描两个区域Eden、SS2,标记存活的复制到SS1区,剩下的做释放,若上一次的SS1对象存活一次,SS2也存活一次,下次会放入到Old区域(简单来说就是存活跳跃2次标记得到到Old区域)
    4、SS1、SS2身份会来回切换,源FROM、目标TO
    大部分的对象在第一阶段都完成回收,因此新生代回收很频繁,根据实际情况可增加空间
    当老年代空间满时,很久才会满,而且回收较慢,若不太频繁,可根据实际情况分配此空间,可适当缩小此空间
    由于full gc全堆时间的垃圾回收,时间较长,卡顿较长,因此需要定义内存空间的大小,减少 full gc的次数,避免对系统造成影响
    如果区域都存活可能是内存空间小了,不考虑极端情况

Major gc 标记整理算法,效率低不会产生内存碎片
Minor gc 复制算法,分代完成

收集器工作情景
串行收集器:单线程收集垃圾(一般客户端使用,当然也可以并行)
并行收集器:多线程同时工作(一般用于科学计算)
并发收集器:回收过程当中,线程不停止工作做回收,回收是分阶段的,有阶段有条件的并发,不是真正的并发(并发一般是对响应时间有影响,缩短响应用户的请求)

1、内存空间设定,包括各种空间的比例切分
2、针对不同代别和业务场景,选择最合适的垃圾收集器算法

The memory structure of a JVM process


-Xmx:堆内存,新生代和老年代的最大空间(一般设置为总系统内存的3/2,早期最大单进程不要超过32G,超过32G以后,内存管理效率会下降,性能不会提高,反而会下降)例:-Xmx4g
-Xms:初始分配内存空间(新生代,老年代,初始空间刚开始占用多少内存空间,也有这种用法, Xmx=Xms)例:-Xms2g
-XX:NewSize 初始分配的新生代空间大小 -Xms-(-XX:NewSize)<=MaxNewSize,**Xms-NewSize=初始老年代空间**
-XX:MaxNewSize **新生代的最大空间**; -Xms- (-XX:MaxNewSize),**Xmx-MaxNewSize=老年代最大空间**
-XX:NewRatio **新生代除以老年代的值**,**以比例的方式来设定**,如果为1,新生代和老年代空间一样,若为2,新生代是老年代空间的2倍
-XX:SurvivoRatio:Eden/Survior=   新生代和Eden设置多大(设置 Eden 空间的比率,例如:如果年轻代空间是 10M,-XX:SurvivoRatio=2,那么 5M 将用于 Eden 区,剩余的 5M 平均分给 2 个 Survivor 区 (每个 2.5M)。默认值为 8)
-Xss:设置线程私有的栈空间大小,使用的不多,一般保持默认即可

PS Eden Space
PS Old Gen
PS Survivor Space 存活区
Code Cache 代码缓存
Compressed Class Space 压缩类空间
Metaspace 元空间

垃圾回收算法

新生代
Serial 序列 串行
ParNew 并行
Paraller Scavenge 吞吐量
老年代
Serial Old:单GC线程回收老年代中不再被使用的对象
Parallel Old:多GC线程回收老年代中不再被使用的对象
CMS(Concurrent Mark Sweep):以获得最短回收停顿时长为目标,是互联网站点服务端的B/S系统上较佳的回收算法;标记-清除
G1:Gabage First 并行和并发,分代收集,空间整合,可预测停顿(新算法)

整理过程分四个阶段
初始标记 串行
并发标记 并发
重新标记 串行
并发清除 并发

指定垃圾收集器

-XX:
UseSerialGC:运行于Client模式下,新生代是Serial,老年代使用SerialOld 
UseParNewGC:新生代使用ParNew,老年代使用Seriatold 
UseParalellGC:运行于server模式下,新生代使用Paralell Scavenge(为吞吐量优化),老年代使用Sertalold
	-XX:ParalessGCThreads=20 指定20个线程,可以和UseParalellGC或UseParalelloldGC使用,新年代与老年代,根据实际场景
UseParalelloldGC:新生代使用Paralell Scavenge,老年代使用Paralell old
UseConcMarkSweepGC:新生代使用ParNew,老年代优先使用CMS,备选方式为Serial old(一般tomcat使用较多,并发标记清理,缩短用户响应时间)

辅助定义工作逻辑

	CMSInitiatingOccupancyFraction:**设定老年代空间占用比例达到多少后触发回收操作**,默认为68%;
	UseCMSCompactAtFullCoilection:CMS完成内存回收后是否要进行内存碎片整理;(标记清理算法在整理)
	CMSFullGCsBeforeCompaction:在多少次回收后执行一次内存碎片整理;

ParalessGCThreads:并行GC线程的数量

调试可开启,调试完一定要关闭,会产生大量的日志IO
显示垃圾回收的统计信息:

-XX:+PrintGC:输出GC信息;
-XX:PrintGCDetails:输出详细的GC信息;
-XX:+PrintGCTimeptamps:一般与前两个混合使用;
-XX:PrintHeapAtGC:打印GC前后的详细堆栈的详细信息

例:指定算法时,注意需要+号

JAVA_OPTS="-server -Xmx1g -Xms512m -XX:NewSize=128m -XX:MaxNewSize=320m -XX:+UseConcMarkSweepGC -XX:CMSInitiatingoccupancyFraction=80"

JVM常用分析工具

JAVA程序相当于黑盒,运行在JVM中

jps 列出目标系统上已检测的 Java 虚拟机 (JVM),查看JAVA进程状态

usage: jps [--help]
       jps [-q] [-mlvV] [<hostid>]

-q:静默模式;
-v:显示传递给jvm的命令行参数;
-m;输出传入main方法的参数;
-1:输出main类或jar完全限定名称;
-V:显示通过flag文件传递给jvm的参数;
[<hostid>]:主机id,默认为Localhost;

常用选项
[root@final ~]# jps -lv
9328 org.apache.catalina.startup.Bootstrap --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp
10006 jdk.jcmd/sun.tools.jps.Jps -Dapplication.home=/usr/lib/jvm/java-11-openjdk-11.0.12.0.7-0.el7_9.x86_64 -Xms8m -Djdk.module.main=jdk.jcmd

jinfo 输出给java进程所有配置信息

jinfo <option> <pid>
   (to connect to a running process)
   
-flag <name>         to print the value of the named VM flag
-flags               to print VM flags
-sysprops            to print Java system properties

常用选项
jinfo -sysprops 9328

[root@final ~]# jinfo -flags 9328
VM Flags:
-XX:CICompilerCount=2 -XX:InitialHeapSize=65011712 -XX:MaxHeapSize=1031798784 -XX:MaxNewSize=343932928 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=21626880 -XX:NonNMethodCodeHeapSize=5825164 -XX:NonProfiledCodeHeapSize=122916538 -XX:OldSize=43384832 -XX:ProfiledCodeHeapSize=122916538 -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC 

jstack 查看java进程、核心文件或远程调试服务器的 Java 线程堆跟踪

jstack [-l][-e] <pid>
	(to connect to running process)
	
-l:long listings,会显示额外的锁信息,因此,发生死锁时常用此选项;
-m:混合模式,既输出Java堆栈信息,也输出C/C++堆栈信息;
-F:当使用"jstack -l PID"无响应,可以使用-F强制输出信息;

jmap 打印进程、核心文件或远程调试服务器的共享对象内存映射或内存详细信息

jstat 监控 Java 虚拟机 (JVM) 统计信息

Usage: jstat --help|-options
       jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]

获取统计列表选项
[root@final ~]# jstat -options
-class	显示有关类加载器行为的统计信息
-compiler	显示有关 Java HotSpot VM Just-in-Time 编译器行为的统计信息
-gc	显示垃圾收集堆行为的统计信息 
-gccapacity	显示关于代的容量及其对应空间的统计信息
-gccause	显示有关垃圾收集统计信息的摘要(与-gqutil 相同),以及上次和当前(适用时)垃圾收集事件的原因
-gcmetacapacity	显示有关元空间大小的统计信息
-gcnew	显示新生代行为的统计信息
-gcnewcapacity	显示新生代的大小及其对应空间的统计信息
-gcold	显示有关老年代行为的统计信息和元空间统计信息
-gcoldcapacity	显示有关老年代大小的统计信息
-gcutil	显示有关垃圾收集统计信息的摘要
-printcompilation	显示 Java HotSpot VM 编译方法统计信息

Loaded:加载的类数
Bytes:加载的 kB 值
Unloaded:卸载的类数
Bytes:卸载的千字节数
Time:执行类加载和卸载操作所花费的时间

[root@final bin]# jstat -class 9328
Loaded  Bytes  Unloaded  Bytes     Time   
  3131  6450.1        0     0.0       2.52

S0C:当前幸存者空间 0 容量(kB),0存活区空间
S1C:当前幸存者空间 1 容量(kB),1存活区空间
S0U:幸存者空间 0 利用率 (kB) ,0存活区已用空间
S1U:幸存者空间 1 利用率 (kB),1存活区已用空间
EC:当前eden空间容量 (kB)
EU:eden空间利用率 (kB)
OC:当前old容量 (kB)
OU:old利用率 (kB)
MC:Metacspace(元空间)容量 (kB)
MU:Metacspace(元空间)利用率 (kB)
CCSC:压缩类空间容量 (kB)
CCSU:使用的压缩类空间 (kB)
YGC:young(年轻代)垃圾收集事件的数量,一共发生了几次新生代的垃圾回收
YGCT:young(年轻代)垃圾回收时间,所有新生代垃圾回收的总时长
FGC:ful1 GC 事件的数量
FGCT:完整的垃圾回收时间 
CCT:总垃圾收集时间

[root@final bin]# jstat -gc 9328   
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT   
2112.0 2112.0 1191.2  0.0   16896.0  15940.1   42368.0     7344.7   14592.0 13607.4 1792.0 1453.3      4    0.123   0      0.000   -          -    0.123

动态跟踪,默认位置ms
jstat -gc 9328 1000
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT   
2112.0 2112.0  0.0   414.1  16896.0   3018.9   42368.0     8436.9   15104.0 14199.8 1792.0 1477.2      5    0.127   0      0.000   -          -    0.127
2112.0 2112.0  0.0   414.1  16896.0   3018.9   42368.0     8436.9   15104.0 14199.8 1792.0 1477.2      5    0.127   0      0.000   -          -    0.127

跟踪新生代
jstat -gcnew 9328 1s	#定义1s,1秒跟踪
[root@final bin]# jstat -gcnew 9328 1000
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
2112.0 2112.0    0.0  414.1 15  15 1056.0  16896.0   3153.8      5    0.127
2112.0 2112.0    0.0  414.1 15  15 1056.0  16896.0   3153.8      5    0.127

定义跟踪次数
[root@final bin]# jstat -gcnew 9328 1s 3
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
2112.0 2112.0  424.2    0.0 15  15 1056.0  16896.0   9572.6      6    0.128
2112.0 2112.0  424.2    0.0 15  15 1056.0  16896.0   9572.6      6    0.128
2112.0 2112.0  424.2    0.0 15  15 1056.0  16896.0   9572.6      6    0.128

图形化工具 jconsole

组件JMX,外部程序是通过JMX接口来监控
jmx: java Management eXtensions

tomcat常用优化配置

1、设定内存空间

/etc/sysconfig/tomcat,/etc/tomcat/tomcat.conf
JAVA_OPTS-"-server-Xms32g-Xmx32g-XX:Newsizes-XX:MaxNewSizes
	-server:服务器模式
	-Xms:堆内存初始化大小;
	-Xmx:堆内存空间上限;
	-XX:NewSizes:新生代空间初始化大小;
	-XX:MaxNewSizes:新生代空间最大值

2、线程池设置

<Connector port="8080" address="127.0.0.1" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

常用属性
maxThreads最大线程数;	连接线程,最大并发数量
minSpareThreads:最小空闲线程数;	极端情况可以设置一样,但空闲时会造成资源浪费
maxSpareThreads:最大空闲线程数;
acceptCount:等待队列的最大长度;	超过并发请求数,多出来的排队,放入内存缓存区中,越长对服务器内存资源越大,超过最大连接数过期会被拒绝,若在队列中,会影响用户访问速度
URIEncod ing:URI地址编码格式,建议使用UTF-8;
enableLookups:是否启用dns解析,建议禁用;	若使用到域名可使用hosts解析,内建DNS
compression:是否启用传输压缩机制,建议"on";    这将节省网络带宽流量,增加 CPU使用周期,如果存在缓存代理服务器,可能会导致缓存出现问题,如请求图片、返回的压缩文件、会导致客户端无法接收、需要设置缓存区、一般内网不会启动压缩
compress ionMinsize:启用压缩传输的数据流最小值,单位是字节;	太小的文件没必要压缩
compressableMimeType:定义启用压缩功能的MIME类型;
	text/html,text/xml,text/css,text/javascript

3、根据实际情况设定关闭不必要的协议
http https ajp(二进程协议)
前端若是nginx,那么关闭http
前端若是httpd,使用ajp,浏览器是无法识别ajp协议的,无法绕过代理服务器

4、禁用8005端口

<Server port="-1"shutdown="SHUTDOWN>

5、隐藏版本信息

<Connector port="8080" address="127.0.0.1" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" Server="SOME STRING"/>

小结

tomcat优化大致分为两部分
1、JVM 优化层级维度 内存设定,垃圾回收设定,TOMCAT线程池设定
2、连接线程优化
程序级优化,一般不是运维做的,开发做的

也不要过度优化

YGC次数和YGCT时长累加
说明YGC过于频繁,要能空间小了

OLDGC很慢,说明空间比例分割有问题
如果两种都很慢,说明总体空间有问题
若YGC过于频繁,疑点元区和存活分区分配有问题,默认还好,存活区占用很小,1.0分区很大,说明失衡了,增加1.0区大小,减少存活区的大小

用于二进制软件包
JAVA_OPS选项定义在脚本首部即可
JAVA_HOME 指定JAVA家目录

tomcat配置语法检查 configtest

posted @ 2021-09-08 10:43  Final233  阅读(298)  评论(0编辑  收藏  举报