tomcat 8 jvm 优化

jvm 的内存结构

jvm 是按照运行时数据的存储结构来划分内存结构的,jvm在运行java 程序时,将他们划分成几 种不同格式的数据,分别存储在不同的区域,这些数据统一称为运行时数据。运行时数据包括java 程序本身的数据信息和jvm运行java 需要额外的数据信息。

jvm 运行时数据区

程序技术器-----线程私有

java 虚拟机栈--线程私有

本地方法栈-----线程私有

java堆----------线程公用

方法区----------线程公用

jvm 内存分配

保存参数、局部变量、中间计算过程和其他数据,退出方法的时候,修改栈顶指针就就可以把栈帧中的内容销毁。

栈的优点:存取数据比堆快,仅此与寄存器,栈数据可以共享

栈的缺点:存在栈中的数据大小,生存期是在编辑时就确定的,导致其缺乏灵活性。

-Xss 每个线程使用的内存

堆的有点:动态地分配内存大小,生存期不必事先告诉编辑器,它是在运行期动态动配分配的垃圾回收器会自动收走不在使用的空间区域

堆内存机构如下图:

年轻代:有eden 区和from 、to 组成,可以是说是e 区s1 s2 区之间的工作模式是开始线程全部进入eden 区域会后会通过copy 工作模式把需要的线程copy 到s1 或者s2 区域所有通过new 创建的对象内存都在堆中分配。其大小可以通过-Xms -Xmx 来控制,堆被划分为新生代和旧生代,新生代又被进一步划分为Eden 和Suruvivor 最后和Survior由formspace 和tospace 组成。

老年代大小=堆内存-新生代-持久带 因为老年代没有参数可控制所以新生态越大老年代越小。

java 堆结构和垃圾回收

说明:Non-Heap 是非堆内存信息

Heap 堆内存信息也是新生代信息

jvm 堆配置参数

1、-Xms 初始化堆内存大小  默认是物理内存的1/64 (<1GB)

2、-Xmx 最大的堆大小 默认是物理内存的1/4(1<1GB),实际中建议大于4Gb

3、一般建议设置-Xms=-Xmx 好处是避免每次gc 后调整堆内存大小,减少系统内存分配的开销

4、整个堆大小=年轻代大小+老年代大小+持久代大小

jvm 新生代(young generation)

1、新生代=1和ede区 和两个subrvivor区

2、-Xmn 年轻代大小(1.4版本之前通过 -xx:NewSize ,-XX:MaxNewSize)

3、-XX:NewRatio

年轻代与老年代的比值(除去持久代)

Xms=Xmx 并且设置了Xmn 的情况下,该参数不需要进行设置

4、-XX:SurvivorRatio

Eden区与Survivor区的大小比值,设置为8,则两个Survivor 区与一个eden 区比值为2:8 Survivor区占整个年轻代的1/10

5、用来存放java 对象刚分配的java 对象

jvm 老年代(teunred geneation)

1、老年代=整个堆-年轻代大小-持久代大小

2、年轻代中经过垃圾回收没有回收掉的对象被复制到老年代

3、老年代存储对象比年轻代年龄大的多,而且不缺乏大对象

4、新建的对象也有可能直接进入老年代

4.1 大对象,可以通过启动参数设置-XX:PretenureSizeThreshold=1024(单位字节,默认为0)来代表超过多大时就不再新生代分配。而是直接在老年代分配

4.2 大的数组对象,切数组中无引用外部对象

java 强引用 java 弱引用
不会丢失数据,所以访问速度快
线程开启,停止服务也没有办法回收线程除非重启系统
同时如果线程数到达java 设定的而无法进行处理那么
服务就会冗机
丢失数据,会去数据库读取数据会慢一些,如果eden区和s1 、s2 到old 区50M 如果old区缓存为40M在理想
的情况下正常数据从eden s1 s2 区到old 过来的数据不会超过1M 假如:老年代缓存为50M 这是空闲空间为5M
这时如果从新生代过来的数据超过5M 那么系统会直接回收所有的空间,用来存放新的数据,缓存的数据会读取数
库,如果是强引用系统就会挂掉。

5、老年代大小无配置参数

java 持久代(perm generation)

1、持久代=整个堆-年轻代大小-老年代大小

2、-XX:PermSize -XX:MaxPermSize

设置持久代的大小,一般情况推荐把-XX:PermSize设置成-XX:MaxPermSize的值为相同的值,因为持久代大小的调整也会导致堆内存需要发出fgc

3、存放Class、Method元信息,其大小与项目的规模;类、方法的数量有关,一般设置为128M 就足够了,设置原则是预留30% 的空间。

4、永久代的回收方式

4.1、常量池中的常量,无用的类信息、常量的回收很简单、没有引用了就可以被回收

4.2、对于无用的类进行回收。必须保证3点:

类的所有实列都已经被回收

加载类的class loader 已经回收

类对象的class对象没有被引用(即没有通过发射引用该类的地方)

jvm 垃圾收集算法

1、引用计数算法

每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0 可以收回,次方法简单无解决对象相互循环引用的问题,还有一个问题是如果解决精准计数

2、根据搜索算法

从GC Rots 开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GCRoots 没有任何引用链相连时,则证明此对象是不可用,不可到达对象

在java 语言中,GCRoots 包括

虚拟机中引用的对象

方法区类静态属性实体引用的对象

方法区类静态属性实体引用的对象

方法区常量引用的对象

本地方法栈中JNI 引用的对象

jvm 垃圾回收算法

复制算法(copying)

标记清除算法(Mark-weep)

标记整理压缩算法(Mark-Compac)

以下是重点*****

名词解释

1、穿行回收

gc 单线程内存回收,会暂停所有用户线程

2、并行回收

手机是指多个gc 线程并行工作,但此用户线程是暂停,所有sebul 是串行的,parallel (并行)收集器是并行的而cms 收集器是并发的

3、并发回收

是指用户线程同时执行(不一定是并行可能是交替,但总体上在同时执行的)不需要停顿用户线程,(其实在cms 中用户线程还是需要停顿的,只是非常短,GC线程在另一个CPU 上执行)

穿行 并行 并发 ****G1 不使用

新生代Serial 回收器

1、-XX:+UseSerialGC来开启 Serial New + Serial Old 的收集器组合进行内存回收

2、使用复制算法。

3、独占式的垃圾回收

缺点:一个线程进行GC 穿行。其他工作线程暂停

老年代Serial 回收器

1、-XX:+UseSerialGC 来开启Serial New+Serial Old 的收集器组合进行内存回收

2、使用标记--压缩算法

3、串行的、独占式的垃圾回收器

因为内存比较大原因,回收比新生代慢

新生代ParNew 回收器

1、-XX:+UseParNewGC 开启新生代使用并行回收收集器,老年代使用串行收集器

2、-XX:ParallelGCThreads 指定线程数默认最好与CPU数量相当,避免过多的线程数影响垃圾收集性能

3、使用复制算法

4、并行的、独占式的垃圾回收器

新生代Parallel Scavenge 回收器

1、吞吐量优先回收器

关注CPU 吞吐量,即运行用户代码的时间/总时间,比如:JVM 运行100分钟,其中运行用户代码99分钟,垃圾收集1分钟,则吞吐是99%,这种收集器能最高效率的利用CPU,适合运行后台运算

2、-XX:UseParallelGC 开启

使用Parallel Scaveng+Serial Old 收集器组合回收垃圾,这也是在Server 模式下的默认值

3、-XX:GCTimeRatio

来设置用户执行时间占总时间的比例,默认99 即1%的时间用来进行垃圾回收

4、-XX:MaxGGFCPauseMilllis

设置GC的最大停顿时间

5、使用复制算法

老年代Parallel Old 回收器

1、-XX:+UseParallel Old 组合收集器进行收集

2、使用标记整理算法

3、并行的、独占式的垃圾回收器

******互联网公司所用

cms (并发标记清楚)回收器

1、标记-清楚算法

同时他又是一个使用多线程并发回收的垃圾收集器

2、-XX:ParallellCMSThreads

手工设定cms 的线程数量,cms 默认启动线程数是(ParallelGCThreads+3/4)

3、-XX+UseConcMarkSweepGC 开启

使用ParNew+CMS+Serial Old 的收集器组合进行内存回收,Serial Old 作为CMS出现“Concurrent Mode Failure”失败后的后备收集器使用

4、-XX:CMSInitiatingOccupancyFraction

设置CMS 收集器在老年代空间被使用多少后触发垃圾收集,默认值为68%,仅在cms收集器时有效-XX:CMSInitiatingOccupancyFraction=70

5、-XX:+UseCMSCompactAtFullCollection

由于CMS 收集器会产生碎片,此参数设置在垃圾收集器后是否需要一次内存碎片整理过程,仅在CMs 收集器有效时有效

6、-XX:+CMSFullGCBeforeCompaction

设置CMS 收集器进行若干次垃圾收集后在进行一次内存碎片整理过程,通常与UserCMSCompactAtFullCollection参数一起使用

7、-XX:+CMSInitiatingPermOccupancyFraction

设置perm Gen 使用到达多少比率时触发,默认是92%

下面是生产例子:(需要根据实际情况部署)

[[email protected] bin]# cat setenv.sh 
#!/bin/sh
export JAVA_HOME=/usr/local/jdk1.7.0_60/
export JRE_HOME=/usr/local/jdk1.7.0_60/
JAVA_OPTS="-server
-Xms5G                                                             ## 堆内存初始值              
-Xmx5G                                                             ##堆内存最大值
-Xmn2G                                                             ##新生代空间
-Dsun.java2d.noddraw=true                              ##如果硬件加速已经被enable,可以通过这个选项来提高Swing GUI速度,默认值为false
-XX:PermSize=500M                                         ## 表示非堆区初始内存分配大小,其缩写为permanent size(持久化内存)                            
-XX:MaxPermSize=500M                                  ##-XX:MaxPermSize:表示对非堆区分配的内存的最大上限。                            
-Xss256k                                                           ##设置每个线程的堆栈大小
-XX:MaxTenuringThreshold=0                          ##在新生代中对象存活次数(经过MinorGC次数)后仍然存活,就会晋升到旧生代
-XX:+UseParNewGC                                        ##设置年轻代多线程收集,可与CMS 收集同时使用。在serial 基础上实现的多线程收集器 
-XX:+UseConcMarkSweepGC                          ##并发标记清楚(CMS)收集器:cms 收集器 也被称为短暂停顿并发收集器。它是对年老代进行垃圾收集的。因为是多线程进行垃圾收回,可与减少停顿时间
-XX:+UseCMSCompactAtFullCollection           ## 表示触发FGC 之后进行压缩,因为CMS 默认不压缩空间的
-XX:CMSFullGCsBeforeCompaction=0            ##,在上一次CMS并发GC执行过后,到底还要再执行多少次full GC才会做压缩。默认是0,也就是在默认配置下每次CMS GC顶不住了而要转入full GC的时候都会做压缩。 把CMSFullGCsBeforeCompaction配置为10,就会让上面说的第一个条件变成每隔10次真正的full GC才做一次压缩(而不是每10次CMS并发GC就做一次压缩,目前VM里没有这样的参数)。这会使full GC更少做压缩,也就更容易使CMS的old gen受碎片化问题的困扰。
-XX:+CMSClassUnloadingEnabled                  ##如果你启用了CMSClassUnloadingEnabled ,垃圾回收会清理持久代,移除不再使用的classes。这个参数只有在 UseConcMarkSweepGC  也启用的情况下才有用
-XX:-CMSParallelRemarkEnabled                    ##降低标记停顿  表示并行remark           
-XX:CMSInitiatingOccupancyFraction=90         ##使用cms作为垃圾回收,使用70%后开始CMS收集,为了保证不出现promotion failed(见下面介绍)错误
-XX:SoftRefLRUPolicyMSPerMB=0                  ##在最后一次引用时,软可达对象将保持一定的时间 等待多少秒
-XX:LargePageSizeInBytes=128M                   ##设置用于Java堆的大页面尺寸
-XX:+UseFastAccessorMethods                       ##原始类型的快速优化
-XX:+UseCMSInitiatingOccupancyOnly            ##使用手动定义初始化定义开始CMS收集
-XX:+PrintClassHistogram                                ##在垃圾收集之前执行
-XX:+PrintGCDetails                                         ##GC 输出
 -XX:+PrintGCTimeStamps                               ##GC 输出
 -XX:+PrintHeapAtGC                                       ##打印GC前后的详细堆栈信息
-Xloggc:${CATALINA_HOME}/logs/gc.log"       ##把相关日志信息记录到文件以便分析.与上面几个配合使用
时间: 2024-10-06 04:44:17

tomcat 8 jvm 优化的相关文章

Tomcat的JVM优化

一.JVM管理内存段分类 1.线程共享内存 方法区:存储jvm加载的class.常量.静态变量.及时编译器编译后的代码等 java堆:存储java所有对象实例.数组等 2.线程私有内存 程序计数寄存器:每个线程有自己的计数寄存器,存储当前线程执行字节码的地址 jvm栈:jvm会为每个运行线程分配一个栈区,线程调用方法时和方法返回时会进行入栈和出栈操作 本地方法栈区:与jvm stack类似,只不过此区域是为调用本地方法服务 二.各参数代表的意义 -Xms:堆内存空间的初始大小 -Xmx:堆内存的

Tomcat调优总结(Tomcat自身优化、Linux内核优化、JVM优化)

Tomcat自身的调优是针对conf/server.xml中的几个参数的调优设置.首先是对这几个参数的含义要有深刻而清楚的理解.以tomcat8.5为例,讲解参数. 同时也得认识到一点,tomcat调优也受制于linux内核.linux内核对tcp连接也有几个参数可以调优. 因此我们可以将tomcat调优分为linux内核优化.java虚拟机调优和tomcat自身的优化. 一.Tomcat自身优化 1. maxThreads :tomcat创建的最大线程数,也就是同时处理的请求最大并发数.默认值

java tomcat jvm优化

tomcat执行器(线程池)的优化 tomcat默认是没有启用线程池的,在tomcat中每一个用户请求都是一个线程,所以我们可以使用线程池来提高性能.tomcat的前段有一个调度线程,会将用户的请求放入线程池中,一定时间后线程池中的用户请求任务就变为工作线程. 1.开启线程池:打开server.xml中关于线程池的配置 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThread

tomcat生产环境优化

使用下面几步来提高Tomcat服务器的性能. 增加JVM堆内存大小 修复JRE内存泄漏 线程池设置 压缩 数据库性能调优 Tomcat本地库 其它选项 1.JVM优化 在Tomcat 的启动脚本 catalina.sh中添加如下的启动参数:    JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m   -XX:NewSize=512m -XX:MaxNewSize=512m -

Tomcat(JVM)性能调优

Tomcat架构图 Tomcat与JVM版本优化Tomcat的运行是基于Java的虚拟机.SUN的JVM动态库有client和server两个版本,分别针对桌面应用和服务器应用做了相应的优化,client版本加载速度较快,server版本加载速度较慢但运行起来较快.在命令行输入 java -version 可以看到jvm目前配置的是哪个版本.如果要修改jvm的版本,可更改默认java.exe调用的jvm.dll,这个由jvm.cfg决定.编辑%JAVA_HOME%/jre/lib/i386/jv

Tomcat中JVM内存溢出及合理配置(转)

Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对Java JVM有关内存方面的知识进行详细介绍. 一.Java JVM内存介绍 JVM管理两种类型的内存,堆和非堆.按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的.""在JVM中堆之外的内存称为非堆内存(Non-heap

Tomcat 内存与优化篇

Tomcat 内存与优化一.Tomcat 运行环境介绍 1.Tomcat 本身无法直接在计算机上运行,需要依赖硬件基础上的操作系统和Java虚拟机: 2.Java 程序启动时JVM都会分配一个初始内存和最大内存给这个应用: 3.当应用程序用到最大内存的时刻,就会触发JVM做垃圾回收(GC)动作,释放被占用的内存: 4.因此想要调整Java程序启动时的初始内存和最大内存,需要向JVM申请: 5.如果初始内存大小设置过小,且此时初始化的应用对象过多,虚拟机就必须重复的加载内存来满足使用: 6.基于以

转 设置Tomcat的JVM内存大小

设置Tomcat的JVM内存大小 2011-11-21 10:19:05|  分类: Tomcat |  标签:tomcat  jvm  |举报|字号 订阅 Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个JVM.JAVA程序启动时JVM都会分配一个初始JVM内存和 最大JVM内存给这个应用程序.这个初始内存和最大内存在一定程度都会影响程序的性能.比如说在应用程序用到最大内存的时候,JVM是要先去做垃圾回收的 动作,释放被占用的一些内存.所以想调整Tomcat的启动

【Tomcat】Tomcat配置JVM参数步骤

这里向大家描述一下如何使用Tomcat配置JVM参数,Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个java虚拟机.您可以选择自己的需要选择不同的操作系统和对应的JDK的版本,但还是推荐您使用Sun公司发布的JDK. Tomcat配置JVM参数 Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个java虚拟机.您可以选择自己的需要选择不同的操作系统和对应的 JDK的版本(只要是符合Sun发布的Java规范的),但我们推荐您使用Sun公司