版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1 前言Tomcat、Jetty、GlassFish 等等这系列 Web容器/应用服务器,虽然做为容器,提供的是一个 Java Web 的运行时环境,以支持Servlet/JSP 等等这些内容的运行,但我们都很清楚,其本质上还是一个 Java 应用程序。 每次对于 容器的启动运行,都是把这个 Java 程序跑起来,来实现 Web 容器的能力。做为一类“特殊”的 Java 应用程序,和任务其他的 Java 应用一样,需要使用到JVM,会有堆,会使用到垃圾回收,会涉及到不同的堆分区比例. 因此在对Web 容器( 应用服务器) 的调优中必不可少的是对于 JVM 的调优。对于 JVM 的调优,主要有两
2、个方面考虑:l 内存大小配置l 垃圾回收算法选择当然,确切的说,以上两点并不互相独立,内存的大小配置也会影响垃圾回收的执行效率。其中内存大小配置,最主要做的有l 确定内存占用的总大小l 确定内存中各个代(Gen) 的大小划分其它说明:1)堆(Heap)和非堆(Non-heap)内存 按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。 可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人
3、员使用的;非堆就是JVM留给自己用的, 所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。2)tomcat内存溢出Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,轻微时,会使系统性能急剧下降,严重时,将导致系统无法运行,影响系统的稳定性。当内存不够用时,常见的问题就是报tomcat内存益处错误,从儿导致客户端包500错误的,如下:解决方法主要是加大TOMCAT可利用内存,并在程序当中加大内存使用。因此根据应用的需求,有必要调整JVM使用内存的大小。2 内
4、存大小配置所谓内存大小的占用,是指应用程序启动后稳定运行一小段时间时,观察到的内存占用情况。以 HotSpot 虚拟机为例,Java 堆主要有三个空间:新生代、老年代和永久代。 根据不同应用的特别,观察应用对于内存的占用,如果有大量的临时对象,不会重复使用,则可以调整 New Gen, 这样这些临时对象就在新生代创建完成,并在 Minor GC 产生时被回收,这样较短生存活的对象不会晋升到老年代,从而可以避免垃圾堆集产生 Full GC。 理想状态下,短期存活的对象都只在新生代完成生命周期,被费时劲少的Minor GC 回收完成,而长期存活,将会多次使用的在多次回收之后晋升到老年代, 最终经过
5、 Full GC 完成生命周期。这里涉及到关于内存大小的调整参数有:-Xms-Xmx这两个参数用于配置 heap 的起始大小和最大值。这里需要经过观察,找一个合适的值,设置太大会导致内存浪费,同时也会导致垃圾回收耗时太长。对于 Tomcat 来说,一般都会将初始值和最大值设置为相同值,这样就避免在初始内存不足时触发 Full GC 来进行扩展内存。设定 heap 大小之后,要根据对象生命周期的特征,来调整新生代与老年代的大小比例。涉及到的参数有:-XX:NewSize #直接指定新生代堆内存初始大小-XX:NewRatio #设置新生代所占比例 方式-XX:MaxNewSize-Xmn第一个是
6、直接设置新生代初始大小,第二个是设置比例(Ratio)。太高或太低都会导致 GC 不能高效的工作。毕竟 Minor GC 也是要耗时的。最后一个设置新生代的初始值和最大值相同,堆空间的变化不影响其值。对于使用了大量第三方类库的应用来说,会加载许多框架依赖的类,使用过程中可能会遇到因为Perm Gen 不足产生的 OOM,这种情况可以通过观察稳定状态下 Perm 区的占用,再通过参数设置。-XX:PermSize-XX:MaxPermSize-XX:MaxMetaspaceSize第一个会设置Perm(永生代)区的初始大小,第二个用于设置Perm 区的最大值。在Java 8的时候,Perm 区被
7、移除,改为Metaspace,不过如果遇到类似的OOM,依然可以调整其大小。此外,对于使用大量线程的应用,也可以配置 -Xss,主要用于设置单个线程的stack 大小。注意,是单个的大小,因此设置值越大,会占用越大,可用的线程数也就越少。这里的配置一般对于-X开始的可以直接在后面用数字加单位,而-XX的则需要等号后数字再加单位,例如:java -Xms100m -Xmx200m -XX:PermSize=300m这里数字后的单可以是m,g,k代表计算机中的不同单位。3 垃圾回收算法不同的垃圾回收算法,对于应用的影响很大。一方面可能在一个服务器上却使用了单线程的回收算法,也可能应用对于响应要求很
8、高,但却使用了一个吞吐量优先的算法,导致响应太慢。所以对于垃圾回收算法的选择,一般都是根据应用的特点,是要低延迟还是高吞吐量,选择合适的算法。我们前面也提到,垃圾回收算法和内存的大小配置并非独立的,内存设置大是回收的频率会降低,但每次的执行时间也会变长。所以这里也是一个需要权衡的地方。l 延迟、吞吐量调优l 其他 JVM 配置垃圾回收算法对应到的就是不同的垃圾收集器,具体到在 JVM 中的配置,是使用 -XX:+UseParallelOldGC 或者 -XX:+UseConcMarkSweepGC 这种不同的收集器来达到选择算法的目的。其中 ParallelGC 也称为 吞吐量优先收集器,可以
9、提升应用的吞吐量,但在老年代大小调整之,进行几次垃圾回收后,不能满足应用的低延迟要求。一般常用到ConcMarkSweepGC, 也称之为 CMS GC,其可以做到老年代的垃圾回收与应用程序的纯种并行执行,所以可以实现低延迟。这里注意,由于 CMS GC 和其他GC回收算法使用的框架不同,因此不能混用,在使用CMS 进行老年代回收时,新生代默认使用了单线程回收算法,此时可以通过配置 -XX:+UseParNewGC来使用 新生代并行回收。由于CMS是垃圾回收和应用线程并行,因此需要额外的CPU处理资源,如果只有一个CPU的机器,或者有多个忙碌的CPU,又想要使用低延迟的收集器,此时可以通过配置
10、 CMS 收集器的增量模式来进行回收,通过指定 -XX:+CMSIncrementalMode 来开启增量模式。此时交替运行垃圾收集器应用线程。通过配置 -XX:CMSIncrementalSafetyFactor=X, -XX:CMSIncrementalDutyCycleMin=Y,-XX:CMSIncrementalPacing 可以控制垃圾收集后台线程为应用线程让出多少CPU周期。参数-XX:+CMSParallelRemarkEnabled 用来降低标记停顿,另外由于CMS 回收后的老年代内存空间并不是连续的,因此通过参数-XX:+UseCMSCompactAtFullCollect
11、ion 在Full GC的时候对年老代的压缩。在JDK1.7 的时候引入了 G1 收集器,可以通过配置-XX:+UseG1GC 来开启。这一方面的实战经验不多,有相关使用经验的朋友欢迎分享。此外,还可以对新生代进行更细致的配置,比如设置Eden 和 Suvivor 区的比例等,和Newxx类似,可以通过SuvivorRation设置比例。4 参数调整说明Windows环境: tomcat安装目录bincatalina.bat我们来看catalina.sh中实际启动时执行的命令:所以我们的选项可以加到 JAVA_OPTSCATALINA_OPTS这些可选项中。配置比较简单,例如下面这样:配置的时
12、候需要特别注意的是,不要把前面已经有的配置冲掉,比如在配置JAVA_OPTS的时候,要把前面已经配置的加上,写起来是这样:JAVA_OPTS="$JAVA_OPTS 新增的内容"Ø 建议的修改Windows环境: tomcat安装目录bincatalina.bat文件中找到下面行set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%这行下面前面加上JAVA_OPTS='-Xms1024m -Xmx1024m'说明:这两个参数用于配置 heap(堆) 的起始大小和最大值。这里需要经过观察,找一个合适的值,设置太大会导致内
13、存浪费,同时也会导致垃圾回收耗时太长。对于 Tomcat 来说,一般都会将初始值和最大值设置为相同值,这样就避免在初始内存不足时触发 Full GC 来进行扩展内存。JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=64M -XX:MaxPermSize=256m"说明:这两个-XX:PermSize=64M -XX:MaxPermSize=256m 指定类空间(用于加载类)的内存大小5 堆内存分析工具那我们前面一直在说根据不同的应用,观察分析设置堆的大小,堆的各个代的大小,那具体观察什么呢?我们一般在JVM的配置中增加一些打印 GC 日
14、志的选项,配置方式和上面的类似,这样在 GC 产生时,会打印出各个代占用的大小,具体触发时间等。推荐的配置有以下几个:-XX:+PrintGCTimeStamps-XX:+PrintGCDetails-Xloggc:<文件名>-XX:PrintGCDateStamps第一个和第四个选项可以任选一个,第一个打印自JVM启动以来的时间,一般也称为uptime, 第四个打印的是系统当前日期和时间。根据 GC 日志产生的内容,来观察具体的大小,开始使用上述的配置参数进行调整。当然,也可以用 JConsole, JVisual VM 这些工具可视化的进行了解再调整。5.1 JVisual V
15、MJAVA JDK自带的一款可视化的 Java VM 应用分析工具。首先到JDK安装目录/bin目录下,双击jvisualvm.exe文件启动,启动后是这个样子:分本地和远程两种,罗列了当前的 JVM 进程。 远程的进程是通过 JMX 进行连接,有一些本地的 Profile 功能不支持。我们以本地进程为例,来介绍下Visual VM 常见功能。双击要分析的 JVM 进程,在打开的 Tab 中选择功能,默认会显示概述、监视、线程、抽样器和 Profiler 这几项。由于Visual VM 实现和 NetBeans 一致,所以可以通过插件的方式,增加许多功能。在【工具】菜单,选择【插件】,打开下图
16、,然后选择要安装的插件,也可以将插件下载到本地再安装。格式是一个扩展名为nbm类型的文件。像我们稍后要介绍的Visual GC, BTrace 都是通过插件安装,来增加对应功能的。5.1.1 概述在概述这个 Tab 中,会有当前 JVM 进程的一些基本信息,包含 JVM的参数,系统属性,Main-class 等等。类似如下图:请注意上图红框,这个是一般启动时配置的一个JVM选项,可以在 OOM 产生时生成一个堆的 dump,方便事后分析。如果没有在启动时配置,默认是关闭的。这里也显示是禁用。通过 Visual VM,可以实时变更该选项,右击对应的 JVM 进程,在弹出菜单中选择【在出现OOME
17、时生成堆 Dump】5.1.2 监视在该 Tab 中会显示 CPU,堆的使用,已装入的类的情况,以及线程的活动情况等。关键是这里有两个按钮【执行垃圾回收】和【堆 Dump】。垃圾回收会进行一次 Full GC,堆的Dump会生成一个当前的dump文件供分析。线程线程 Tab 会将当前进程的所有线程按时间线的形式开出来。可以根据不同的线程状态进行查看。这里还可以进行线程的 Dump,和 jstack 功能一致,生成一个所有线程的运行调用图。(jstack,可以查看前面的文章了解。Java七武器系列霸王枪 - 线程状态分析 jstack)抽样器可以按照 CPU 和内存进行抽样, 和Profiler
18、类似,我们后面介绍。Profiler在众多功能中,该功能可用于进行应用的 Profiling,分析应用方法的占用时间,内存中各个类的对象数量及大小等。下方的图是CPU profiling,分析方法的执行时间。这张图是内存的 profiling,显示对象在内存中的数量及大小通过这两种 profiling,对于应用中有内存占用较多的情况发生时,可以观察是哪些对象占用,是否有些代码中存在的总是导致生成的大量无用的对象等。这两个功能和工具 MAT 的几个功能类似。5.1.3 Visual GC-重要插件下载:https:/visualvm.github.io/uc/release139/updates
19、.html注意:该 Tab 需要安装插件后才能显示。一直以来,Java 的 GC 对于我们来说只能通过在命令行中展示的方式,或者是从 gc log 里查看一些 执行情况,Visual VM 的 Visual GC 插件,可以让我们更直观的观察 堆的占用,GC 的执行情况等,是个可视化的GC 查看工具。通过这个工具,能够观察堆各个区域的大小,占用情况等。比如在配置了Xms, PermSize, 或者一些 xxxRation之类的,具体分到各个代的大小是多少,除了计算之外,可以在这里直观的查看。同时,在每个每个 Gen 旁边,都有显示 GC 的执行次数和时间。上图说明:一、整个区域分为三部分:sp
20、aces、graphs、histogram1、spaces区域代表虚拟机内存分布情况。从图中可以看出,虚拟机被分为Perm、Old、Eden、S0、S11.1)perm:英文叫做Permanent Generation,我们称之为永久代。(根据深入java虚拟机作者说明,这里说法不是不是很正确,因为hotspot虚拟机的设计团队选择把GC分代收集扩展至此而已,正确的应该叫做方法区或者非堆)。1.1.1)通过VM Args:-XX:PermSize=128m -XX:MaxPermSize=256m 设置初始值与最大值1.2)heap:java堆(Java heap)。它包括老年代(图中Old区
21、域)和新生代(图中Eden/S0/S1三个统称新生代,分为Eden区和两个Survivor区域),他们默认是8:1分配内存1.2.1)通过VM Args:-xms512m -Xmx512m -XX:+HeapDumpOnOutofMemoryError -Xmn100m -XX:SurvivorRatio=8 设置初始堆内存、最大堆内存、内存异常打印dump、新生代内存、新生代内存分配比例(8:1:1),因为Heap分为新生代跟老年代,所以512M-100M=412M,老年代就是412M(初始内存跟最大内存最好相等,防止内存不够时扩充内存或者Full GC,导致性能降低)2、Graphs区域内
22、存使用详细介绍2.1)Compile Time(编译时间):6368compiles 表示编译总数,4.407s表示编译累计时间。一个脉冲表示一次JIT编译,窄脉冲表示持续时间短,宽脉冲表示持续时间长。2.2)Class Loader Time(类加载时间): 20869loaded表示加载类数量, 139 unloaded表示卸载的类数量,40.630s表示类加载花费的时间2.3)GC Time(GC Time):2392collections表示垃圾收集的总次数,37.454s表示垃圾收集花费的时间,last cause表示最近垃圾收集的原因2.4)Eden Space(Eden 区):括
23、号内的31.500M表示最大容量,9.750M表示当前容量,后面的4.362M表示当前使用情况,2313collections表示垃圾收集次数,8.458s表示垃圾收集花费时间2.5)Survivor 0/Survivor 1(S0和S1区):括号内的3.938M表示最大容量,1.188M表示当前容量,之后的值是当前使用情况2.6)Old Gen(老年代):括号内的472.625M表示最大容量,145.031M表示当前容量,之后的87.031表示当前使用情况,79collections表示垃圾收集次数 ,28.996s表示垃圾收集花费时间2.7)Perm Gen(永久代):括号内的256.00
24、0M表示最大容量,105.250M表示当前容量,之后的105.032M表示当前使用情况3、Histogram区域survivor区域参数跟年龄柱状图3.1)Tenuring Threshold:表示新生代年龄大于当前值则进入老年代3.2)Max Tenuring Threshold:表示新生代最大年龄值。3.3)Tenuring Threshold与Max Tenuring Threshold区别:Max Tenuring Threshold是一个最大限定,所有的新生代年龄都不能超过当前值,而Tenuring Threshold是个动态计算出来的临时值,一般情况与Max Tenuring Th
25、reshold相等,如果在Suivivor空间中,相同年龄所有对象大小的总和大于Survivor空间的一半,则年龄大于或者等于该年龄的对象就都可以直接进入老年代(如果计算出来年龄段是5,则Tenuring Threshold=5,age>=5的Suivivor对象都符合要求),它才是新生代是否进入老年代判断的依据。3.4)Desired Survivor Size:Survivor空间大小验证阙值(默认是survivor空间的一半),用于Tenuring Threshold判断对象是否提前进入老年代。3.5)Current Survivor Size:当前survivor空间大小3.6)
26、histogram柱状图:表示年龄段对象的存储柱状图3.7)如果显示指定-XX:+UseParallelGC -新生代并行、老年代串行收集器 ,则histogram柱状图不支持当前收集器Visual GC插件安装离线安装,下载插件工具à插件,切换到“已下载”,添加插件,选择下载的nbm文件 18 / 18后台117 80端口tomcat5.1.4 堆Dump生成堆dump之后,相当于对当前的堆做了一个镜像,可以基于此分析应用内的一些问题。整个dump中,除了摘要外,还有类,实例数等和 Profiler 中实时内容一致。此外,还包含线程的 stackTrace。在类中双击任意一个要关注
27、的,会打开实例数视图,显示该类对应的各个实例的数据5.1.5 远程监控tomcat1)在服务器上配置 jstatd 的 security policy 文件“远程” 项下列出的远程主机上的 Java 程序的资源占用情况,但需要在远程主机上运行 jstatd 守护程序。jstatd是一个监控 JVM 从创建到销毁过程中资源占用情况并提供远程监控接口的 RMI ( Remote Method Invocation ,远程方法调用)服务器程序,它是一个 Daemon 程序,要保证远程监控软件连接到本地的话需要 jstatd 始终保持运行。 jstatd运行需要通过 -J-Djava.security
28、.policy=* 指定安全策略,因此我们需要在服务器上建立一个指定安全策略的文件 jstatd.all.policy ,文件内容如下:grant codebase "file:$java.home/./lib/tools.jar" permission java.security.AllPermission; ;2)修改服务器 hosts 文件中的 IP 地址 要使Java VisualVM 成功连接到远程服务器上,服务器端应该在 /etc/hosts 文件中把本机地址设为本机的 IP 地址。使用 hostname -i 命令查看,如果显示的是 或者与
29、本机实际 IP 不一致的话,需要把 /etc/hosts 文件中相应的地址改为本机实际 IP 。 3)运行 jstatd 守护程序 由于 jstatd 需要保持一直运行,所以建议使用 screen 命令执行 jstatd 程序,命令如下:screen jstatd -J-Djava.security.policy=jstatd.all.policy6 其它说明6.1 服务启动时参数不生效很多人修改后,发现修改并没有起作用,即通过windows的服务启动tomcat时,实际的内存还是默认的,修改的设置并没有起作用;而通过<CATALINA_HOME>binstartup.bat 启动
30、却是生效的。这是为什么呢?因为在安装过程中,JVM的初始化参数已经写在注册表中了,由于没有修改注册表中相关参数,所以以windows服务方式启动时,修改的并没有生效。而通过<CATALINA_HOME>binstartup.bat 启动直接是通过<CATALINA_HOME>bincatalina.bat文件中的配置的。你需要重新加载到系统服务中才生效,或者你手工在注册表中查找修改启动值,加载到服务中的时候参数已经配置好了,自己修改startup.bat不会改变注册表中的参数设置。解决方法:修改注册表中的参数,加入JVM初始化内存的参数:HKEY_LOCAL_MACHINESOFTWAREApache Software FoundationTomcat Service ManagerTomcat5ParametersJavaOptions值为-Dcatalina.home="C:ApacheGroupT
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年雅安职业技术学院单招职业适应性测试题库含答案详细解析
- 2026年成都艺术职业大学单招职业适应性测试题库带答案详细解析
- 2026年四川体育职业学院单招综合素质考试题库及答案详细解析
- 2026年花卉租赁合同
- 2026年流量计检定合同
- 2026年财产保全申请书
- 第三节 信息搜索和文件下载教学设计初中信息技术甘教版2011七年级上册-甘教版2011
- 2025-2026学年数学对教学设计进行分析
- 2025-2026学年高中数学教学设计例题
- 2025-2026学年树干拼音教学设计
- 2026年滁州职业技术学院单招综合素质考试题库附答案详解
- 2026春统编版三年级下册道德与法治每课知识点清单
- 2025年建筑安全员c2考试题及答案
- 2025中国国新控股有限责任公司招聘7人笔试历年常考点试题专练附带答案详解
- 东北三省三校2026年高三下学期高考第一次联合模拟考试政治试卷
- 2026秋招:平安银行笔试题及答案
- 2026年六安职业技术学院单招职业适应性考试题库附参考答案详解ab卷
- 2026广东江门职业技术学院管理教辅人员招聘4人备考题库带答案详解(基础题)
- 货梯使用专项安全培训课件
- (2025版)国家基层高血压防治管理指南2025版课件
- 女职工安全教育培训内容课件
评论
0/150
提交评论