本期面试题
- 你怎么给tomcat调优?
- 如何加大tomcat链接数
- 如何加载tomcat的内存
- tomcat如何禁止列出目录下的文件?
- tomcat有几种部署方式?
- tomcat的优化经验
- java类加载过程
- java内存分配
- 描述jvm加载class文件的原理机制
- gc是什么?为什么要有gc?
你答对了几道?? 下面是答案哟~
你怎么给tomcat调优
-
参数调优
-Xms<size> -- 表示JVM初始化堆的大小 -Xmx<size> -- 表示JVM堆的最大值这两个值的大小,一般根据需要进行设置. 当应用程序需要的内存超过堆的最大值时,虚拟机就会提示内存溢出,并且导致应用服务崩溃.因此一般建议最大值设置为最大可用内存的80%. 在
catalina.bat中,设置JAVA_OPTS='-Xms256m- Xmx512m'表示初始化内存256MB,最大可使用内存512MB -
禁用DNS查询
当web应用程序需要记录客户端的信息时,它也会记录客户端的ip地址或者通过域名服务查找机器名转换为ip地址.DNS查询需要占用网络,并且包括很多很远的服务器或者不起作用的服务器上面去获取对应ip的过程,这样就会消耗一定的时间.为了消除DNS查询对性能的影响,我们可以关闭DNS查询.
关闭方式:修改 ``server.xml
文件中的enableLookups` 参数值Tomcat4 <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"port="80" minProcessors="5"maxProcessors="75"enableLookups="false"redire ctPort="8443" acceptCount="100"debug="0"connectionTimeout="20000" useURIValidationHack="false"disableUploadTimeout="true"/> Tomcat5 <Connectorport="80"maxThreads="150"minSpareThreads="25" maxSpareThreads="75"enableLookups="false"redirectPort="8443" acceptCount="100"debug="0"connectionTimeout="20000" disableUploadTimeout="true"/> -
调整线程数
通过应用程序的连接器
Con nector进行性能控制的参数是创建的处理请求的线程数.Tomcat4使用线程池加速响应速度来处理请求.在java中,线程是程序运行时的路径,是在程序中与其他控制线程无关的,能够独立运行的代码段.他们共享相同的地址空间.多线程帮助程序员写出CPU最大利用率的高效程序,使空闲时间保持最低,从而接更多的请求.Tomcat 中可以通过修改
minProcess和maxProcess的值来控制线程数.这些值在安装就已经设定足够使用的默认值,但是随着站点的扩容而改大这些值.minProcess服务器启动时创建的处理请求的线程数应该足够处理一个小量的负载.也就是说,如果QPS为5的服务,并且每个请求都需要一秒时间的处理,那么预先设置的5个线程就足够了.但在你的站点访问量较大时,就需要设置一个更大的数值,指定为参数maxProcess的值.maxProcess的值也是有上限的,防止流量不可控制或者恶意的站点攻击,从而导致超出虚拟机的内存大小.如果加大并发的连接数,应该同时加大这两个参数.web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000,linux是1000.Tomcat5对这些参数进行了调整,请看下面的属性.maxThreads ## Tomcat使用线程来处理接收的每个请求.这个值标识Tomcat可创建的最大的线程数. acceptCount ## 指定当前所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理. connection Timeout ## 网络连接超时,单位 毫秒. 设置为0 标识用不超时,这样设置有隐患的. 通常可设置为30000毫秒. minSpareThreadsTomcat ## 初始化时创建的线程数. maxSpareThreads ## 一旦创建的线程超过这个值, Tomcat就会关闭不再需要的socket线程最好的方式是多设置几次并且进行测试,观察响应时间和内存使用情况.在不同的机器,操作系统或虚拟机组合的情况下可能会不同,而且并不是所有的web站点的流量都是一样的,因此没有一刀切的方案来确定线程数的值.
如何加大Tomcat连接数
在Tomcat 配置文件 server.xml中的 配置中,和连接数相关的参数有:
minProcessors ## 最小空闲连接线程数,用于提高系统处理性能,默认值为10
maxProcessors ## 最大连接线程数,即: 并发处理的最大请求书,默认值为75
acceptCount ## 允许的最大连接数,应大于等于 maxProcessors, 默认值为100
enableLookups ## 是否反查域名,取值为 true或false. 为了提高处理能力,应设置为false
connectionTimeout ## 网络连接超时,单位 毫秒.设置为0用不超时.通常可设置为30000毫秒.
<Connectorport="8080"
maxThreads="150"minSpareThreads="25"maxSpareThreads="75"
enableLookups="false"redirectPort="8443"acceptCount="100"
debug="0"connectionTimeout="20000"
disableUploadTimeout="true"/>
如何加大Tomcat的内存
首先检查程序有没有陷入死循环.这个问题主要是由于内存溢出引起的.java.lang.OutOfMemeoryError:java heap space
第一次出现这样的问题后,引发了其他的问题.在网上查了一下,可能是JAVA的堆栈设置的太小的原因.
两种解决方法:
-
环境变量
修改
TOMCAT_HOME/bin/catalina.shsetJAVA_OPTS=-Xms32m-Xmx512m可以根据自己机器的内存进行更改. -
java执行参数程序参数
java-Xms32m-Xmx800m就是在执行JAVA程序时,加上这个参数.这个问题解决了,而且执行的速度比没有设置的时候快很多.如果在测试的时候会用idea,这时候只需要在执行参数中,
VM options加上-Xms32m- Xmx800m参数就行了. -
内存溢出分情况分析
-
java.lang.OutOfMemoryError:PermGen space
PermGen space 全称是: Permanent Generation space,是指内存的永久保存区
这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection) 不会再主程序运行期间对PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space 错误,这种错误常见在web服务器对JSP进行preco mpile的时候. 如果你的WEB APP下都用了大量的第三方jar,其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了.
解决方法:手动设置MaxPermSize大小 :
TOMCAT_HOME/bin/catalina.sh在
echo"Using CATALINA_BASE:$CATALINA_BASE"上面加入 :JAVA_OPTS="-server-XX:PermSize=64M-XX:MaxPermSize=128m建议:将相同的第三方jar文件移动到tomcat/shared/lib目录下,这样可以达到减少jar文档重复占用内存的目的. -
java.lang.OutOfMemoryError:Java heap space
JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置. JVM在启动的时候会自动设置 Heap size的值,其初始空间 (即-Xms) 是物理内存的 1/64,最大空间 (-Xmx) 是物理内存的 1/4. 可以利用JVM提供的 -Xmn-Xms-Xmx等选项进行设置. Heap size的大小是 年轻代和老年代之和.
提示:在JVM中如果98%的时间是用于GC且可用的Heap size不足2%的时候将抛出此类异常信息.
提示: Heap size 最大不要超过可用物理内存的 80%,一般的要将 -Xms和-Xmx选项设置为相同,而 -Xmn 为1/4 的 -Xmx值.
解决方法: 手动设置Heap size
修改
TOMCAT_HOME/bin/catalina.sh在echo"Using CATALINA_BASE:$CATALINA_BASE"加入JAVA_OPTS="-server-Xms800m-Xmx800m-XX:MaxNewSize=256m"
-
-
1G内存环境下 java jvm 的参数设置参考:
JAVA_OPTS="-server-Xms800m-Xmx800m-XX:PermSize=64M- XX:MaxNewSize=256m-XX:MaxPermSize=128m- Djava.awt.headless=true"很大的web工程,用tomcat默认分配的内存空间无法启动,如果不是在idea中启动.tomcat可以这样设置:
TOMCAT_HOME/bin/catalina.bat中 添加set JAVA_OPTS=-server-Xms2048m-Xmx4096m-XX:PermSize=512M- XX:MaxPermSize=1024M-Duser.timezone=GMT+08或者
set JAVA_OPTS=-Xmx1024M-Xms512M-XX:MaxPermSize=256m如果是在idea中启动,在启动参数 VM options中添加
-Xmx1024M-Xms512M-XX:MaxPermSize=256m
tomcat中如何禁止列出目录下的文件
在 TOMCAT_HOME/conf/web.xml 中,吧listings参数设置成false 即可.
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
tomcat有几种部署方式
四种
-
在tomcat 中 conf 目录下 server.xml 中的
<host />节点中添加<Context path="/hello" docBase="/Users/WebRoot"debug="0" privileged="true"> </Context>Context 节点数量,可以看tomcat官方文档
-
将 web 项目文件拷贝到 webapps 目录中.
-
很灵活,在conf 目录中, 新建Catalina(注意大小写) \localhost目录, 在该目录中新建一个 xml文件,名字可以随意取,只要和当前文件中的文件名不重复就行. 该xml文件的内容为:
<Context path="/hello"docBase="D:eclipse3.2.2forwebtoolsworksp aceheloWebRoot" debug="0"privileged="true"> </Context>优点:可以定义别名.服务器端运行的项目名称为path,外部访问的URL则使用 XML的文件名. 这个方法很方便的隐藏了项目的名称,对一些项目名称被固定不能更换,但外部访问时又想换个路径,非常有效.
还可以定义一些个性配置,如数据源的配置等.
-
tomcat在线后台管理器,一般tomcat都打开了,直接上传war就可以.
Tomcat的优化经验
tomcat 作为web服务器,它的处理性能直接关系到用户体验,下面是种常见的优化措施:
-
去掉对web.xml的监视,把jsp提前编辑成servlet. 物理内存充足的情况,加大tomcat使用的jvm内存.
-
服务器资源,服务器所能提供CPU,内存,硬盘的性能对处理能力有决定性影响.
-
对于高并发情况下会有大量的运算,那么CPU的速度会直接影响到处理速度.
-
内存在大量数据处理的情况下,将会有较大的内存容量需求,可以用
-Xmx-Xms-XX:MaxPermSize等参数对内存不同的功能块进行划分.我们之前就遇到过内存分配不足,导致虚拟机一直处于full GC,从而导致处理能力严重下降. -
硬盘主要问题就是读写性能,当大量文件进行读写时,磁盘极容易成为性能瓶颈.最好的办法还是利用下面提到的缓存.
-
利用缓存和压缩.对于静态页面最好能缓存起来,这样就不比每次从磁盘上读.这里我们才用了Nginx作为缓存服务器,将图片,css,js文件都进行了缓存,有效的减少了后端tomcat的访问.另外,为了能加快网络传输速度,开启gzip压缩也是必不可少的.考虑到tomcat已经需要处理很多东西了,所以把这个压缩的工作就交给前端的NGINX来完成.
除了文本可以用gzip压缩,其实很多图片也可以用图像处理工具预先进行压缩,找到一个平衡点可以让画质损失很小而且文件可以减小很多.曾经我就见过一个图片从300多kb压缩到几十kb,自己几乎看不出来区别.
-
采用集群,单个服务器性能总是有限的,最好的办法自然是实现横向扩展,那么组建tomcat集群是有效提升性能的手段.我们还是才用了NGINX来作为请求分流的服务器,后端多个tomcat共享session来协同工作.
-
优化tomcat参数.这里以tomcat7的俺叔配置为例,需要修改conf/server.xml文件,主要优化链接配置,关闭客户端dns查询.
<Connector port="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="500"
minSpareThreads="20"
acceptCount="100"
disableUploadTimeout="true"
enableLookups="false"
URIEncoding="UTF-8"/>
java类加载过程
java类加载需要经历7个过程
-
加载
加载是类加载的第一个过程,在这个阶段,完成三件事
- 通过一个类的全限定名获取该类的二进制流.
- 将该二进制流中的静态存储结构转化为方法区运行时数据结构.
- 在内存中生成该类的class对象,作为该类的数据访问入口.
-
验证
验证的目的是为了确保class文件的字节流中的信息不会危害到虚拟机,在该阶段主要完成四种验证.
- 文件格式验证:验证字节流是否符合 class 文件的规范,如主次版本号是否在当前虚拟机范围内,常量池中的常量是否有不被支持的类型.
- 原数据验证: 对字节码描述的信息进行语义分析, 如这个类是否有父类,是否继承了不被集成的类等.
- 字节码验证: 是整个验证过程中最复杂的一个阶段,通过验证数据流和控制流的分析,确定程序语义是否正确,主要针对方法体的验证.如: 方法中的类型转换是否正确,跳转指令是否正确等.
- 符号引用验证: 这个动作在后面的解析过程中发生,主要为了确保解析动作能正确执行.
-
准备
准备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行分配.准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配在java堆中.
public static int value=123; //在准备阶段 value初始化值为0,初始化阶段才会变为123. -
解析
该阶段主要完成符号引用到直接引用的转换动作.解析动作并不一定在初始化动作完成之前,也有可能在初始化之后.
-
初始化
初始化时类加载的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制.到了初始化阶段,才真正开始执行类中的定义的java程序代码.
-
使用
-
卸载
java内存分配
- 寄存器: 我们无法控制
- 静态域: static 定义的静态成员.
- 常量池: 编译时被确定并保存在 .class 文件中的 final 常量值和一些文本修饰的符号引用(类和接口的全限定名,字段的名称和描述符,方法和名称和描述符).
- 非 RAM 存储: 硬盘等永久存储空间.
- 堆内存: new创建的对象和数组,由java虚拟机自动垃圾回收器管理,存取速度慢.
- 栈内存: 基本类型的变量和对象的引用变量(堆内存空间的访问地址),速度快,可以共享,但是大小与生存周期必须确定,缺乏灵活性.
java堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)?
JVM 的堆是运行时数据区,所有类的实例和数组都是在堆上面分配内存.它在 JVM 启动的时候被创建. 对象所占的堆内存是由自动内存管理系统也就是垃圾收集器回收.
堆内存是由存货和死亡的对象组成的.存活的对象是引用可以访问的,不会被垃圾回收.死亡的对象是应用不可访问尚且还没有被垃圾收集器回收掉的对象.一直到垃圾收集器把这些对象回收掉之前,他们会一直占据堆内存空间.
描述下JVM加载Class文件的原理机制?
java语言是一种具有动态性的解释性语言,类(Class)只有被加载到JVM后才能运行.当运行指定程序时,JVM会将编译生成的.class文件按照需求和一定的规则加载到内存中,并组织成为一个完整的java应用程序. 这个加载过程是由类加载器完成,具体来说,就是由ClassLoader和它的子类来实现的.类加载器本身也是一个类,其实质是把类文件从硬盘读取到内存中.
类的加载方式分为隐式加载和显式加载.隐式加载指的是程序在使用new等方式创建对象时,会隐式的调用类的加载器把对应的类加载到JVM中.显式加载指的是通过直接调用class.forName() 方法来把所需的类加载到JVM中.
任何一个工程项目都是由许多类组成的,当程序启动时,只把需要的类加载到JVM中,其他类只有被使用的时候才会被加载,采用这种方法一方面可以加快加载速度,另一方面可以节约程序运行时对内存的开销.此外,在java语言中,每个类或接口都对应一个.class文件,这些文件可以被看成是一个个可以被动态加载的单元,因此当只有部分类被修改时,只需要重新编译变化的类即可,而不需要重新编译所有文件,因此加快了编译速度.
在java语言中,类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(例如基类)完全加载到JVM中,至于其他类,则在需要的时候才加载.
类加载的主要步骤:
- 装载:根据查找路径找到对应的class文件,然后导入
- 链接:链接又可分为3个小步
- 检查:检查代价在的class文件的正确性
- 准备:给类中的静态变量分配存储空间
- 解析:将符号引用转换为直接引用(可选)
- 初始化:对静态变量和静态代码块执行初始化工作.
GC是什么?为什么要有GC
GC是垃圾收集的意思(GabageCollection), 内存处理是程序员很容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,因为java语言没有提供释放已分配内存的显示操作方法.