(一)关于JVM
- JVM启动参数是控制将代码制作成可运行程序的过程。
- Tomat需要运行在JVM之上。
- JVM就是一个进程。
- Tomcat容器中运行的多个web程序不能相互通信(可以简单理解为分布式应用)。
- Tomcat中的多个web程序运行在同一个JVM中。
1 关于JVM类加载
JVM类加载采用父类委托机制,如下图:
2 关于tomcat类加载
tomcat是一个java写的程序,它会根据自己的需求实现java的类加载器classLoader,以满足自己要在哪里加载jar包以及一些其他的东西。这与JVM中的加载稍有不同:
当tomcat启动时,会创建以下几种类的加载器:
-
Bootstrap:引导类加载器,加载JVM启动所需的类,以及标准扩展类(位于jre/lib/ext下)。
-
system系统类加载器,加载tomcat启动的类,比如bootstrap.jar,通常在catalina.sh中指定。位于CATALINA_HOME/bin下。
-
Common通用类加载器,加载tomcat使用以及应用通用的一些类,位于CATALINA_HOME/lib下,如servlet-api.jar
-
webapp应用类加载器,每个应用部署后,都会创建一个唯一的类加载器,该类加载器会加载位于WEB-INF/lib下的jar文件中的class和WEB-INF/classes下的class文件。当应用需要用到某个类时,则会按照下面的顺序进行类加载:
- 使用bootstrap引导类加载器加载
- 使用system系统类加载器加载
- 使用应用类加载器在WEB-INF/classes中加载
- 使用应用类加载器在WEB-INF/lib中加载
- 使用common类加载器在CATALINA_HOME/lib中加载
3 tomcat与jvm的关系
Tomcat是Java程序,运行再JVM之上,其本质和之前写的运行在tomcat上的Hello World程序一样,都是运行在JVM之上。复杂的地方在于tomcat实现了Service和JSP的规范,是一种容器。
需要了解Tomcat在启动时所做的事情,首先从启动脚本入手,可以观察到从Bootstrap类开始启动,具体的细节包含classLoader的创建、配置文件的解析、安全策略的配置和使用、Logging的初始化、对Host的解析、对Context的解析等。
4 JVM配置(运维人员了解即可)
1.-Xms:初始堆大小。只要启动,就占用的堆大小。
2.-Xmx:最大堆大小。java.lang.OutOfMemoryError:Java heap这个错误可以通过配置-Xms和-Xmx参数来设置。
3.-Xss:栈大小分配。栈是每个线程私有的区域,通常只有几百K大小,决定了函数调用的深度,而局部变量、参数都分配到栈上。
当出现大量局部变量,递归时,会发生栈空间OOM(java.lang.StackOverflowError)之类的错误。
4.XX:NewSize:设置新生代大小的绝对值。
5.-XX:NewRatio:设置年轻代和年老代的比值。比如设置为3,则新生代:老年代=1:3,新生代占总heap的1/4。
6.-XX:MaxPermSize:设置持久代大小。
java.lang.OutOfMemoryError:PermGenspace这个OOM错误需要合理调大PermSize和MaxPermSize大小。
7.-XX:SurvivorRatio:年轻代中Eden区与两个Survivor区的比值。注意,Survivor区有form和to两个。比如设置为8时,那么eden:form:to=8:1:1。
8.-XX:HeapDumpOnOutOfMemoryError:发生OOM时转储堆到文件,这是一个非常好的诊断方法。
9.-XX:HeapDumpPath:导出堆的转储文件路径。
10.-XX:OnOutOfMemoryError:OOM时,执行一个脚本,比如发送邮件报警,重启程序。后面跟着一个脚本的路径。