启动过程:html
经过bin目录下的startup.bat来启动tomcat,startup.bat又调用了catalina.bat,catalina.bat从命令行启动org.apache.catalina.startup.Bootstrap,这个类有main方法,因此能够从命令行执行。java
Bootstrap执行后,首先执行init()方法进行初始化,而后调用load()和start()方法web
查看服务器内存:apache
cat /proc/meminfo
一台服务器上跑三个tomcat:数组
服务器内存:1G缓存
三个tomcat参数优化配置:tomcat
每一个tomcat均匀分配:服务器
maxThreads="200"app
catalina.sh(catalina.bat)添加:less
JAVA_OPTS="-server -Xms4096m -Xmx4096m -XX:PermSize=256M -XX:MaxNewSize=256m -XX:MaxPermSize=256m"
Tomcat自己不能直接在计算机上运行,须要依赖于硬件基础之上的操做系统和一个Java虚拟机。Tomcat的内存溢出本质就是JVM内存溢出,因此在本文开始时,应该先对Java JVM有关内存方面的知识进行详细介绍。
1、Java JVM内存介绍
JVM管理两种类型的内存,堆和非堆。按照官方的说法:“Java 虚拟机具备一个堆,堆是运行时数据区域,全部类实例和数组的内存均今后处分配。堆是在 Java 虚拟机启动时建立的。”“在JVM中堆以外的内存称为非堆内存(Non-heap memory)”。简单来讲堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给本身用的,因此方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每一个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中,它和堆不一样,运行期内GC不会释放其空间。
(1). 堆内存分配
JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。默认空余堆内存小于 40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减小堆直到-Xms的最小限制。所以服务器通常设置-Xms、 -Xmx相等以免在每次GC 后调整堆的大小。能够利用JVM提供的-Xmn -Xms -Xmx等选项可进行堆内存设置,通常的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值,建议堆的最大值设置为可用内存的最大值的80%。
初始化堆的大小是JVM在启动时向系统申请的内存的大小。通常而言,这个参数不重要。可是有的应用程序在大负载的状况下会急剧地占用更多的内存,此时这个参数就是显得很是重要,若是JVM启动时设置使用的内存比较小而在这种状况下有许多对象进行初始化,JVM就必须重复地增长内存来知足使用。因为这种缘由,咱们通常把-Xms和-Xmx设为同样大,而堆的最大值受限于系统使用的物理内存。通常使用数据量较大的应用程序会使用持久对象,内存使用有可能迅速地增加。当应用程序须要的内存超出堆的最大值时JVM就会提示内存溢出,而且致使应用服务崩溃。因此,若是Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操做系统的最大限制都会引发服务器启动不起来。
(2). 非堆内存分配
也叫永久保存的区域,用于存放Class和Meta信息,Class在被Load的时候被放入该区域。它和存放类实例(Instance)的Heap区域不一样,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理。JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。 GC不会对PermGen space进行清理,因此若是你的APP会LOAD不少CLASS的话,就极可能出现PermGen space错误。
(3). JVM内存限制(最大值)
首先JVM内存限制于实际的最大物理内存(废话!,呵呵),假设物理内存无限大的话,JVM内存的最大值跟操做系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,可是具体的操做系统会给一个限制,这个限制通常是2GB-3GB(通常来讲Windows系统下为1.5G-2G,Linux系统 下为2G-3G),而64bit以上的处理器就不会有限制了。
2、三种内存溢出异常介绍
1. OutOfMemoryError: Java heap space 堆溢出
内存溢出主要存在问题就是出如今这个状况中。当在JVM中若是98%的时间是用于GC且可用的 Heap size 不足2%的时候将抛出此异常信息。
2. OutOfMemoryError: PermGen space 非堆溢出(永久保存区域溢出)
这种错误常见在web服务器对JSP进行pre compile的时候。若是你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。若是web app用了大量的第三方jar或者应用有太多的class文件而刚好MaxPermSize设置较小,超出了也会致使这块内存的占用过多形成溢出,或者tomcat热部署时侯不会清理前面加载的环境,只会将context更改成新部署的,非堆存的内容就会愈来愈多。
3. OutOfMemoryError: unable to create new native thread. 没法建立新的线程
这种现象比较少见,也比较奇怪,主要是和jvm与系统内存的比例有关。这种怪事是由于JVM已经被系统分配了大量的内存(好比1.5G),而且它至少要占用可用内存的一半。
3、Java JVM内存配置
1. JVM内存分配设置的参数有四个
-Xmx Java Heap最大值,默认值为物理内存的1/4;
-Xms Java Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值,开发测试机JVM能够保留默认值;
-Xmn Java Heap Young区大小,不熟悉最好保留默认值;
-Xss 每一个线程的Stack大小,不熟悉最好保留默认值;
-XX:PermSize:设定内存的永久保存区域;
-XX:MaxPermSize:设定最大内存的永久保存区域;
-XX:PermSize:设定内存的永久保存区域;
-XX:NewSize:设置JVM堆的‘新生代’的默认大小;
-XX:MaxNewSize:设置JVM堆的‘新生代’的最大大小;
2. 如何设置JVM的内存分配
(1)当在命令提示符下启动并使用JVM时(只对当前运行的类Test生效):
java -Xmx128m -Xms64m -Xmn32m -Xss16m Test
(2)当在集成开发环境下(如eclipse)启动并使用JVM时:
a. 在eclipse根目录下打开eclipse.ini,默认内容为(这里设置的是运行当前开发工具的JVM内存分配): -vmargs -Xms40m -Xmx256m -vmargs表示如下为虚拟机设置参数,可修改其中的参数值,也可添加-Xmn,-Xss,另外,eclipse.ini内还能够设置非 堆内存,如:-XX:PermSize=56m,-XX:MaxPermSize=128m。
b. 打开eclipse-窗口-首选项-Java-已安装的JRE(对在当前开发环境中运行的java程序皆生效) 编辑当前使用的JRE,在缺省VM参数中输入:-Xmx128m -Xms64m -Xmn32m –Xss16m。
c. 打开eclipse-运行-运行-Java应用程序(只对所设置的java类生效) 选定需设置内存分配的类-自变量,在VM自变量中输入:-Xmx128m -Xms64m -Xmn32m -Xss16m 注:若是在同一开发环境中同时进行了b和c设置,则b设置生效,c设置无效,如: 开发环境的设置为:-Xmx256m,而类Test的设置为:-Xmx128m -Xms64m,则运行Test时生效的设置为: -Xmx256m -Xms64m。
(3)当在服务器环境下(如Tomcat)启动并使用JVM时(对当前服务器环境下因此Java程序生效):
a. 设置环境变量: 变量名:CATALINA_OPTS 变量值:-Xmx128m -Xms64m -Xmn32m -Xss16m。
b. 打开Tomcat根目录下的bin文件夹,编辑catalina.bat,将其中的%CATALINA_OPTS%(共有四处)替换为:-Xmx128m -Xms64m -Xmn32m -Xss16m。
c. 若没有catalina.bat,只有tomcat.exe,tomcat6w.exe;则能够在启动tomcat6w.exe 后 右键配置--Java--java option 下面输入:
-Xmx256m –Xms64m
也能够找到注册表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\TomcatService Manager\Tomcat6\Parameters\JavaOptions原值为 -Dcatalina.home="C:\ApacheGroup\Tomcat 6.0" -Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 6.0\common\endorsed" -Xrs 加入 -Xms300m -Xmx350m (个人是加入-Xmx350m,tomcat才能启动,加入-Xms300m -Xmx350m反而tomcat都不能启动)重起tomcat服务,设置生效。
3. 查看JVM内存信息
Runtime.getRuntime().maxMemory(); //最大可用内存,对应-Xmx
Runtime.getRuntime().freeMemory(); //当前JVM空闲内存
Runtime.getRuntime().totalMemory(); //当前JVM占用的内存总数,其值至关于当前JVM已使用的内存及freeMemory()的总和
关于maxMemory(),freeMemory()和totalMemory():maxMemory()为JVM的最大可用内存,可经过-Xmx设置,默认值为物理内存的1/4,设置不能高于计算机物理内存; totalMemory()为当前JVM占用的内存总数,其值至关于当前JVM已使用的内存及freeMemory()的总和,会随着JVM使用内存的增长而增长; freeMemory()为当前JVM空闲内存,由于JVM只有在须要内存时才占用物理内存使用,因此freeMemory()的值通常状况下都很小,而JVM实际可用内存并不等于freeMemory(),而应该等于maxMemory()-totalMemory()+freeMemory()。
4. 实例,如下给出1G内存环境下java jvm 的参数设置参考
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "
大型的web工程,用tomcat默认分配的内存空间没法启动,若是不是在myeclipse中启动tomcat能够对tomcat这样设置:
TOMCAT_HOME\bin\catalina.bat 中添加这样一句话:
set JAVA_OPTS= -Xmx1024M -Xms512M -XX:MaxPermSize=256m
若是要在myeclipse中启动,上述的修改就不起做用了,可以下设置:
Myeclipse->preferences->myeclipse->servers->tomcat->tomcat×.×->JDK面板中的
Optional Java VM arguments中添加:-Xmx1024M -Xms512M -XX:MaxPermSize=256m
对于单独的.class,能够用下面的方法对Test运行时的jvm内存进行设置。 java -Xms64m -Xmx256m Test -Xms是设置内存初始化的大小 -Xmx是设置最大可以使用内存的大小。
4、JVM内存配置与GC
须要考虑的是Java提供的垃圾回收机制。JVM的堆大小决定了JVM花费在收集垃圾上的时间和频度。收集垃圾能够接受的速度与应用有关,应该经过分析实际的垃圾收集的时间和频率来调整。若是堆的大小很大,那么彻底垃圾收集就会很慢,可是频度会下降。若是你把堆的大小和内存的须要一致,彻底收集就很快,可是会更加频繁。调整堆大小的的目的是最小化垃圾收集的时间,以在特定的时间内最大化处理客户的请求。在基准测试的时候,为保证最好的性能,要把堆的大小设大,保证垃圾收集不在整个基准测试的过程当中出现。若是系统花费不少的时间收集垃圾,请减少堆大小。一次彻底的垃圾收集应该不超过 3-5 秒。若是垃圾收集成为瓶颈,那么须要指定堆的大小,检查垃圾收集的详细输出,研究垃圾收集参数对性能的影响。通常说来,你应该使用物理内存的 80% 做为堆大小。当增长处理器时,记得增长内存,由于分配能够并行进行,而垃圾收集不是并行的。
Java Heap分为3个区:
1.Young 2.Old 3.Permanent。Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。Permanent区则负责保存反射对象,本文不讨论该区。
JVM有2个GC线程:
第一个线程负责回收Heap的Young区;
第二个线程在Heap不足时,遍历Heap,将Young 区升级为Older区,Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,由于第二个线程被迫运行会下降JVM的性能。
为何一些程序频繁发生GC?有以下缘由:
1. 程序内调用了System.gc()或Runtime.gc()。
2. 一些中间件软件调用本身的GC方法,此时须要设置参数禁止这些GC。
3. Java的Heap过小,通常默认的Heap值都很小。
4. 频繁实例化对象,Release对象 此时尽可能保存并重用对象,例如使用StringBuffer()和String()。
若是你发现每次GC后,Heap的剩余空间会是总空间的50%,这表示你的Heap处于健康状态许多Server端的Java程序每次GC后最好能有65%的剩余空间。
经验之谈:
1.Server端JVM最好将-Xms和-Xmx设为相同值。为了优化GC,最好让-Xmn值约等于-Xmx的1/3。
2.一个GUI程序最好是每10到20秒间运行一次GC,每次在半秒以内完成。
注意:
1.增长Heap的大小虽然会下降GC的频率,但也增长了每次GC的时间。而且GC运行时,全部的用户线程将暂停,也就是GC期间,Java应用程序不作任何工做。
2.Heap大小并不决定进程的内存使用量。进程的内存使用量要大于-Xmx定义的值,由于Java为其余任务分配内存,例如每一个线程的Stack等。
参考:
http://www.what21.com/webserver/t/tomcat7-optimize.html
http://blog.csdn.net/ye1992/article/details/9344807