首页 > 代码库 > JVM内存管理(转)
JVM内存管理(转)
转载出处:http://blog.csdn.net/wind5shy/article/details/8349559
模型
JVM运行时数据区域
JVM执行Java程序的过程中,会使用到各种数据区域,这些区域有各自的用途、创建和销毁时间。根据《Java虚拟机规范(第二版)》(下文称VM Spec)的规定,JVM包括下列几个运行时数据区域:
1.程序计数器(Program Counter Register):
每一个Java线程都有一个程序计数器来用于保存程序执行到当前方法的哪一个指令,对于非Native方法,这个区域记录的是正在执行的VM原语的地址,如果正在执行的是Natvie方法,这个区域则为空(undefined)。此内存区域是唯一一个在VM Spec中没有规定任何OutOfMemoryError情况的区域。
2.Java虚拟机栈(Java Virtual Machine Stacks)
与程序计数器一样,VM栈的生命周期也是与线程相同。VM栈描述的是Java方法调用的内存模型:每个方法被执行的时候,都会同时创建一个帧(Frame)用于存储本地变量表、操作栈、动态链接、方法出入口等信息。每一个方法的调用至完成,就意味着一个帧在VM栈中的入栈至出栈的过程。
经常有人把Java内存简单的区分为堆内存(Heap)和栈内存(Stack),实际中的区域远比这种观点复杂,这样划分只是说明与变量定义密切相关的内存区域是这两块。其中所指的“堆”后面会专门描述,而所指的“栈”就是VM栈中各个帧的本地变量表部分。本地变量表存放了编译期可知的各种标量类型(boolean、byte、char、short、int、float、long、double)、对象引用(不是对象本身,仅仅是一个引用指针)、方法返回地址等。其中long和double会占用2个本地变量空间(32bit),其余占用1个。本地变量表在进入方法时进行分配,
当进入一个方法时,这个方法需要在帧中分配多大的本地变量是一件完全确定的事情,在方法运行期间不改变本地变量表的大小。
在VM Spec中对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果VM栈可以动态扩展(VM Spec中允许固定长度的VM栈),当扩展时无法申请到足够内存则抛出OutOfMemoryError异常。
3.本地方法栈(Native Method Stacks)
本地方法栈与VM栈所发挥作用是类似的,只不过VM栈为虚拟机运行VM原语服务,而本地方法栈是为虚拟机使用到的Native方法服务。它的实现的语言、方式与结构并没有强制规定,甚至有的虚拟机(譬如Sun Hotspot虚拟机)直接就把本地方法栈和VM栈合二为一。和VM栈一样,这个区域也会抛出StackOverflowError和OutOfMemoryError异常。
4.Java堆(Java Heap)
对于绝大多数应用来说,Java堆是虚拟机管理最大的一块内存。Java堆是被所有线程共享的,在虚拟机启动时创建。Java堆的唯一目的就是存放对象实例,绝大部分的对象实例都在这里分配。
Java堆内还有更细致的划分:新生代、老年代,再细致一点的:eden、from survivor、to survivor,甚至更细粒度的本地线程分配缓冲(TLAB)等,无论对Java堆如何划分,目的都是为了更好的回收内存,或者更快的分配内存。
根据VM Spec的要求,Java堆可以处于物理上不连续的内存空间,它逻辑上是连续的即可,就像我们的磁盘空间一样。实现时可以选择实现成固定大小的,也可以是可扩展的,不过当前所有商业的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。如果在堆中无法分配内存,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
5.方法区(Method Area)
叫“方法区”可能认识它的人还不太多,如果叫永久代(Permanent Generation)它的粉丝也许就多了。它还有个别名叫做Non-Heap(非堆)。
方法区中存放了每个Class的结构信息,包括常量池、字段描述、方法描述等等。VM Space描述中对这个区域的限制非常宽松,除了和Java堆一样不需要连续的内存,也可以选择固定大小或者可扩展外,甚至可以选择不实现垃圾收集。相对来说,垃圾收集行为在这个区域是相对比较少发生的,但并不是某些描述那样永久代不会发生GC(至少对当前主流的商业JVM实现来说是如此),这里的GC主要是对常量池的回收和对类的卸载,虽然回收的“成绩”一般也比较差强人意,尤其是类卸载,条件相当苛刻。
6.运行时常量池(Runtime Constant Pool)
Class文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量表(constant_pool table),用于存放编译期已可知的常量,这部分内容将在类加载后进入方法区(永久代)存放。但是Java语言并不要求常量一定只有编译期预置入Class的常量表的内容才能进入方法区常量池,运行期间也可将新内容放入常量池(最典型的String.intern()方法)。
运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法在申请到内存时会抛出OutOfMemoryError异常。
7.本机直接内存(Direct Memory)
直接内存并不是虚拟机运行时数据区的一部分,它根本就是本机内存而不是VM直接管理的区域。但是这部分内存也会导致OutOfMemoryError异常出现。
在JDK1.4中新加入了NIO类,引入一种基于渠道与缓冲区的I/O方式,它可以通过本机Native函数库直接分配本机内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java对和本机堆中来回复制数据。
显然本机直接内存的分配不会受到Java堆大小的限制,但是即然是内存那肯定还是要受到本机物理内存(包括SWAP区或者Windows虚拟内存)的限制的,一般服务器管理员配置JVM参数时,会根据实际内存设置-Xmx等参数信息,但经常忽略掉直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),而导致动态扩展时出现OutOfMemoryError异常。
Java堆
新生代(Young Generation)
大部分的对象的内存分配和回收在这里完成。
Eden
新建的对象分配在此,新生代GC后被清空。
Survivor
存储至少经过一次GC存活下来的对象,以增大该对象在提升至老生代前被回收的机会。
From Space
在新生代GC后被清空,GC后存活的对象放入老生代。
To Space
Eden中在新生代GC后存活的对象放在此。
老生代(Old Generation)
永生代(Permanent Generation)
垃圾回收
注意垃圾回收器Garbage Collector(简称Collector)和垃圾回收Garbage Collection(简称GC)的区别。
垃圾回收器Collector
Collector的职责
· 分配内存。
· 保证有引用的内存不被释放。
· 回收没有指针引用的内存。
对象被引用称为活对象,对象没有被引用称为垃圾对象/垃圾/垃圾内存,找到垃圾对象并回收是Collector的一个主要工作,该过程称为GC。
好的Collector的特性
· 保证有引用的对象不被GC。
· 快速的回收内存垃圾。
· 在程序运行期间GC要高效,尽量少的影响程序运行。和大部分的计算机问题一样,这是一个关于空间,时间,效率平衡的问题。
· 避免内存碎片,内存碎片导致占用大量内存的大对象内存申请难以满足。可以采用Compaction技术避免内存碎片。Compaction技术:把活对象移向连续内存区的一端,回收其余的内存以便以后的分配。
· 良好的扩展性,内存分配和GC在多核机器上不应该成为性能瓶颈。
设计或选择Collector
· 串行或并行。
串行Collector在多核上也只有一个线程在运行,并行Collector可以同时有多个线程执行GC,但是其算法更复杂。
· 并发或Stop the World。
Stop the World Collection执行GC时,需要冻住所有内存,因此更简单一些,但是,在GC时,程序是被挂起的。并发GC时,程序和GC同时执行,当然,一般的并发GC算法还是需要一些Stop the World时间。
· Compacting or Non-compacting orCopying
Compacting: 去除内存碎片,回收内存慢,分配内存快。
Non-compacting: 容易产生内存碎片,回收内存快,分配内存慢,对大对象内存分配支持不好。
Copying: 复制活对象到新的内存区域,原有内存直接回收,需要额外的时间来做复制,额外的空间来做存储。
GC性能指标
· Throughput: 程序时间(不包含GC时间)/总时间。
· GC overhead: GC时间/总时间。
· Pause time: GC运行时程序挂起时间。
· Frequency of GC: GC频率。
· Footprint: Size度量,如堆大小。
· Promptness:对象变为垃圾到该垃圾被回收后内存可用的时间。
分代GC
分代GC把内存划分为多个代(内存区域),每个代存储不同年龄的对象。常见的分为2代,young和old。
分配内存时,先从新生代分配,如果新生代已满,可以执行GC(可能导致对象提升),如果有空间,则分配,如果新生代还是没有空间,可以对整个内存堆GC。
新生代GC后还存活的对象可以提升到老生代。
该机制基于以下观察事实:
1. 大部分新分配的对象很快就没有引用了,变成垃圾。
2. 很少有老生代对象引用新生代对象。
基于代内存存储对象的特性,对不同代的内存可以使用不同的GC算法。
新生代GC需要高效,快速,频繁的执行,关注点主要在速度上。
老生代由于增长缓慢,因此GC不频繁,但是其内存空间比较大,因此,需要更长时间才能执行完GC。关注点在内存空间利用率上。
快速内存分配
大部分的内存分配请求发生时,Collector都有一块大的连续内存块,简单的内存大小计算和指针移动就可以分配内存了。因此非常快速。该技术称为bump-the-pointer技术。
对于多线程的内存分配,每个线程使用Thread Local Allocation Buffer(TLAB)进行分配,因此还是很高效。TLAB可以看作一个线程的特殊代。只有TLAB满的时候才需要进行同步操作。
GC根集合
GC运行时当前程序可以直接访问的对象。如线程中当前调用栈的方法参数,局部变量,静态变量,当前线程对象等等。
Collector根据GC根集合来寻找所有活对象。GC根集合不可达对象自然就是垃圾了。
Serial Collector
单线程,Young and old GC是串行,stop the world GC的。
Young GC
Eden中活对象copy到to survivor中,大对象直接进老生代。
From survivor中相对老的活对象进入老生代,相对年轻的对象进入to survivor中。
如果to survivor放不下活对象,则这些活对象直接进入old。
经历过young GC,Eden和from survivor都变成空的内存区域,to survivor存储有活的对象。To survivor和from survivor角色互换。
Full (Old/Permanent) GC
Mark-sweep-compact算法。
S1 标识哪些对象是活的对象。
S2 标识哪些对象是垃圾。
S3 把活的对象压缩到内存的一端,以便可以使用bump-the-pointer处理以后的内存分配请求。
非server-class machine 的默认GC。
Parallel Collector/Throughput Collector
利用了现代计算机大部分都是多核的事实。
Young GC
和Serial Collector一样,是一个stop the world和copying Collector。只不过是多线程并行扫描和做copy,提高速度,减少了stop the world的时间,增大了throughput。
Full (Old/Permanent) GC
和serial collector一样。Mark-sweep-compact算法。单线程。
Server-class machine的默认GC。
Parallel Compacting Collector
Young GC。
和Parallel Collector一样。
Full (Old/Permanent) GC
Stop the world,并且多线程并发GC。
每一代被划分为一些长度固定的区域。
第1步(mark phase),GC根集合划分后分发给多个GC线程,每个GC线程更新可达活对象所在区域的信息(活对象的内存位置,大小)。
第2步(summary phase),操作在区域上,而不是对象上。由于以前GC的影响,内存的一端活对象的密度比较高,在该阶段找到一个临界点,该临界点以前的区域由于活对象内存密度高,不参与GC,不做compact。该临界点之后的区域参与GC,做compact。该阶段为单线程执行。
第3步(compact phase)。GC多线程使用summary info做回收和compact工作。
可以设置GC线程数,防止GC线程长时间占有整台机器的资源。
-XX:ParallelGCThreads=n
Concurrent Mark Sweep Collector (CMS)
Young GC
和Parallel Collector一样。
Full (Old/Permanent) GC
GC和程序并发执行。
Initial Phase:短暂停,标记GC根集合,单线程执行。
Concurrent marking phase: GC多线程标记从根集合可达的所有活对象,程序和GC并发运行。由于是并发运行,有可能有活对象没有被标记上。
concurrent pre-clean:单线程,并发执行。
Remark phase:短暂停,多线程标记在Concurrentmarking phase中有变化的相关对象。
Concurrent sweep phase:和程序并发执行,单线程执行,不做compacting。
concurrent reset:单线程,并发执行。
CMS不做compacting,不能使用bump-the-pointer技术,只能使用传统的内存空闲链表技术。
导致内存分配变慢,影响了新生代的GC速度,因为Young的GC如果有对象提升的话依赖于Old的内存分配。
CMS需要更多的内存空间,因为markphase时程序还是在运行,程序可以申请更多的old空间。在mark phase中,CMS保证标识活对象,但是该过程中,活对象可能转变为垃圾,只能等待下一次GC才能回收。
和其他Collector不同,CMS不是等到old满时才GC,基于以前的统计数据(GC时间,Old空间消耗速度)来决定何时GC。CMS GC也可以基于old空间的占用率。
Incremental Mode。
CMS的concurrent phase可以是渐进式执行。以减少程序的一次暂停时间。
4种Collector的对比和适用场景
直到jdk1.3.1,java只提供Serial Collector,Serial Collector在多核的机器上表现比较差。主要是throughput比较差。
大型应用(大内存,多核)应该选用并行Collector。
· Serial Collector:大多数client-style机器。对于低程序暂停时间没有需求的程序。
· Parallel Collector:多核机器,对于低程序暂停时间没有需求的程序。
· Parallel Compacting Collector:多核机器,对于低程序暂停时间有需求的程序。
· CMS Collector:和ParallelCompacting Collector相比,降低了程序暂停时间,但是young GC程序暂停时间变长,需要更大的堆空间,降低了程序的throughput。
优化
堆内存与GC
自动优化Ergonomics
J2SE 5.0后,Collector的选择,堆大小的选择,VM(client还是server)的选择,都可以依赖平台和OS来做自动选择。
JVM会自动选择使用server mode还是client mode。但是我们一样可以手工设置。t
Server-class machine的选择:
2个或更多的处理器
And
2G或更多的物理内存
And
不是32bits,windows OS。
Client-class
The client JVM
The serial collector
Initial heap size = 4M
Max heap size=64M
Server-class
The server JVM
The parallel collector
Initial heap size= 1/64物理内存(>=32M),最大1G。
Max heap size=1/4物理内存,最大1G。
基于行为的调优
可以基于最大暂停时间或throughput。
· -XX:MaxGCPauseMillis=n
指示vm调整堆大小和其他参数来满足这个时间需求。如果vm不满足该目标,则减小堆大小来满足该目标。该目标没有默认值。
· -XX:GCTimeRatio=n
GC time/APP time=1/(1+n)
如n=99表示GC时间占整个运行时间的1%。
如果该目标不能满足,则增大堆大小来满足该目标。默认值n=99。
· Footprint Goal
如果最大暂停时间和Throughput目标都满足了,则减少堆大小直到有一个目标不满足,然后又回调。
目标优先级:
最大暂停时间>Throughput>footprint。
手动调优
由于有了Ergonomics,第一个建议就是不要手工去配置各种参数。让系统自己去根据平台和OS来选择。然后观测性能,如果OK的话,不用搞了。但是Ergonomics也不是万能的。因此还是需要程序员来手工搞。注意性能问题一定要测量/调优/测量/调优不停的循环下去。
Vm mode 选择
· Java –server:server mode.
· Java –client:client mode.
观测性能主要使用gc的统计信息
· -XX:+PrintGC:输出GC信息。
· -XX:+PrintGCDetail:输出GC详细信息。
· -XX:+PrintGCTimeStamps:输出时间戳,和–XX:+PrintGC或–XX:+PrintGCDetails一起使用。
· -Xloggc::gc.log 输出到指定文件。
1 决定堆内存大小
决定整个堆内存的大小。内存的大小对于Collector的性能影响是最大的。
可以决定堆空间的起始值和最大值,大型程序可以考虑把起始值调大,避免程序启动时频繁GC和内存扩展申请,可能的话最好将最小值和最大值设成一致。
堆空间中可用内存的比例范围,vm会动态管理堆内存来满足该比例范围。
· -Xms:初始堆大小,默认为物理内存的1/64(<1GB);默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制。
· -Xmx:最大堆大小,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。
· -XX:MinHeapFreeRatio=n
· -XX:MaxHeapFreeRatio=n
2 决定代空间大小
新生代空间越大,则新生代(minor)GC的频率越小。但是,给定堆内存大小,新生代空间大,则full/major GC频率变大。
如果没有过多的Full GC或者过长的暂停时间问题,给新生代尽量大的空间。
YoungGeneration Guarantee
对于serial collector,当执行新生代 GC时,必须保证老生代中有可用的空间来处理最坏情况(即eden和survivor空间中的对象都是活对象,需要提升至老生代),如果不满足,则该新生代GC触发full GC。所以对于serial collector,设置eden+survivor的内存不要大过老生代内存。
其他collector不做该保证,只有老生代无法存储提升对象时才触发full GC。
对于其他collector,由于多线程做新生代 GC时,考虑到最坏情况,每个线程要在老生代内存预留一定空间做对象提升,因此可能导致内存碎片。因此老生代内存应该调整的更大一些。
· -Xmn:新生代的内存空间大小,在保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
· -XX:NewSize=n:新生代初始大小。
· -XX:MaxNewSize=n:新生代上限。
· -XX:NewRatio=n:新生代和老生代的比例。
· -XX:SurvivorRatio=n:新生代中Eden区域与Survivor区域的容量比值,默认值为8。两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。
· -XX:PermSize=n:永生代初始大小,默认值为物理内存的1/64。
· -XX:MaxPermSize=n:永生代上限,默认值为物理内存的1/4。
3.决定使用Collector
Collector选择
· -XX:+UseSerialGC Serial
· -XX:+UseParallelGC Parallel
· -XX:+UseParallelOldGC Parallel compacting
· -XX:+UseConcMarkSweepGC Concurrent mark–sweep (CMS)
Parallel和Parallel Compacting Collector
· -XX:ParallelGCThreads=n:并行收集器的线程数。
· -XX:MaxGCPauseMillis=n
· -XX:GCTimeRatio=n
设定目标好于明确设定参数值。
为了增大Throughput,堆大小需要变大。可以把堆大小设为物理内存允许的最大值(同时程序不swapping)来检测该环境可以支持的最大throughput。
为了减小最大暂停时间和footprint,堆大小需要变小。
2个目标有一定的矛盾,因此要视具体应用场景,做平衡。
CMSCollector
· -XX:+CMSIncrementalMode:启动增量模式
· -XX:+CMSIncrementalPacing:依据收集的统计信息启用增量模式自动调节占空比
· -XX:ParallelGCThreads=n
· -XX:CMSInitiatingOccupancyFraction=n:默认68。
· -XX:+UseCMSInitiatingOccupancyOnly:使vm只使用old内存占用比来触发CMSGC。
非堆内存
· -Xss :设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成。
· -XX:MaxDirectMemorySize:本机直接内存大小上限,默认和堆(-Xmx)内存上限一致。
检测
java工具
freeMemory(),totalMemory(),maxMemory()
java.lang.Runtime类中的freeMemory(), totalMemory(), maxMemory()这几个方法的反映的都是 java这个进程的内存情况,跟操作系统的内存根本没有关系。
maxMemory()这个方法返回的是java虚拟机(这个进程)能构从操作系统那里挖到的最大的内存,以字节为单位,如果在运行java程序的时候,没有添加-Xmx参数,那么就是jvm默认的可以使用内存大小,client为64M,server为1G。如果添加了-Xmx参数,将以这个参数后面的值为准。
totalMemory()这个方法返回的是java虚拟机现在已经从操作系统那里挖过来的内存大小,也就是java虚拟机这个进程当时所占用的所有内存。如果在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的从操作系统那里挖的,基本上是用多少挖多少,直到挖到maxMemory()为止,所以totalMemory()是慢慢增大的。如果用了-Xms参数,程序在启动的时候就会无条件的从操作系统中挖 -Xms后面定义的内存数,然后在这些内存用的差不多的时候,再去挖。
freeMemory()是什么呢,刚才讲到如果在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的从操 作系统那里挖的,基本上是用多少挖多少,但是java虚拟机100%的情况下是会稍微多挖一点的,这些挖过来而又没有用上的内存,实际上就是 freeMemory(),所以freeMemory()的值一般情况下都是很小的,但是如果你在运行java程序的时候使用了-Xms,这个时候因为程序在启动的时候就会无条件的从操作系统中挖-Xms后面定义的内存数,这个时候,挖过来的内存可能大部分没用上,所以这个时候freeMemory()可能会有些大。
jstack
如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。目前只有在Solaris和Linux的JDK版本里面才有。
例子:
jstack 6448
jconsole
jconsole是基于Java ManagementExtensions (JMX)的实时图形化监测工具,这个工具利用了内建到JVM里面的JMX指令来提供实时的性能和资源的监控,包括了Java程序的内存使用,Heap size, 线程的状态,类的分配状态和空间使用等等。
jinfo
jinfo可以从core文件或进程中获得Java应用程序的配置信息,目前只有在Solaris和Linux的JDK版本里面才有。
jmap
jmap 可以从core文件或进程中获得jvm的相关内存信息,包括Heapsize, Perm size等等,目前只有在Solaris和Linux的JDK版本里面才有。
参数如下:
· -heap:打印jvm heap的情况
· -histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
· -histo:live :同上,但是只答应存活对象的情况
· -permstat:打印permanentgeneration heap情况
例子:
jmap -heap 2083
jmap -histo 2083 | jmap-histo:live 2083
jstat
利用了JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控等等。
具体参数如下:
· -class:统计classloader行为信息
· -compile:统计编译行为信息
· -gc:统计jdk gc时heap信息
· -gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区)相应的heap容量情况
· -gccause:统计gc的情况,(同-gcutil)和引起gc的事件
· -gcnew:统计gc时,新生代的情况
· -gcnewcapacity:统计gc时,新生代heap容量
· -gcold:统计gc时,老年区的情况
· -gcoldcapacity:统计gc时,老年区heap容量
· -gcpermcapacity:统计gc时,permanent区heap容量
· -gcutil:统计gc时,heap情况
一般比较常用的几个参数是:
jstat -class 2083 1000 10 (每隔1秒监控一次,一共做10次)
输出内容含义如下:
Loaded Numberof classes loaded.
Bytes Numberof Kbytes loaded.
Unloaded Numberof classes unloaded.
Bytes Numberof Kbytes unloaded.
Time Timespent performing class load and unload operations.
jstat -gc 2083 2000 20(每隔2秒监控一次,共做10)
输出内容含义如下:
S0C Currentsurvivor space 0 capacity (KB).
EC Currenteden space capacity (KB).
EU Edenspace utilization (KB).
OC Currentold space capacity (KB).
OU Oldspace utilization (KB).
PC Currentpermanent space capacity (KB).
PU Permanentspace utilization (KB).
YGC Numberof young generation GC Events.
YGCT Younggeneration garbage collection time.
FGC Numberof full GC events.
FGCT Fullgarbage collection time.
GCT Totalgarbage collection time.
linux命令
top
TOP是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止该程序为止.比较准确的说,top命令提供了实时的对系统处理器的状态监视.它将显示系统中CPU最“敏感”的任务列表.该命令可以按CPU使用.内存使用和执行时间对任务进行排序;而且该命令的很多特性都可以通过交互式命令或者在个人定制文件中进行设定.
top - 12:38:33 up 50 days, 23:15, 7 users, load average: 60.58, 61.14, 61.22
Tasks: 203 total, 60 running, 139 sleeping, 4 stopped, 0 zombie
Cpu(s) : 27.0%us, 73.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1939780k total, 1375280kused, 564500k free, 109680k buffers
Swap: 4401800k total, 497456kused, 3904344k free, 848712k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4338oracle 25 0 627m 209m 207m R 0 11.0297:14.76 oracle
4267oracle 25 0 626m 144m 143m R 6 7.6 89:16.62 oracle
3458oracle 25 0 672m 133m 124m R 0 7.1 1283:08 oracle
3478oracle 25 0 672m 124m 115m R 0 6.6 1272:30 oracle
3395oracle 25 0 672m 122m 113m R 0 6.5 1270:03 oracle
3480oracle 25 0 672m 122m 109m R 8 6.4 1274:13 oracle
3399oracle 25 0 672m 121m 110m R 0 6.4 1279:37 oracle
4261oracle 25 0 634m 100m 99m R 0 5.3 86:13.90 oracle
25737 oracle 25 0 632m 81m 74m R 0 4.3 272:35.42 oracle
7072oracle 25 0 626m 72m 71m R 0 3.8 6:35.68 oracle
16073 oracle 25 0 630m 68m 63m R 8 3.6 175:20.36 oracle
16140 oracle 25 0 630m 66m 60m R 0 3.5 175:13.42 oracle
16122 oracle 25 0 630m 66m 60m R 0 3.5 176:47.73 oracle
786oracle 25 0 627m 63m 63m R 0 3.4 1:54.93 oracle
4271oracle 25 0 627m 59m 58m R 8 3.1 86:09.64 oracle
4273oracle 25 0 627m 57m 56m R 8 3.0 84:38.20 oracle
22670 oracle 25 0 626m 50m 49m R 0 2.7 84:55.82 oracle
统计信息区前五行是系统整体的统计信息。
1. 第一行是任务队列信息
12:38:33 | 当前时间 |
up 50days | 系统运行时间,格式为时:分 |
1 user | 当前登录用户数 |
load average: 0.06, 0.60, 0.48 | 系统负载,即任务队列的平均长度。 三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值。 |
2. 第二、三行为进程和CPU的信息
当有多个CPU时,这些内容可能会超过两行。
Tasks: 29 total | 进程总数 |
1 running | 正在运行的进程数 |
28 sleeping | 睡眠的进程数 |
0 stopped | 停止的进程数 |
0 zombie | 僵尸进程数 |
Cpu(s): 0.3% us | 用户空间占用CPU百分比 |
1.0% sy | 内核空间占用CPU百分比 |
0.0% ni | 用户进程空间内改变过优先级的进程占用CPU百分比 |
98.7% id | 空闲CPU百分比 |
0.0% wa | 等待输入输出的CPU时间百分比 |
0.0% hi | |
0.0% si |
3. 第四五行为内存信息。
Mem: 191272k total | 物理内存总量 |
173656k used | 使用的物理内存总量 |
17616k free | 空闲内存总量 |
22052k buffers | 用作内核缓存的内存量 |
Swap: 192772k total | 交换区总量 |
0k used | 使用的交换区总量 |
192772k free | 空闲交换区总量 |
123988k cached | 缓冲的交换区总量。 内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖, 该数值即为这些内容已存在于内存中的交换区的大小。相应的内存再次被换出时可不必再对交换区写入。 |
进程信息
列名 | 含义 |
PID | 进程id |
PPID | 父进程id |
RUSER | Real user name |
UID | 进程所有者的用户id |
USER | 进程所有者的用户名 |
GROUP | 进程所有者的组名 |
TTY | 启动进程的终端名。不是从终端启动的进程则显示为 ? |
PR | 优先级 |
NI | nice值。负值表示高优先级,正值表示低优先级 |
P | 最后使用的CPU,仅在多CPU环境下有意义 |
%CPU | 上次更新到现在的CPU时间占用百分比 |
TIME | 进程使用的CPU时间总计,单位秒 |
TIME+ | 进程使用的CPU时间总计,单位1/100秒 |
%MEM | 进程使用的物理内存百分比 |
VIRT | 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES |
SWAP | 进程使用的虚拟内存中,被换出的大小,单位kb。 |
RES | 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA |
CODE | 可执行代码占用的物理内存大小,单位kb |
DATA | 可执行代码以外的部分(数据段+栈)占用的物理内存大小,单位kb |
SHR | 共享内存大小,单位kb |
nFLT | 页面错误次数 |
nDRT | 最后一次写入到现在,被修改过的页面数。 |
S | 进程状态。 |
COMMAND | 命令名/命令行 |
WCHAN | 若该进程在睡眠,则显示睡眠中的系统函数名 |
Flags | 任务标志,参考 sched.h |
pmap
[root@CentOS5 ~]#pmap -d 9639
9639: /usr/local/apache2/bin/httpd -k start
Address Kbytes Mode Offset Device Mapping
00110000 28 r-x-- 0000000000000000 008:00003librt-2.5.so
00117000 4 r---- 0000000000006000 008:00003librt-2.5.so
00118000 4 rw--- 0000000000007000 008:00003librt-2.5.so
00119000 1276 r-x-- 0000000000000000 008:00003 libc-2.5.so
00258000 8 r---- 000000000013f000 008:00003libc-2.5.so
0025a000 4 rw--- 0000000000141000 008:00003libc-2.5.so
0025b000 12 rw--- 000000000025b000 000:00000 [ anon ]
0025e000 60 r-x-- 0000000000000000 008:00003libexslt.so.0.8.12
0026d000 4 rw--- 000000000000e000 008:00003libexslt.so.0.8.12
0026e000 268 r-x-- 0000000000000000 008:00003 libmysqlclient.so.16.0.0
002b1000 168 rw--- 0000000000042000 008:00003 libmysqlclient.so.16.0.0
002db000 4 rw--- 00000000002db000 000:00000 [ anon ]
002dc000 448 r-x-- 0000000000000000 008:00003 libfreetype.so.6.4.0
0034c000 16 rw--- 000000000006f000 008:00003libfreetype.so.6.4.0
00350000 72 r-x-- 0000000000000000 008:00003libz.so.1.2.3
00362000 4 rw--- 0000000000011000 008:00003libz.so.1.2.3
00363000 60 r-x-- 0000000000000000 008:00003libresolv-2.5.so
00372000 4 r---- 000000000000e000 008:00003libresolv-2.5.so
00373000 4 rw--- 000000000000f000 008:00003libresolv-2.5.so
00374000 8 rw--- 0000000000374000 000:00000 [ anon ]
00376000 76 r-x-- 0000000000000000 008:00003libnsl-2.5.so
00389000 4 r---- 0000000000012000 008:00003libnsl-2.5.so
0038a000 4 rw--- 0000000000013000 008:00003libnsl-2.5.so
0038b000 8 rw--- 000000000038b000 000:00000 [ anon ]
0038d000 200 r-x-- 0000000000000000 008:00003 libcurl.so.3.0.0
003bf000 4 rw--- 0000000000031000 008:00003libcurl.so.3.0.0
003c0000 192 r-x-- 0000000000000000 008:00003 libidn.so.11.5.19
003f0000 4 rw--- 000000000002f000 008:00003libidn.so.11.5.19
003f1000 188 r-x-- 0000000000000000 008:00003libxslt.so.1.1.15
00420000 4 rw--- 000000000002f000 008:00003libxslt.so.1.1.15
00421000 588 r-x-- 0000000000000000 008:00003 libkrb5.so.3.3
004b4000 12 rw--- 0000000000092000 008:00003libkrb5.so.3.3
004b7000 8 r-x-- 0000000000000000 008:00003libcom_err.so.2.1
004b9000 4 rw--- 0000000000001000 008:00003libcom_err.so.2.1
004ba000 148 r-x-- 0000000000000000 008:00003 libk5crypto.so.3.1
004df000 4 rw--- 0000000000025000 008:00003libk5crypto.so.3.1
004e0000 8 r-x-- 0000000000000000 008:00003libkeyutils-1.2.so
004e2000 4 rw--- 0000000000001000 008:00003libkeyutils-1.2.so
004e3000 36 r-x-- 0000000000000000 008:00003libnss_files-2.5.so
004ec000 4 r---- 0000000000008000 008:00003libnss_files-2.5.so
004ed000 4 rw--- 0000000000009000 008:00003libnss_files-2.5.so
004f4000 124 r-x-- 0000000000000000 008:00003 libexpat.so.0.5.0
00513000 8 rw--- 000000000001e000 008:00003libexpat.so.0.5.0
00517000 180 r-x-- 0000000000000000 008:00003 libgssapi_krb5.so.2.2
00544000 4 rw--- 000000000002d000 008:00003libgssapi_krb5.so.2.2
00545000 32 r-x-- 0000000000000000 008:00003libkrb5support.so.0.1
0054d000 4 rw--- 0000000000007000 008:00003libkrb5support.so.0.1
0054e000 88 r-x-- 0000000000000000 008:00003libselinux.so.1
00564000 8 rw--- 0000000000015000 008:00003libselinux.so.1
00566000 44 r-x-- 0000000000000000 008:00003memcache.so
00571000 4 rw--- 000000000000a000 008:00003memcache.so
00572000 28 r-x-- 0000000000000000 008:00003mcrypt.so
00579000 4 rw--- 0000000000007000 008:00003mcrypt.so
0057a000 156 r-x-- 0000000000000000 008:00003 libmcrypt.so.4.4.8
005a1000 12 rw--- 0000000000027000 008:00003libmcrypt.so.4.4.8
005a4000 20 rw--- 00000000005a4000 000:00000 [ anon ]
005c9000 120 r-x-- 0000000000000000 008:00003 libjpeg.so.62.0.0
005e7000 4 rw--- 000000000001d000 008:00003libjpeg.so.62.0.0
00605000 88 r-x-- 0000000000000000 008:00003mysqli.so
0061b000 8 rw--- 0000000000016000 008:00003mysqli.so
0068a000 236 r-x-- 0000000000000000 008:00003 libgd.so.2.0.0
006c5000 128 rw--- 000000000003a000 008:00003 libgd.so.2.0.0
006e5000 16 rw--- 00000000006e5000 000:00000 [ anon ]
007bf000 104 r-x-- 0000000000000000 008:00003 ld-2.5.so
007d9000 4 r---- 0000000000019000 008:00003ld-2.5.so
007da000 4 rw--- 000000000001a000 008:00003ld-2.5.so
00816000 4 r-x-- 0000000000816000 000:00000 [ anon ]
00817000 988 r-x-- 0000000000000000 008:00003 libxml2.so.2.6.19
0090e000 32 rw--- 00000000000f7000 008:00003libxml2.so.2.6.19
00916000 4 rw--- 0000000000916000 000:00000 [ anon ]
00929000 8 r-x-- 0000000000000000 008:00003libdl-2.5.so
0092b000 4 r---- 0000000000001000 008:00003libdl-2.5.so
0092c000 4 rw--- 0000000000002000 008:00003libdl-2.5.so
0092f000 76 r-x-- 0000000000000000 008:00003libpthread-2.5.so
00942000 4 r---- 0000000000013000 008:00003libpthread-2.5.so
00943000 4 rw--- 0000000000014000 008:00003libpthread-2.5.so
00944000 8 rw--- 0000000000944000 000:00000 [ anon ]
00948000 148 r-x-- 0000000000000000 008:00003 libm-2.5.so
0096d000 4 r---- 0000000000024000 008:00003libm-2.5.so
0096e000 4 rw--- 0000000000025000 008:00003libm-2.5.so
00971000 12 r-x-- 0000000000000000 008:00003libuuid.so.1.2
00974000 4 rw--- 0000000000003000 008:00003libuuid.so.1.2
0097b000 152 r-x-- 0000000000000000 008:00003 libapr-1.so.0.4.2
009a1000 4 rw--- 0000000000025000 008:00003libapr-1.so.0.4.2
009ab000 236 r-x-- 0000000000000000 008:00003 libsepol.so.1
009e6000 4 rw--- 000000000003b000 008:00003libsepol.so.1
009e7000 40 rw--- 00000000009e7000 000:00000 [ anon ]
00a2f000 20 r-x-- 0000000000000000 008:00003pdo_mysql.so
00a34000 4 rw--- 0000000000005000 008:00003pdo_mysql.so
00aa1000 36 r-x-- 0000000000000000 008:00003libcrypt-2.5.so
00aaa000 4 r---- 0000000000008000 008:00003libcrypt-2.5.so
00aab000 4 rw--- 0000000000009000 008:00003libcrypt-2.5.so
00aac000 156 rw--- 0000000000aac000 000:00000 [ anon ]
00b78000 108 r-x-- 0000000000000000 008:00003 libaprutil-1.so.0.3.9
00b93000 4rw--- 000000000001b000 008:00003 libaprutil-1.so.0.3.9
00b94000 6560 r-x-- 0000000000000000 008:00003 libphp5.so
011fc000 156 rw--- 0000000000667000 008:00003 libphp5.so
01223000 20 rw--- 0000000001223000 000:00000 [ anon ]
03492000 268 r-x-- 0000000000000000 008:00003 libssl.so.0.9.8e
034d5000 16 rw--- 0000000000042000 008:00003libssl.so.0.9.8e
03c71000 12 r-x-- 0000000000000000 008:00003libgpg-error.so.0.3.0
03c74000 4 rw--- 0000000000002000 008:00003libgpg-error.so.0.3.0
03c77000 504 r-x-- 0000000000000000 008:00003 libgcrypt.so.11.5.2
03cf5000 12 rw--- 000000000007d000 008:00003libgcrypt.so.11.5.2
05748000 1192 r-x-- 0000000000000000 008:00003 libcrypto.so.0.9.8e
05872000 76 rw--- 0000000000129000 008:00003libcrypto.so.0.9.8e
05885000 16 rw--- 0000000005885000 000:00000 [ anon ]
08048000 484 r-x-- 0000000000000000 008:00003 httpd
080c1000 12 rw--- 0000000000078000 008:00003 httpd
080c4000 12 rw--- 00000000080c4000 000:00000 [ anon ]
0951b000 2136 rw--- 000000000951b000 000:00000 [ anon ]
b7cb2000 2048 r---- 0000000000000000 008:00003 locale-archive (deleted)
b7ee3000 64 rw-s- 0000000000000000 000:00009 zero(deleted)
b7ef3000 12 rw--- 00000000b7ef3000 000:00000 [ anon ]
b7f01000 4 r---- 00000000005da000 008:00003locale-archive (deleted)
b7f02000 4 rw--- 00000000b7f02000 000:00000 [ anon ]
bfd31000 84 rw--- 00000000bffea000 000:00000 [ stack ]
mapped: 21164K writeable/private: 3340K shared: 64K
每列的含义如下:
Address:进程所占的地址空间
Kbytes:该虚拟段的大小
RSS:设备号(主设备:次设备)
Anon:设备的节点号,0表示没有节点与内存相对应
Locked:是否允许swapped
Mode 权限:r=read, w=write,x=execute, s=shared, p=private(copy on write)
Mapping:bash 对应的映像文件名
Resident :表示在内存中驻留的段的空间
shared :表示这些被分配的内存是被系统中其他进程共享的。
private :表示只能被该进程使用的空间大小。你可以发现share的空间不具有 private的属性。
参考链接:
http://hllvm.group.iteye.com/group/wiki/2857-JVM
http://www.iteye.com/topic/976522
http://blog.csdn.net/kelly859/article/details/5827365
http://blog.csdn.net/sanshiqiduer/article/details/1933625
JVM内存管理(转)