java进程工具及tomcat性能调优
-
JVM内存管理
首先要明白一个概念——类加载器
class loader 类加载器,加载应用程序的类文件,及程序的类文件依赖到的其它的类文件到运行时区域中(一部分内存空间),然后交由执行引擎处理。
Java要执行并行任务,是靠java线程来实现的
那么线程运行在哪里呢?
运行时区域,它就是一段内存空间,如下图,有以下几种:
JVM内存管理.png - 方法区:线程共享; 用于存储被JVM加载的class信息、常量、静态变量、方法等;
- 堆:是线程共享的,是jvm所管理的内存中占用空间最大的一部分;也是GC(Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一)管理的主要区域;主要存储对象实例、数组等;
- Java栈:线程私有,存储线程自己的局部变量,放指令指针的,;
- PC寄存器:程序计数寄存器,线程私有的内存空间,程序的指令指针,每一个线程都有自己的上下文,下一次该运行哪一个指令,就放到这个寄存器中;
-
本地方法栈:线程私有
注意
方法区和堆内存是线程共享内存
Java栈、pc寄存器、本地方法栈是线程自己的内存
参考:
Java 内存区域和GC机制:http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html
Java垃圾回收(GC)机制详解:https://www.cnblogs.com/xiaoxi/p/6486852.html
-
堆内存区段
运行在内存上的JVM进程结构.png
Java编程语言是纯面向对象的,所以程序运行就是不断的创建对象,因为对象创建销毁不断的在发生着,对java本身来讲,堆内存成了运行时区域最大的一个内存区段,那么这个运行时区域的堆内存区段是如何划分的呢?
我们从下图来看:
主要有新生代、老年代、持久代(老版本(jdk1.6以前)有持久代,之后可能就没了) -
新生代:在此创建新的java对象,大多数创建完之后一次使用就结束了,活不过一次应用,每一个对象都有一个引用计数器,如果计数器为0,就表现这个对象没人用,就是该回收的垃圾,但也不一定,说不定现在没人用,一会就有人用了,所以说并不是引用计数器为0,就标识为垃圾的。而是需要等待那么一段时间,来确定是否标识为垃圾。
-
Eden区:创建新的java对象的放在此,过一会垃圾收集器来扫描,看下有没有计算器不为0的,如果有不为0的,就将这些对象挪到from区域里,但eden剩下的那些对象计数器为0的都当做垃圾回收了,空间收回来。当再次扫描时也扫描from段,如果里面还有活的,就挪
到to区域里,接着将from和eden区域计算器为0的都清理掉,回收空间。对于to段而言,可能一会再给挪到old区段去了。 -
存活区:分为to和from
-
老年代:存放两朝元老对象
-
总结:在eden区域创建对象,然后扫描,有活的就挪到from里,计算器为0的清理掉,下次再扫描时,因为from区域内已经有对象了,所以同时扫描from和eden,from里如果有活的就挪到to区域里,然后在to区域里集结的对象,一会一块挪到old区域里。这样to区域段就空了。这时再一轮扫描时,eden区域如果有活的就挪到to里,to如果有活的就挪到from里,from再集中挪到old。这样to和from的角色一直在循环转换。
Old区域清理垃圾方法是如果计算器为0的就清理,不为0的继续在old呆着
持久代是不会被回收的 -
问题
一般情况,一个java进程在运行时,它的堆内存不应该超过32G,如果超过,会产生一些垃圾收集等方面的问题,可能还会导致内存碎片,导致服务器性能下降等。假如我们给整个堆内存是20G。那么里面的新生代等区域该怎么分配呢? -
堆内存和里面划分的内存区段名称
Jvm可调参数
-Xmx:最大堆内存,它只包括新生代和老年代,因为持久代是不会变化的,而且不会回收一般在指定的配置文件定义,例如对于tomcat来讲,如果安装的是绿色包,它就会解压目录的启动脚本catalina.sh里面定义
-Xms:初始堆内存,s表示启动时之意。也就是初始化的堆内存大小,如果不够用,就会扩展,一直扩展到最大堆内存大小定义的值。建议将初始堆内存和最大堆内存设置为一样大小,这样就省得中间去申请空间,提升了性能。
-XX:NewSize:新生代空间初始大小,新版本可能叫-Xmn了
-XX:MaxSize:新生代空间的最大值,MaxSize-NewSize=新生代可用的空间大小(reserved)
-Xms -NewSize=老年代的初始空间大小
-Xmx- MaxSize=老年代的最大空间大小
老年代的最大值-老年代的初始值=老年代的可用空间大小(reserved)
-XX:MaxPermSize:持久代的最大值
-XX:PermSize:持久代的初始值
我们不仅仅可以调整上述参数,还可以调整下述参数
-Xss:每个线程的栈大小,也就是java栈,多数设置为1M
-XX:NewRatio:新生代与老年代的比值,我们一般不需要特意指定新生代和老年代具体多数空间,而可以靠他们的空间比值来设置
例:
-XX:NewRatio=5 这个5表示1:5之意,而且都是新生代小,老年代大,所以各占六分之一和六分之五
-XX:SurvivorRatio:Eden区与Survivor(存活区,等于from+to)的大小比值,如果设置为8,同上,就是from占十分之一,to占十分之一,eden占十分之八
特例:
-XX:+UseParallelGC表示使用老年代的垃圾回收算法
-XX:+UseParNewGC表示使用并行的垃圾回收算法,例如新生代的
-XX:+PrintGC 表示运行过程中输出GC(垃圾收集器)的信息
-XX:+PrintGCDetail:显示GC的详细信息 -
JVM常用的分析工具:
image.png
jps:用来查看运行的所有jvm进程,也就是java进程;
例如:本机运行了一个tomcat进程,根据pid进程号就知道
jinfo:查看进程的运行环境参数,主要是jvm命令行参数;
jstat:对jvm应用程序的资源和性能进行实时监控,类似于vmstat;
jstack:查看所有线程栈(java栈)的运行状态;
jmap:查看jvm占用物理内存的状态;
jconsole:图形工具。
jvisualvm:图形工具
jps:Java 虚拟机进程状态管理工具
-q:静默模式;
-v:显示传递给jvm的命令行参数;
-m:输出传入main方法的参数;
-l:输出main类或jar完全限定名称;
-V:显示通过flag文件传递给jvm的参数;
[<hostid>]:主机id,默认为localhost;
jinfo:输出给定的java进程的所有配置信息;注意查看的进程需要目前存在
jinfo [option] <pid>
-flags:to print VM flags
-sysprops:to print Java system properties
-flag <name>:to print the value of the named VM flag
jstack:查看指定的java进程的线程栈的相关信息;
jstack -F [-m] [-l] <pid>
-l:long listings,会显示额外的锁信息,因此,发生死锁时常用此选项;
-m:混合模式,既输出java堆栈信息,也输出C/C++堆栈信息;
-F:当使用“jstack -l PID"无响应,可以使用-F强制输出信息;
jstat:输出指定的java进程的统计信息
jstat -help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
# jstat -options
-class:class loader
-compiler:JIT
-gc:gc
-gccapacity:统计堆中各代的容量
-gccause:
-gcmetacapacity
-gcnew:新生代
-gcnewcapacity
-gcold:老年代
-gcoldcapacity
-gcutil
-printcompilation
[<interval> [<count>]]
interval:时间间隔,单位是毫秒;
count:显示的次数;
-gc:
YGC:新生代的垃圾回收次数;
YGCT:新生代垃圾回收消耗的时长;
FGC:Full GC的次数;
FGCT:Full GC消耗的时长;
GCT:GC消耗的总时长;
jmap:Memory Map, 用于查看堆内存的使用状态;
jhat:Java Heap Analysis Tool
jmap [option] <pid>
查看堆空间的详细信息:
jmap -heap <pid>
查看堆内存中的对象的数目:
jmap -histo[:live] <pid>
live:只统计活动对象;
保存堆内存数据至文件中,而后使用jvisualvm或jhat进行查看:
jmap -dump:<dump-options> <pid>
dump-options:
live dump only live objects; if not specified, all objects in the heap are dumped.
format=b binary format
file=<file> dump heap to <file>
Tomcat的常用优化配置:
(1) 内存空间:
/etc/sysconfig/tomcat
JAVA_OPTS="-server -Xms -Xmx -XX:NewSize= -XX:MaxNewSize= -XX:PermSize= -XX:MaxPermSize="
-server:服务器模型
-Xms:堆内存初始化大小;
-Xmx:堆内存空间上限;
-XX:NewSize=:新生代空间初始化大小;
-XX:MaxNewSize=:新生代空间最大值;
-XX:PermSize=:持久代空间初始化大小;
-XX:MaxPermSize=:持久代空间最大值;
(2) 线程池设置:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />```
常用属性:
maxThreads:最大线程数;
minSpareThreads:最小空闲线程数; 类似于httpd的worker模型
maxSpareThreads:最大空闲线程数;
acceptCount:等待队列的最大长度;
URIEncoding:URI地址编码格式,建议使用UTF-8;
enableLookups:是否启用dns解析,建议禁用;
compression:是否启用传输压缩机制,建议“on";
compressionMinSize:启用压缩传输的数据流最小值,单位是字节;至少多少才压缩
compressableMimeType:定义启用压缩功能的MIME类型;
text/html, text/xml, text/css, text/javascript
(3) 禁用8005端口;
<Server port="-1" shutdown="SHUTDOWN">
将端口设置为“-1”即可
示例:
(4) 隐藏版本信息:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" Server="SOME STRING" />
示例:
``