精华内容
下载资源
问答
  • Tomcat调优面试题(一)

    千次阅读 2017-08-13 11:08:25
    Tomcat的优化经验 一、掉对web.xml的监视,把jsp提前编辑成Servlet。有富余物理内存的情况,加大tomcat使用的jvm的内存 二、服务器资源  服务器所能提供CPU、内存、硬盘的性能对处理能力有决定性影响。 ...

    Tomcat的优化经验

    一、掉对web.xml的监视,把jsp提前编辑成Servlet。有富余物理内存的情况,加大tomcat使用的jvm的内存
    二、服务器资源
      服务器所能提供CPU、内存、硬盘的性能对处理能力有决定性影响。
      (1) 对于高并发情况下会有大量的运算,那么CPU的速度会直接影响到处理速度。
      (2) 内存在大量数据处理的情况下,将会有较大的内存容量需求,可以用-Xmx -Xms -XX:MaxPermSize等参数对内存不同功能块进行划分。我们之前就遇到过内存分配不足,导致虚拟机一直处于full GC,从而导致处理能力严重下降。
      (3) 硬盘主要问题就是读写性能,当大量文件进行读写时,磁盘极容易成为性能瓶颈。最好的办法还是利用下面提到的缓存。
    三、利用缓存和压缩
      对于静态页面最好是能够缓存起来,这样就不必每次从磁盘上读。这里我们采用了Nginx作为缓存服务器,将图片、css、js文件都进行了缓存,有效的减少了后端tomcat的访问。
      另外,为了能加快网络传输速度,开启gzip压缩也是必不可少的。但考虑到tomcat已经需要处理很多东西了,所以把这个压缩的工作就交给前端的Nginx来完成。
      除了文本可以用gzip压缩,其实很多图片也可以用图像处理工具预先进行压缩,找到一个平衡点可以让画质损失很小而文件可以减小很多。曾经我就见过一个图片从300多kb压缩到几十kb,自己几乎看不出来区别。
      四、采用集群
      单个服务器性能总是有限的,最好的办法自然是实现横向扩展,那么组建tomcat集群是有效提升性能的手段。我们还是采用了Nginx来作为请求分流的服务器,后端多个tomcat共享session来协同工作。可以参考之前写的《利用nginx+tomcat+memcached组建web服务器负载均衡》。
    五、优化tomcat参数
      这里以tomcat7的参数配置为例,需要修改conf/server.xml文件,主要是优化连接配置,关闭客户端dns查询。   

    1. <Connector port="8080"   
    2.            protocol="org.apache.coyote.http11.Http11NioProtocol"  
    3.            connectionTimeout="20000"  
    4.            redirectPort="8443"   
    5.            maxThreads="500"   
    6.            minSpareThreads="20"  
    7.            acceptCount="100" 
    8.            disableUploadTimeout="true" 
    9.            enableLookups="false"   
    10.            URIEncoding="UTF-8" />
    展开全文
  • Tomcat调优面试题(二)

    千次阅读 2017-08-13 11:29:17
    对于Tomcat的处理耗时较长的问题主要有当时的并发量、session数、内存及内存的回收等几个方面造成的。出现问题之后就要进行分析了。  1.关于Tomcat的session数目  这个可以直接从Tomcat的web管理界面去查看...

    一、问题定位--耗时较长

    对于Tomcat的处理耗时较长的问题主要有当时的并发量、session数、内存及内存的回收等几个方面造成的。出现问题之后就要进行分析了。 

    1.关于Tomcat的session数目 

    这个可以直接从Tomcat的web管理界面去查看即可 ;
    或者借助于第三方工具Lambda Probe来查看,它相对于Tomcat自带的管理稍微多了点功能,但也不多 ;

    2.监视Tomcat的内存使用情况 

    使用JDK自带的jconsole可以比较明了的看到内存的使用情况,线程的状态,当前加载的类的总量等;
    JDK自带的jvisualvm可以下载插件(如GC等),可以查看更丰富的信息。如果是分析本地的Tomcat的话,还可以进行内存抽样等,检查每个类的使用情况

    3.打印类的加载情况及对象的回收情况 

    这个可以通过配置JVM的启动参数,打印这些信息(到屏幕(默认也会到catalina.log中)或者文件),具体参数如下: 
    -XX:+PrintGC:输出形式:[GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs] 
    -XX:+PrintGCDetails:输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs] 
    -XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用,输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs] 
    -XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中断的执行时间。可与上面混合使用。输出形式:Application time: 0.5291524 seconds 
    -XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂停的时间。可与上面混合使用。输出形式:Total time for which application threads were stopped: 0.0468229 seconds 
    -XX:PrintHeapAtGC: 打印GC前后的详细堆栈信息 
    -Xloggc:filename:与上面几个配合使用,把相关日志信息记录到文件以便分析 
    -verbose:class 监视加载的类的情况 
    -verbose:gc 在虚拟机发生内存回收时在输出设备显示信息 
    -verbose:jni 输出native方法调用的相关情况,一般用于诊断jni调用错误信息 

    4.添加JMS远程监控 

    对于部署在局域网内其它机器上的Tomcat,可以打开JMX监控端口,局域网其它机器就可以通过这个端口查看一些常用的参数(但一些比较复杂的功能不支持),同样是在JVM启动参数中配置即可,配置如下: 
    -Dcom.sun.management.jmxremote.ssl=false  -Dcom.sun.management.jmxremote.authenticate=false 
    -Djava.rmi.server.hostname=192.168.71.38 设置JVM的JMS监控监听的IP地址,主要是为了防止错误的监听成127.0.0.1这个内网地址 
    -Dcom.sun.management.jmxremote.port=1090 设置JVM的JMS监控的端口 
    -Dcom.sun.management.jmxremote.ssl=false 设置JVM的JMS监控不实用SSL 
    -Dcom.sun.management.jmxremote.authenticate=false 设置JVM的JMS监控不需要认证 

    5.专业点的分析工具有 

    IBM ISA,JProfiler等,具体监控及分析方式去网上搜索即可。   

    二、集群方案--负载均衡

    单个Tomcat的处理性能是有限的,当并发量较大的时候,就需要有部署多套来进行负载均衡了。 

    集群的关键点有以下几点: 

    1.引入负载端 

    软负载可以使用nginx或者apache来进行,主要是使用一个分发的功能 
    参考: 
    http://ajita.iteye.com/blog/1715312(nginx负载) 
    http://ajita.iteye.com/blog/1717121(apache负载) 

    2.共享session处理 

    目前的处理方式有如下几种: 
    1).使用Tomcat本身的Session复制功能 
    参考http://ajita.iteye.com/blog/1715312(Session复制的配置) 
    方案的有点是配置简单,缺点是当集群数量较多时,Session复制的时间会比较长,影响响应的效率 
    2).使用第三方来存放共享Session 
    目前用的较多的是使用memcached来管理共享Session,借助于memcached-sesson-manager来进行Tomcat的Session管理 
    参考http://ajita.iteye.com/blog/1716320(使用MSM管理Tomcat集群session) 
    3).使用黏性session的策略 
    对于会话要求不太强(不涉及到计费,失败了允许重新请求下等)的场合,同一个用户的session可以由nginx或者apache交给同一个Tomcat来处理,这就是所谓的session sticky策略,目前应用也比较多 
    参考:http://ajita.iteye.com/blog/1848665(tomcat session sticky) 
    nginx默认不包含session sticky模块,需要重新编译才行(windows下我也不知道怎么重新编译) 
    优点是处理效率高多了,缺点是强会话要求的场合不合适 

    3.小结 

    以上是实现集群的要点,其中1和2可以组合使用,具体场景具体分析吧~  

    三、JVM优化

    Tomcat本身还是运行在JVM上的,通过对JVM参数的调整我们可以使Tomcat拥有更好的性能。针对JVM的优化目前主要在两个方面: 

    1.内存调优 

    内存方式的设置是在catalina.sh中,调整一下JAVA_OPTS变量即可,因为后面的启动参数会把JAVA_OPTS作为JVM的启动参数来处理。 
    具体设置如下: 
    JAVA_OPTS="$JAVA_OPTS -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4" 
    其各项参数如下: 
    -Xmx3550m:设置JVM最大可用内存为3550M。 
    -Xms3550m:设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。 
    -Xmn2g:设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。 
    -Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。 
    -XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 
    -XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6 
    -XX:MaxPermSize=16m:设置持久代大小为16m。 
    -XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。 

    2.垃圾回收策略调优 

    垃圾回收的设置也是在catalina.sh中,调整JAVA_OPTS变量。 
    具体设置如下: 
    JAVA_OPTS="$JAVA_OPTS -Xmx3550m -Xms3550m -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100" 

    具体的垃圾回收策略及相应策略的各项参数如下: 
    串行收集器(JDK1.5以前主要的回收方式) 
    -XX:+UseSerialGC:设置串行收集器 
    并行收集器(吞吐量优先) 
    示例: 
    java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100 

    -XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。 
    -XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。 
    -XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集 
    -XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。 
    -XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开。 
    并发收集器(响应时间优先) 
    示例:java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC 
    -XX:+UseConcMarkSweepGC:设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置。 
    -XX:+UseParNewGC: 设置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。 
    -XX:CMSFullGCsBeforeCompaction:由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。 
    -XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩。可能会影响性能,但是可以消除碎片 

    3.小结 

    在内存设置中需要做一下权衡 
    1)内存越大,一般情况下处理的效率也越高,但同时在做垃圾回收的时候所需要的时间也就越长,在这段时间内的处理效率是必然要受影响的。 
    2)在大多数的网络文章中都推荐 Xmx和Xms设置为一致,说是避免频繁的回收,这个在测试的时候没有看到明显的效果,内存的占用情况基本都是锯齿状的效果,所以这个还要根据实际情况来定。  

    四、Server.xml的Connection优化

    Tomcat的Connector是Tomcat接收HTTP请求的关键模块,我们可以配置它来指定IO模式,以及处理通过这个Connector接受到的请求的处理线程数以及其它一些常用的HTTP策略。其主要配置参数如下: 

    1.指定使用NIO模型来接受HTTP请求 

    protocol="org.apache.coyote.http11.Http11NioProtocol" 指定使用NIO模型来接受HTTP请求。默认是BlockingIO,配置为protocol="HTTP/1.1" 
    acceptorThreadCount="2" 使用NIO模型时接收线程的数目 

    2.指定使用线程池来处理HTTP请求 

    首先要配置一个线程池来处理请求(与Connector是平级的,多个Connector可以使用同一个线程池来处理请求) 
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" 
    maxThreads="1000" minSpareThreads="50" maxIdleTime="600000"/> 
    <Connector port="8080"
    executor="tomcatThreadPool" 指定使用的线程池 

    3.指定BlockingIO模式下的处理线程数目 

    maxThreads="150"//Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。默认值200。可以根据机器的时期性能和内存大小调整,一般可以在400-500。最大可以在800左右。 
    minSpareThreads="25"---Tomcat初始化时创建的线程数。默认值4。如果当前没有空闲线程,且没有超过maxThreads,一次性创建的空闲线程数量。Tomcat初始化时创建的线程数量也由此值设置。 
    maxSpareThreads="75"--一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。默认值50。一旦创建的线程超过此数值,Tomcat会关闭不再需要的线程。线程数可以大致上用 “同时在线人数*每秒用户操作次数*系统平均操作时间” 来计算。 
    acceptCount="100"----指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。默认值10。如果当前可用线程数为0,则将请求放入处理队列中。这个值限定了请求队列的大小,超过这个数值的请求将不予处理。 
    connectionTimeout="20000" --网络连接超时,默认值20000,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。 

    4.其它常用设置 

    maxHttpHeaderSize="8192" http请求头信息的最大程度,超过此长度的部分不予处理。一般8K。 
    URIEncoding="UTF-8" 指定Tomcat容器的URL编码格式。 
    disableUploadTimeout="true" 上传时是否使用超时机制 
    enableLookups="false"--是否反查域名,默认值为true。为了提高处理能力,应设置为false 
    compression="on"   打开压缩功能 
    compressionMinSize="10240" 启用压缩的输出内容大小,默认为2KB 
    noCompressionUserAgents="gozilla, traviata"   对于以下的浏览器,不启用压缩 
    compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" 哪些资源类型需要压缩 

    5.小结 

    关于Tomcat的Nio和ThreadPool,本身的引入就提高了处理的复杂性,所以对于效率的提高有多少,需要实际验证一下。 

    6.配置示例 

    <Connector port="8080" 
    redirectPort="8443"
    maxThreads="150" 
    minSpareThreads="25" 
    maxSpareThreads="75" 
    acceptCount="100" 
    connectionTimeout="20000" 
    protocol="HTTP/1.1" 

    maxHttpHeaderSize="8192" 
    URIEncoding="UTF-8" 
    disableUploadTimeout="true" 
    enableLookups="false" 
    compression="on" 
    compressionMinSize="10240" 
    noCompressionUserAgents="gozilla, traviata" 
    compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"> 
    ... 
    </Connector>

     

    展开全文
  • 前段时间参加面试面试过程中提到服务器的调优方案,这里总结一下。 首先说一下tomcat调优方案: Tomcat本身的优化,Java虚拟机调优Tomcat 优化分为系统优化,接下来一个个介绍: 一、Tomcat本身的优化 ...

    前段时间参加面试,面试过程中提到服务器的调优方案,这里总结一下。

    首先说一下tomcat的调优方案:

    Tomcat本身的优化,Java虚拟机调优,Tomcat 优化分为系统优化,接下来一个个介绍:

     一、Tomcat本身的优化

       Tomcat 的自身参数的优化,这块很像 ApacheHttp Server。修改一下 xml 配置文件中的参数,调整最大连接数,超时等。此外,我们安装 Tomcat 是,优化就已经开始了。

    1、工作方式选择      

    为了提升性能,首先就要对代码进行动静分离,让 Tomcat 只负责 jsp 文件的解析工作。如采用 Apache 和 Tomcat 的整合方式,他们之间的连接方案有三种选择,JK、http_proxy 和 ajp_proxy。相对于 JK 的连接方式,后两种在配置上比较简单的,灵活性方面也一点都不逊色。但就稳定性而言不像JK 这样久经考验,所以建议采用 JK 的连接方式。 

    2、Connector连接器的配置

    之前文件介绍过的 Tomcat 连接器的三种方式: bio、nio 和 apr,三种方式性能差别很大,apr 的性能最优, bio 的性能最差。而 Tomcat 7 使用的 Connector  默认就启用的 Apr 协议,但需要系统安装 Apr 库,否则就会使用 bio 方式。

    3、配置文件优化

    配置文件优化其实就是对 server.xml 优化,可以提大大提高 Tomcat 的处理请求的能力,下面我们来看 Tomcat 容器内的优化。

    默认配置下,Tomcat 会为每个连接器创建一个绑定的线程池(最大线程数 200),服务启动时,默认创建了 5 个空闲线程随时等待用户请求。

    首先,打开 ${TOMCAT_HOME}/conf/server.xml,搜索【<Executor name="tomcatThreadPool"】,开启并调整为


    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
            maxThreads="500" minSpareThreads="20" maxSpareThreads="50" maxIdleTime="60000"/>
    注意, Tomcat 7 在开启线程池前,一定要安装好 Apr 库,并可以启用,否则会有错误报出,shutdown.sh 脚本无法关闭进程。

    然后,修改<Connector …>节点,增加 executor 属性,搜索【port="8080"】,调整为


    <Connector executor="tomcatThreadPool"
                   port="8080" protocol="HTTP/1.1"
                   URIEncoding="UTF-8"
                   connectionTimeout="30000"
                   enableLookups="false"
                   disableUploadTimeout="false"
                   connectionUploadTimeout="150000"
                   acceptCount="300"
                   keepAliveTimeout="120000"
                   maxKeepAliveRequests="1"
                   compression="on"
                   compressionMinSize="2048"
                   compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/gif,image/jpg,image/png" 
                   redirectPort="8443" />
    maxThreads :Tomcat 使用线程来处理接收的每个请求,这个值表示 Tomcat 可创建的最大的线程数,默认值是 200

    minSpareThreads:最小空闲线程数,Tomcat 启动时的初始化的线程数,表示即使没有人使用也开这么多空线程等待,默认值是 10。

    maxSpareThreads:最大备用线程数,一旦创建的线程超过这个值,Tomcat 就会关闭不再需要的 socket 线程。

    上边配置的参数,最大线程 500(一般服务器足以),要根据自己的实际情况合理设置,设置越大会耗费内存和 CPU,因为 CPU 疲于线程上下文切换,没有精力提供请求服务了,最小空闲线程数 20,线程最大空闲时间 60 秒,当然允许的最大线程连接数还受制于操作系统的内核参数设置,设置多大要根据自己的需求与环境。当然线程可以配置在“tomcatThreadPool”中,也可以直接配置在“Connector”中,但不可以重复配置。

    URIEncoding:指定 Tomcat 容器的 URL 编码格式,语言编码格式这块倒不如其它 WEB 服务器软件配置方便,需要分别指定。

    connnectionTimeout: 网络连接超时,单位:毫秒,设置为 0 表示永不超时,这样设置有隐患的。通常可设置为 30000 毫秒,可根据检测实际情况,适当修改。

    enableLookups: 是否反查域名,以返回远程主机的主机名,取值为:true 或 false,如果设置为false,则直接返回IP地址,为了提高处理能力,应设置为 false。

    disableUploadTimeout:上传时是否使用超时机制。

    connectionUploadTimeout:上传超时时间,毕竟文件上传可能需要消耗更多的时间,这个根据你自己的业务需要自己调,以使Servlet有较长的时间来完成它的执行,需要与上一个参数一起配合使用才会生效。

    acceptCount:指定当所有可以使用的处理请求的线程数都被使用时,可传入连接请求的最大队列长度,超过这个数的请求将不予处理,默认为100个。

    keepAliveTimeout:长连接最大保持时间(毫秒),表示在下次请求过来之前,Tomcat 保持该连接多久,默认是使用 connectionTimeout 时间,-1 为不限制超时。

    maxKeepAliveRequests:表示在服务器关闭之前,该连接最大支持的请求数。超过该请求数的连接也将被关闭,1表示禁用,-1表示不限制个数,默认100个,一般设置在100~200之间。

    compression:是否对响应的数据进行 GZIP 压缩,off:表示禁止压缩;on:表示允许压缩(文本将被压缩)、force:表示所有情况下都进行压缩,默认值为off,压缩数据后可以有效的减少页面的大小,一般可以减小1/3左右,节省带宽。

    compressionMinSize:表示压缩响应的最小值,只有当响应报文大小大于这个值的时候才会对报文进行压缩,如果开启了压缩功能,默认值就是2048。

    compressableMimeType:压缩类型,指定对哪些类型的文件进行数据压缩。

    noCompressionUserAgents="gozilla, traviata": 对于以下的浏览器,不启用压缩。

    如果已经对代码进行了动静分离,静态页面和图片等数据就不需要 Tomcat 处理了,那么也就不需要配置在 Tomcat 中配置压缩了。

    以上是一些常用的配置参数属性,当然还有好多其它的参数设置,还可以继续深入的优化,HTTP Connector 与 AJP Connector 的参数属性值,可以参考官方文档的详细说明:

    https://tomcat.apache.org/tomcat-7.0-doc/config/http.html

    https://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html

    二、JVM 优化

    Tomcat 启动命令行中的优化参数,就是 JVM 的优化 。Tomcat 首先跑在 JVM 之上的,因为它的启动其实也只是一个 java 命令行,首先我们需要对这个 JAVA 的启动命令行进行调优。不管是 YGC 还是 Full GC,GC 过程中都会对导致程序运行中中断,正确的选择不同的 GC 策略,调整 JVM、GC 的参数,可以极大的减少由于 GC 工作,而导致的程序运行中断方面的问题,进而适当的提高 Java 程序的工作效率。但是调整 GC 是以个极为复杂的过程,由于各个程序具备不同的特点,如:web 和 GUI 程序就有很大区别(Web可以适当的停顿,但GUI停顿是客户无法接受的),而且由于跑在各个机器上的配置不同(主要 cup 个数,内存不同),所以使用的 GC 种类也会不同。

    1、JVM 参数配置方法

    Tomcat 的启动参数位于安装目录 ${JAVA_HOME}/bin目录下,Linux 操作系统就是 catalina.sh 文件。JAVA_OPTS,就是用来设置 JVM 相关运行参数的变量,还可以在 CATALINA_OPTS 变量中设置。关于这 2 个变量,还是多少有些区别的:

    JAVA_OPTS:用于当 Java 运行时选项“start”、“stop”或“run”命令执行。

    CATALINA_OPTS:用于当 Java 运行时选项“start”或“run”命令执行。

    为什么有两个不同的变量?它们之间都有什么区别呢?

    首先,在启动 Tomcat 时,任何指定变量的传递方式都是相同的,可以传递到执行“start”或“run”命令中,但只有设定在 JAVA_OPTS 变量里的参数被传递到“stop”命令中。对于 Tomcat 运行过程,可能没什么区别,影响的是结束程序,而不是启动程序。

    第二个区别是更微妙,其他应用程序也可以使用 JAVA_OPTS 变量,但只有在 Tomcat 中使用 CATALINA_OPTS 变量。如果你设置环境变量为只使用 Tomcat,最好你会建议使用 CATALINA_OPTS 变量,而如果你设置环境变量使用其它的 Java 应用程序,例如 JBoss,你应该把你的设置放在JAVA_OPTS 变量中。


    2、JVM 参数属性

    32 位系统下 JVM 对内存的限制:不能突破 2GB ,那么这时你的 Tomcat 要优化,就要讲究点技巧了,而在 64 位操作系统上无论是系统内存还是 JVM 都没有受到 2GB 这样的限制。

           针对于 JMX 远程监控也是在这里设置,以下为 64 位系统环境下的配置,内存加入的参数如下:

    CATALINA_OPTS="
    -server 
    -Xms6000M 
    -Xmx6000M 
    -Xss512k 
    -XX:NewSize=2250M 
    -XX:MaxNewSize=2250M 
    -XX:PermSize=128M
    -XX:MaxPermSize=256M  
    -XX:+AggressiveOpts 
    -XX:+UseBiasedLocking 
    -XX:+DisableExplicitGC 
    -XX:+UseParNewGC 
    -XX:+UseConcMarkSweepGC 
    -XX:MaxTenuringThreshold=31 
    -XX:+CMSParallelRemarkEnabled 
    -XX:+UseCMSCompactAtFullCollection 
    -XX:LargePageSizeInBytes=128m 
    -XX:+UseFastAccessorMethods 
    -XX:+UseCMSInitiatingOccupancyOnly
    -Duser.timezone=Asia/Shanghai 
    -Djava.awt.headless=true"
    为了看着方便,将每个参数单独写一行。上面参数好多啊,可能有人写到现在都没见过一个在 Tomcat 的启动命令里加了这么多参数,当然,这些参数只是我机器上的,不一定适合你,尤其是参数后的 value(值)是需要根据你自己的实际情况来设置的。

    上述这样的配置,基本上可以达到:

    系统响应时间增快;

    JVM回收速度增快同时又不影响系统的响应率;

    JVM内存最大化利用;

    线程阻塞情况最小化。

    JVM 常用参数详解:

    -server:一定要作为第一个参数,在多个 CPU 时性能佳,还有一种叫 -client 的模式,特点是启动速度比较快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或开发调试,在 32 位环境下直接运行 Java 程序默认启用该模式。Server 模式的特点是启动速度比较慢,但运行时性能和内存管理效率很高,适用于生产环境,在具有 64 位能力的 JDK 环境下默认启用该模式,可以不配置该参数。

    -Xms:表示 Java 初始化堆的大小,-Xms 与-Xmx 设成一样的值,避免 JVM 反复重新申请内存,导致性能大起大落,默认值为物理内存的 1/64,默认(MinHeapFreeRatio参数可以调整)空余堆内存小于 40% 时,JVM 就会增大堆直到 -Xmx 的最大限制。

    -Xmx:表示最大 Java 堆大小,当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃,因此一般建议堆的最大值设置为可用内存的最大值的80%。如何知道我的 JVM 能够使用最大值,使用 java -Xmx512M -version 命令来进行测试,然后逐渐的增大 512 的值,如果执行正常就表示指定的内存大小可用,否则会打印错误信息,默认值为物理内存的 1/4,默认(MinHeapFreeRatio参数可以调整)空余堆内存大于 70% 时,JVM 会减少堆直到-Xms 的最小限制。

    -Xss:表示每个 Java 线程堆栈大小,JDK 5.0 以后每个线程堆栈大小为 1M,以前每个线程堆栈大小为 256K。根据应用的线程所需内存大小进行调整,在相同物理内存下,减小这个值能生成更多的线程,但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在 3000~5000 左右。一般小的应用, 如果栈不是很深, 应该是128k 够用的,大的应用建议使用 256k 或 512K,一般不易设置超过 1M,要不然容易出现out ofmemory。这个选项对性能影响比较大,需要严格的测试。

    -XX:NewSize:设置新生代内存大小。

    -XX:MaxNewSize:设置最大新生代新生代内存大小

    -XX:PermSize:设置持久代内存大小

    -XX:MaxPermSize:设置最大值持久代内存大小,永久代不属于堆内存,堆内存只包含新生代和老年代。

    -XX:+AggressiveOpts:作用如其名(aggressive),启用这个参数,则每当 JDK 版本升级时,你的 JVM 都会使用最新加入的优化技术(如果有的话)。

    -XX:+UseBiasedLocking:启用一个优化了的线程锁,我们知道在我们的appserver,每个http请求就是一个线程,有的请求短有的请求长,就会有请求排队的现象,甚至还会出现线程阻塞,这个优化了的线程锁使得你的appserver内对线程处理自动进行最优调配。

    -XX:+DisableExplicitGC:在 程序代码中不允许有显示的调用“System.gc()”。每次在到操作结束时手动调用 System.gc() 一下,付出的代价就是系统响应时间严重降低,就和关于 Xms,Xmx 里的解释的原理一样,这样去调用 GC 导致系统的 JVM 大起大落。

    -XX:+UseConcMarkSweepGC:设置年老代为并发收集,即 CMS gc,这一特性只有 jdk1.5
    后续版本才具有的功能,它使用的是 gc 估算触发和 heap 占用触发。我们知道频频繁的 GC 会造面 JVM
    的大起大落从而影响到系统的效率,因此使用了 CMS GC 后可以在 GC 次数增多的情况下,每次 GC 的响应时间却很短,比如说使用了 CMS
    GC 后经过 jprofiler 的观察,GC 被触发次数非常多,而每次 GC 耗时仅为几毫秒。

    -XX:+UseParNewGC:对新生代采用多线程并行回收,这样收得快,注意最新的 JVM 版本,当使用 -XX:+UseConcMarkSweepGC 时,-XX:UseParNewGC 会自动开启。因此,如果年轻代的并行 GC 不想开启,可以通过设置 -XX:-UseParNewGC 来关掉。

    -XX:MaxTenuringThreshold:设置垃圾最大年龄。如果设置为0的话,则新生代对象不经过 Survivor 区,直接进入老年代。对于老年代比较多的应用(需要大量常驻内存的应用),可以提高效率。如果将此值设置为一 个较大值,则新生代对象会在 Survivor 区进行多次复制,这样可以增加对象在新生代的存活时间,增加在新生代即被回收的概率,减少Full GC的频率,这样做可以在某种程度上提高服务稳定性。该参数只有在串行 GC 时才有效,这个值的设置是根据本地的 jprofiler 监控后得到的一个理想的值,不能一概而论原搬照抄。

    -XX:+CMSParallelRemarkEnabled:在使用 UseParNewGC 的情况下,尽量减少 mark 的时间。

    -XX:+UseCMSCompactAtFullCollection:在使用 concurrent gc 的情况下,防止 memoryfragmention,对 live object 进行整理,使 memory 碎片减少。

    -XX:LargePageSizeInBytes:指定 Java heap 的分页页面大小,内存页的大小不可设置过大, 会影响 Perm 的大小。

    -XX:+UseFastAccessorMethods:使用 get,set 方法转成本地代码,原始类型的快速优化。

    -XX:+UseCMSInitiatingOccupancyOnly:只有在 oldgeneration 在使用了初始化的比例后 concurrent collector 启动收集。

    -Duser.timezone=Asia/Shanghai:设置用户所在时区。

    -Djava.awt.headless=true:这个参数一般我们都是放在最后使用的,这全参数的作用是这样的,有时我们会在我们的 J2EE 工程中使用一些图表工具如:jfreechart,用于在 web 网页输出 GIF/JPG 等流,在 winodws 环境下,一般我们的 app server 在输出图形时不会碰到什么问题,但是在linux/unix 环境下经常会碰到一个 exception 导致你在 winodws 开发环境下图片显示的好好可是在 linux/unix 下却显示不出来,因此加上这个参数以免避这样的情况出现。

    -Xmn:新生代的内存空间大小,注意:此处的大小是(eden+ 2 survivor space)。与 jmap -heap 中显示的 New gen 是不同的。整个堆大小 = 新生代大小 + 老生代大小 + 永久代大小。在保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的 3/8。

    -XX:CMSInitiatingOccupancyFraction:当堆满之后,并行收集器便开始进行垃圾收集,例如,当没有足够的空间来容纳新分配或提升的对象。对于 CMS 收集器,长时间等待是不可取的,因为在并发垃圾收集期间应用持续在运行(并且分配对象)。因此,为了在应用程序使用完内存之前完成垃圾收集周期,CMS 收集器要比并行收集器更先启动。因为不同的应用会有不同对象分配模式,JVM 会收集实际的对象分配(和释放)的运行时数据,并且分析这些数据,来决定什么时候启动一次 CMS 垃圾收集周期。这个参数设置有很大技巧,基本上满足(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100 >= Xmn 就不会出现 promotion failed。例如在应用中 Xmx 是6000,Xmn 是 512,那么 Xmx-Xmn 是 5488M,也就是老年代有 5488M,CMSInitiatingOccupancyFraction=90 说明老年代到 90% 满的时候开始执行对老年代的并发垃圾回收(CMS),这时还 剩 10% 的空间是 5488*10% = 548M,所以即使 Xmn(也就是新生代共512M)里所有对象都搬到老年代里,548M 的空间也足够了,所以只要满足上面的公式,就不会出现垃圾回收时的 promotion failed,因此这个参数的设置必须与 Xmn 关联在一起。

    -XX:+CMSIncrementalMode:该标志将开启 CMS 收集器的增量模式。增量模式经常暂停 CMS 过程,以便对应用程序线程作出完全的让步。因此,收集器将花更长的时间完成整个收集周期。因此,只有通过测试后发现正常 CMS 周期对应用程序线程干扰太大时,才应该使用增量模式。由于现代服务器有足够的处理器来适应并发的垃圾收集,所以这种情况发生得很少,用于但 CPU情况。

    -XX:NewRatio:年轻代(包括 Eden 和两个 Survivor 区)与年老代的比值(除去持久代),-XX:NewRatio=4 表示年轻代与年老代所占比值为 1:4,年轻代占整个堆栈的 1/5,Xms=Xmx 并且设置了 Xmn 的情况下,该参数不需要进行设置。

    -XX:SurvivorRatio:Eden 区与 Survivor 区的大小比值,设置为 8,表示 2 个 Survivor 区(JVM 堆内存年轻代中默认有 2 个大小相等的 Survivor 区)与 1 个 Eden 区的比值为 2:8,即 1 个 Survivor 区占整个年轻代大小的 1/10。

    -XX:+UseSerialGC:设置串行收集器。

    -XX:+UseParallelGC:设置为并行收集器。此配置仅对年轻代有效。即年轻代使用并行收集,而年老代仍使用串行收集。

    -XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集,JDK6.0 开始支持对年老代并行收集。

    -XX:ConcGCThreads:早期 JVM 版本也叫-XX:ParallelCMSThreads,定义并发 CMS 过程运行时的线程数。比如 value=4 意味着 CMS 周期的所有阶段都以 4 个线程来执行。尽管更多的线程会加快并发 CMS 过程,但其也会带来额外的同步开销。因此,对于特定的应用程序,应该通过测试来判断增加 CMS 线程数是否真的能够带来性能的提升。如果还标志未设置,JVM 会根据并行收集器中的 -XX:ParallelGCThreads 参数的值来计算出默认的并行 CMS 线程数。

    -XX:ParallelGCThreads:配置并行收集器的线程数,即:同时有多少个线程一起进行垃圾回收,此值建议配置与 CPU 数目相等。

    -XX:OldSize:设置 JVM 启动分配的老年代内存大小,类似于新生代内存的初始大小 -XX:NewSize。

    以上就是一些常用的配置参数,有些参数是可以被替代的,配置思路需要考虑的是 Java 提供的垃圾回收机制。虚拟机的堆大小决定了虚拟机花费在收集垃圾上的时间和频度。收集垃圾能够接受的速度和应用有关,应该通过分析实际的垃圾收集的时间和频率来调整。假如堆的大小很大,那么完全垃圾收集就会很慢,但是频度会降低。假如您把堆的大小和内存的需要一致,完全收集就很快,但是会更加频繁。调整堆大小的的目的是最小化垃圾收集的时间,以在特定的时间内最大化处理客户的请求。在基准测试的时候,为确保最好的性能,要把堆的大小设大,确保垃圾收集不在整个基准测试的过程中出现。

    假如系统花费很多的时间收集垃圾,请减小堆大小。一次完全的垃圾收集应该不超过 3-5 秒。假如垃圾收集成为瓶颈,那么需要指定代的大小,检查垃圾收集的周详输出,研究垃圾收集参数对性能的影响。当增加处理器时,记得增加内存,因为分配能够并行进行,而垃圾收集不是并行的。

    3、设置系统属性

    之前说过,Tomcat 的语言编码,配置起来很慢,要经过多次设置才可以了,否则中文很有可能出现乱码情况。譬如汉字“中”,以 UTF-8 编码后得到的是 3 字节的值 %E4%B8%AD,然后通过 GET 或者 POST 方式把这 3 个字节提交到 Tomcat 容器,如果你不告诉 Tomcat 我的参数是用 UTF-8编码的,那么 Tomcat 就认为你是用 ISO-8859-1 来编码的,而 ISO8859-1(兼容 URI 中的标准字符集 US-ASCII)是兼容 ASCII 的单字节编码并且使用了单字节内的所有空间,因此 Tomcat 就以为你传递的用 ISO-8859-1 字符集编码过的 3 个字符,然后它就用 ISO-8859-1 来解码。

    设置起来不难使用“ -D<名称>=<值> ”来设置系统属性:

    -Djavax.servlet.request.encoding=UTF-8

    -Djavax.servlet.response.encoding=UTF-8 

    -Dfile.encoding=UTF-8 

    -Duser.country=CN 

    -Duser.language=zh

    4、常见的 Java 内存溢出有以下三种

    (1) java.lang.OutOfMemoryError: Java heap space —-JVM Heap(堆)溢出

    JVM 在启动的时候会自动设置 JVM Heap 的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)不可超过物理内存。可以利用 JVM提供的 -Xmn -Xms -Xmx 等选项可进行设置。Heap 的大小是 Young Generation 和 Tenured Generaion 之和。在 JVM 中如果 98% 的时间是用于 GC,且可用的 Heap size 不足 2% 的时候将抛出此异常信息。

    解决方法:手动设置 JVM Heap(堆)的大小。  
    (2) java.lang.OutOfMemoryError: PermGen space  —- PermGen space溢出。

    PermGen space 的全称是 Permanent Generation space,是指内存的永久保存区域。为什么会内存溢出,这是由于这块内存主要是被 JVM 存放Class 和 Meta 信息的,Class 在被 Load 的时候被放入 PermGen space 区域,它和存放 Instance 的 Heap 区域不同,sun 的 GC 不会在主程序运行期对 PermGen space 进行清理,所以如果你的 APP 会载入很多 CLASS 的话,就很可能出现 PermGen space 溢出。

    解决方法: 手动设置 MaxPermSize 大小

    (3) java.lang.StackOverflowError   —- 栈溢出

    栈溢出了,JVM 依然是采用栈式的虚拟机,这个和 C 与 Pascal 都是一样的。函数的调用过程都体现在堆栈和退栈上了。调用构造函数的 “层”太多了,以致于把栈区溢出了。通常来讲,一般栈区远远小于堆区的,因为函数调用过程往往不会多于上千层,而即便每个函数调用需要 1K 的空间(这个大约相当于在一个 C 函数内声明了 256 个 int 类型的变量),那么栈区也不过是需要 1MB 的空间。通常栈的大小是 1-2MB 的。
    通常递归也不要递归的层次过多,很容易溢出。

    三、系统优化

    Windows环境下,是tomcat安装版(利用windows的系统服务启动tomcat),解决办法:

    修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Procrun2.0\Tomcat6\Parameters\JavaOptions

           原值为:

    -Dcatalina.home=E:\Tomcat 6.0

    -Dcatalina.base=E:\Tomcat 6.0

    -Djava.endorsed.dirs=E:\Tomcat 6.0\common\endorsed

    -Djava.io.tmpdir=E:\Tomcat 6.0\temp

    -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager


    -Djava.util.logging.config.file=E:\Tomcat
    6.0\conf\logging.properties

             加入:

    Xms512m -Xmx512m -XX:PermSize=128M
    -XX:MaxNewSize=256m -XX:MaxPermSize=512m

             重起tomcat服务,设置生效。

             Linux环境下, ,解决办法:

            修改“%TOMCAT_HOME%\bin\catalina.sh”文件,在文件开头增加如下设置:JAVA_OPTS=’-Xms256m-Xmx512m’

            各参数详解:

            -Xms:设置JVM初始内存大小(默认是物理内存的1/64)

            -Xmx:设置JVM可以使用的最大内存(默认是物理内存的1/4,建议:物理内存80%)

           -Xmn:设置JVM最小内存(128-256m就够了,一般不设置)

           默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。

           在较大型的应用项目中,默认的内存是不够的,有可能导致系统无法运行。常见的问题是报Tomcat内存溢出错误“java.lang.OutOfMemoryError:
    Java heap space”,从而导致客户端显示500错误。
          -XX:PermSize :为JVM启动时Perm的内存大小

         -XX:MaxPermSize :为最大可占用的Perm内存大小(默认为32M)

         -XX:MaxNewSize,默认为16M

         PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGenspace中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGenspace进行清理,所以如果你的应用中有很CLASS的话,就很可能出现“java.lang.OutOfMemoryError:PermGen space”错误。

           对于WEB项目,jvm加载类时,永久域中的对象急剧增加,从而使jvm不断调整永久域大小,为了避免调整),你可以使用更多的参数配置。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小,那么就会产生此错误信息了。

    其它参数:

    -XX:NewSize :默认为2M,此值设大可调大新对象区,减少Full
    GC次数

    -XX:NewRatio :改变新旧空间的比例,意思是新空间的尺寸是旧空间的1/8(默认为8)

    -XX:SurvivorRatio :改变Eden对象空间和残存空间的尺寸比例,意思是Eden对象空

    间的尺寸比残存空间大survivorRatio+2倍(缺省值是10)

    -XX:userParNewGC 可用来设置并行收集【多CPU】

    -XX:ParallelGCThreads 可用来增加并行度【多CPU】

    -XXUseParallelGC 设置后可以使用并行清除收集器【多CPU】
     

    展开全文
  • JVM与调优面试题

    千次阅读 2021-02-26 10:03:49
    3.1.3 分布式缓存与一致性哈希 3.2 异步 3.2.1 同步和异步,阻塞和非阻塞 3.2.2 常见异步的手段 3.3 集群 image.png 3.4 应用相关 3.4.1 代码级别 3.4.2 并发编程 3.4.3 资源的复用 3.4.4 JVM 3.4.5 GC 调优 3.4.6 ...

    一、JVM 内存区域划分

    1.程序计数器(线程私有)

    程序计数器(Program Counter Register),也有称作为 PC 寄存器。保存的是程序当前执行的指令的地址(也可以说保存下一条指令的所在存储单元的地址),当 CPU 需要执行指令时,需要从程序计数器中得到当前需要执行的指令所在存储单元的地址,然后根据得到的地址获取到指令,在得到指令之后,程序计数器便自动加 1 或者根据转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令。也就是说是用来指示执行哪条指令的。

    由于在 JVM 中,多线程是通过线程轮流切换来获得 CPU 执行时间的,因此,在任一具体时刻,一个 CPU 的内核只会执行一条线程中的指令,因此,为了能够使得每个线程都在线程切换后能够恢复在切换之前的程序执行位置,每个线程都需要有自己独立的程序计数器,并且不能互相被干扰,否则就会影响到程序的正常执行次序。因此,可以这么说,程序计数器是每个线程所私有的。

    在 JVM 规范中规定,如果线程执行的是非 native 方法,则程序计数器中保存的是当前需要执行的指令的地址;如果线程执行的是 native 方法,则程序计数器中的值是 undefined。

    由于程序计数器中存储的数据所占空间的大小不会随程序的执行而发生改变,因此,对于程序计数器是不会发生内存溢出现象(OutOfMemory)的。

    异常情况:

    不存在

    2.Java 栈(线程私有)

    3.本地方法栈(线程私有)

    4.堆(线程共享)

    5.方法区(线程共享)

    6.直接内存(线程共享)

    dac08c14643e

    image.png

    二、JVM 执行子系统

    1.Class 类文件结构

    1.1 Java 跨平台的基础

    各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节码(ByteCode)是构成平台无关性的基石,也是语言无关性的基础。Java 虚拟机不和包括 Java 在内的任何语言绑定,它只与“Class 文件”这种特定的二进制文件格式所关联,Class 文件中包含了 Java虚拟机指令集和符号表以及若干其他辅助信息。

    1.2 Class 类的本质

    任何一个 Class 文件都对应着唯一一个类或接口的定义信息,但反过来说,Class 文件实际上它并不一定以磁盘文件的形式存在。Class 文件是一组以 8 位字节为基础单位的二进制流。

    1.3 Class 文件格式

    各个数据项目严格按照顺序紧凑地排列在 Class 文件之中,中间没有添加任何分隔符,这使得整个 Class 文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。Class 文件格式采用一种类似于 C 语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表。

    无符号数属于基本的数据类型,以 u1、u2、u4、u8 来分别代表 1 个字节、2 个字节、4 个字节和 8 个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照 UTF-8编码构成字符串值。

    表是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地以“_info”结尾。表用于描述有层次关系的复合结构的数据,整个 Class 文件本质上就是一张表。

    2.字节码指令

    2.1 加载和存储指令

    2.2 运算或算术指令

    2.3 类型转换指令

    2.4 创建类实例的指令

    2.5 创建数组的指令

    2.6 访问字段指令

    2.7 数组存取相关指令

    2.8 检查类实例类型的指令

    2.9 操作数栈管理指令

    2.10 控制转移指令

    2.11 方法调用指令

    dac08c14643e

    image.png

    2.12 方法返回指令

    2.13 异常处理指令

    2.14 同步指令

    3.类加载机制

    4.类加载器

    4.1 系统的类加载器

    4.2 双亲委派模型

    5.Tomcat 类加载机制

    6.方法调用详解

    6.1 解析

    6.2 静态分派

    6.3 动态分派

    6.4 基于栈的字节码解释执行引擎

    dac08c14643e

    image.png

    三.垃圾回收器和内存分配策略

    1.Java 中是值传递还是引用传递?

    2.引用类型

    3.基本垃圾回收算法

    3.1.1 引用计数(Reference Counting):

    比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为 0 的对象。此算法最致命的是无法处理循环引用的问题。

    3.1.2 可达性分析清理

    dac08c14643e

    image.png

    标记-清除(Mark-Sweep):此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。

    dac08c14643e

    image.png

    复制(Copying): 此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。次算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。

    dac08c14643e

    image.png

    标记-整理(Mark-Compact):此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,清除标记对象,并未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。

    3.1 按照基本回收策略分

    3.2 按分区对待的方式分

    3.3 按系统线程分

    4.分代处理垃圾

    5.JAVA 中垃圾回收 GC 的类型

    dac08c14643e

    image.png

    四、编写高效优雅 Java 程序

    1.面向对象

    1.1 构造器参数太多怎么办?

    用 builder 模式,用在

    (1)5 个或者 5 个以上的成员变量

    (2)参数不多,但是在未来,参数会增加

    Builder 模式:

    属于对象的创建模式,一般有

    (1)抽象建造者:一般来说是个接口,包含

    1)建造方法,建造部件的方法(不止一个)

    2)返回产品的方法

    (2) 具体建造者

    (3) 导演者,调用具体的建造者,创建产品对象

    (4)产品,需要建造的复杂对象

    对于客户端,创建导演者和具体建造者,并把具体建造者交给导演者,然后由客户端通知导演者操纵建造者进行产品的创建。

    在实际的应用过程中,有时会省略抽象建造者和导演者。

    1.2 不需要实例化的类应该构造器私有

    1.3 不要创建不必要的对象

    1.4 避免使用终结方法

    1.5 使类和成员的可访问性最小化

    1.6 使可变性最小化

    1.7 复合优先于继承

    1.8 接口优于抽象类

    2.方法

    2.1 可变参数要谨慎使用

    2.2 返回零长度的数组或集合,不要返回 null

    2.3 优先使用标准的异常

    3.通用程序设计

    dac08c14643e

    image.png

    五、性能优化

    一个 web 应用不是一个孤立的个体,它是一个系统的部分,系统中的每一部分都会影响整

    个系统的性能

    1.常用的性能评价/测试指标

    1.1 响应时间

    提交请求和返回该请求的响应之间使用的时间,一般比较关注平均响应时间。

    常用操作的响应时间列表:

    dac08c14643e

    image.png

    1.2 并发数

    同一时刻,对服务器有实际交互的请求数。

    和网站在线用户数的关联:1000 个同时在线用户数,可以估计并发数在 5%到 15%之间,也就是同时并发数在 50~150 之间。

    1.3 吞吐量

    对单位时间内完成的工作量(请求)的量度

    1.4 关系

    系统吞吐量和系统并发数以及响应时间的关系:

    理解为高速公路的通行状况:

    吞吐量是每天通过收费站的车辆数目(可以换算成收费站收取的高速费),并发数是高速公路上的正在行驶的车辆数目,响应时间是车速。车辆很少时,车速很快。但是收到的高速费也相应较少;

    随着高速公路上车辆数目的增多,车速略受影响,但是收到的高速费增加很快;

    随着车辆的继续增加,车速变得越来越慢,高速公路越来越堵,收费不增反降;

    如果车流量继续增加,超过某个极限后,任务偶然因素都会导致高速全部瘫痪,车走不动,当然后也收不着,而高速公路成了停车场(资源耗尽)。

    2.常用的性能优化手段

    2.1 避免过早优化

    2.2 进行系统性能测试

    2.3 寻找系统瓶颈,分而治之,逐步优化

    2.4 前端优化常用手段

    dac08c14643e

    image.png

    3 应用服务性能优化

    3.1 缓存

    3.1.1 缓存的基本原理和本质

    3.1.2 合理使用缓冲的准则

    3.1.3 分布式缓存与一致性哈希

    3.2 异步

    3.2.1 同步和异步,阻塞和非阻塞

    3.2.2 常见异步的手段

    3.3 集群

    dac08c14643e

    image.png

    3.4 应用相关

    3.4.1 代码级别

    3.4.2 并发编程

    3.4.3 资源的复用

    3.4.4 JVM

    3.4.5 GC 调优

    3.4.6 调优实战

    3.4.7 存储性能优化

    展开全文
  • 【Java面试系列】JVM与调优面试题

    万次阅读 2020-04-30 15:59:21
    热门系列: 【Java面试系列】2020年最新最全java面试题大全及答案解析 【Java虚拟机JVM系列】Java虚拟机原理哪家强?CSDN找老杨 【Java虚拟机JVM系列】GC配置及详解,持续输出,哒哒哒哒哒 【Java虚拟机JVM系列】为...
  • Tomcat 面试题汇总

    万次阅读 多人点赞 2018-08-09 15:11:05
    1、Tomcat的缺省端口是多少,怎么修改? 1)找到Tomcat目录下的conf文件夹 2)进入conf文件夹里面找到server.xml文件 3)打开server.xml文件 4)在server.xml文件里面找到下列信息 &amp;amp;lt;Connector...
  • tomcat调优

    2021-10-29 17:56:15
    深入学习企业级性能调优方案,同时提供高频面试题集锦,主要内容包括如下:1.连接器三大参数调优2.tomcat线程池调优3.反向代理调优4.动静分离调优5.应用安全调优6.配置安全调优
  • Tomcat面试题+http面试题+Nginx面试题+常见面试题

    千次阅读 多人点赞 2019-12-12 15:04:43
    Tomcat面试题 1、Tomcat的缺省端口是多少?怎么修改? 答:缺省端口是8080,若要修改,可以进入Tomcat的安装目录下找到conf目录下的server.xml文件,找到该文件中的Connector字段中的port。 2、Tomcat有哪几种...
  • Tomcat面试题总结

    2021-03-09 02:10:33
    1、Tomcat的缺省端口是多少,怎么修改?1)找到Tomcat目录下的conf文件夹2)进入conf文件夹里面找到server.xml文件3)打开server.xml文件4)在server.xml文件里面找到下列信息port="8080"改成你想要的端口2、Tomcat有哪...
  • 性能优化是什么?性能优化,简而言之,就是在不影响系统运行正确性的前提下,使之...今天就由京东资深技术官来详解「Java性能优化」问题,从JVM、Tomcat、MySQL三种调优方式来详细讲解,以下含一些面试题、脑图以及...
  • 怎样给 tomcat调优? 1.JVM参数调优 -Xms示JVM初始化堆的大小,-Xmx表示JVM堆的最大值。 这两个值的大小一般根据需要进行设置。当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃...
  • Tomcat 面试题(总结最全面的面试题!!!)

    千次阅读 多人点赞 2019-12-22 11:31:37
    Tomcat是一个应用服务器,比方说,我有个web项目是想让他运行,就可以在运行在tomcat平台上,如果开启就可以运行访问,如果停掉tomcat服务,那么无法访问了 2、Tomcat的默认端口是多少,怎么修改? 8080 修改方式:...
  • Tomcat相关的面试题出场的几率并不高,正式因为如此,很多人忽略了对Tomcat相关技能的掌握。 这次整理了Tomcat相关的系统架构,介绍了Server、Service、Connector、Container之间的关系,各个模块的功能,可以说把...
  • Tomcat常见面试题你都知道答案吗?

    万次阅读 2019-01-25 16:53:27
    请解释将Tomcat作为一个Windows 服务运行会带来哪些好处? 1)自动启动:对于需要在维护后远程重新启动系统的环境来说,这是至关重要的; 2)启动无活动用户登录的服务器:Tomcat通常在刀片服务器上运行,这些服务器...
  • Java面试题Tomcat的优化经验

    万次阅读 2015-10-07 15:32:11
     Tomcat作为Web服务器,它的处理性能直接关系到用户体验,下面是几种常见的优化措施: 一、掉对web.xml的监视,把jsp提前编辑成Servlet。有富余物理内存的情况,加大tomcat使用的jvm的内存 二、服务器资源  ...
  • Java经典面试题(其三)——JVM原理和调优

    万次阅读 多人点赞 2017-09-16 11:08:59
    Java经典面试题(其三)——JVM原理和调优一、什么是JVM  JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机...
  • 前言 性能优化是什么? 答:性能优化,简而言之,就是在不影响系统运行正确性的...今天就由阿里资深技术官来详解「性能优化」问题,从JVM、Tomcat、MySQL三种调优方式来详细讲解,以下含一些面试题、脑图以及调优文档
  • 怎样加大 tomcat的内存? 首先检查程序有没有限入死循环; 这个问题主要还是由java.lang.Out0fMemoryError:Java heap space引起的。 第一次出现这样的的问题以后,引发了其他的问题。在网上一查可能是JAVA的堆栈设置...
  • Tomcat常见面试题

    2021-06-07 20:27:41
    1、tomcat有哪些组件? 2、tomcat有哪些Connector? http ajp 3、tomcat的Valve的作用是什么? 给每一个虚拟主机定义访问日志 4、servlet的生命周期? Servlet 生命周期可被定义为从创建直到毁灭的整个过程...
  • Tomcat常用面试题

    2020-01-04 03:46:27
    一、Tomcat的缺省是多少,怎么修改Tomcat的缺省端口号是8080.修改Tomcat端口号:1.找到Tomcat目录下的conf文件夹2.进入conf文件夹里面找到server.x...
  • JVM面试题及答案整理(最新版)

    千次阅读 2021-08-05 08:28:41
    Jvm面试题及答案整理965道(2021最新版) 这是我收集的《Jvm 最常见的 965道面试题》高级Java面试问题列表。这些问题主要来自 JVM核心部分 ,你可能知道这些棘手的JVM 问题的答案,或者觉得这些不足以挑战你的 Java ...
  • 若有收获,请记得分享和转发哦对于工作3年左右的Java程序员来说,在面试大厂的过程中,面试官可能不会太关注你做了多少个项目、你的CRUD水平如何。更多的是关注你对某项技术点的理解深度,所以...
  • 40 道JVM面试题解答

    2021-01-19 00:32:56
    PhantomReference 实现 12、你做过 JVM 调优,说说如何查看 JVM 参数默认值? jps -v 可以查看 jvm 进程显示指定的参数 使用 -XX:+PrintFlagsFinal 可以看到 JVM 所有参数的值 jinfo 可以实时查看和调整虚拟机各项...
  • JVM调优 JVM 调优的参数可以在那设置参数值 说一下 JVM 调优的工具? 常用的 JVM 调优的参数都有哪些? JVM的GC收集器设置 Java内存模型 我们开发人员编写的Java代码是怎么让电脑认识的 首先先了解电脑是二进制的...
  • Netty与Tomcat的区别是什么? 什么是 Reactor 线程模型? Netty的架构与核心主件 Netty的工作模型是什么? Netty的逻辑架构是怎样的?有哪些核心组件? Netty组件的工作流程是怎样的? EventLoop 是一种什么...
  • 即将进入金三银四的黄金时段,所以很多人已经开始准备自己的面试抱佛脚了。今天我整理了6道关于tomcat的核心面试题以及参看答案,看完对于绝大多数人应对面试妥妥的。1、Tomcat的缺省端口...
  • 以下是一些比较常见的Tomcat面试题:JAVA高级架构​​​​​​​ 1,Tomcat的的缺省端口是多少,怎么修改? 2,tomcat有哪几种连接器运行模式(优化)? 3,Tomcat的有几种部署方式? 4,tomcat的容器是如何创建...
  • tomcat面试题

    2017-12-29 11:28:57
    1.tomcat给你你怎样去调优? 1. JVM参数调优:-Xms 表示JVM初始化堆的大小,-Xmx表示JVM堆的最大值。这两个值的大小一般根据需要进行设置。当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致...
  • 即将进入金三银四的黄金时段,所以很多人已经开始准备自己的面试抱佛脚了。今天我整理了6道关于tomcat的核心面试题以及参看答案,看完对于绝大多数人应对面试妥妥的。1、Tomcat的缺省端...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,429
精华内容 3,371
关键字:

tomcat调优面试题