- 浏览: 71486 次
- 来自: 北京
文章分类
最新评论
-
zong.jianhui06:
讲的不错,比我的好啊a ...
<<大型网站系统与Java中间件实践>> 读书笔记(第2章) -
asle:
在分布式系统设计中,为了提供更好的非质量属性(高可用, ...
<<大型网站系统与Java中间件实践>> 读书笔记(第2章) -
zong.jianhui06:
可以啊,Gradle已经帮你生成eclipse工程了
Spring源码研究之环境搭建 -
riverphoenix:
[img][/img]
Spring源码研究之环境搭建 -
riverphoenix:
我想问一下你的eclipse 是安装的吧,我的是解压缩版本,像 ...
Spring源码研究之环境搭建
转载地址:http://www.ccplat.com/?p=528
模型
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 or Copying
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后还存活的对象可以提升到老生代。
该机制基于以下观察事实:
大部分新分配的对象很快就没有引用了,变成垃圾。
很少有老生代对象引用新生代对象。
基于代内存存储对象的特性,对不同代的内存可以使用不同的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:短暂停,多线程标记在Concurrent marking phase中有变化的相关对象。
Concurrent sweep phase:和程序并发执行,单线程执行,不做compacting。
concurrent reset:单线程,并发执行。
CMS不做compacting,不能使用bump-the-pointer技术,只能使用传统的内存空闲链表技术。
导致内存分配变慢,影响了新生代的GC速度,因为Young的GC如果有对象提升的话依赖于Old的内存分配。
CMS需要更多的内存空间,因为mark phase时程序还是在运行,程序可以申请更多的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:和Parallel Compacting 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或者过长的暂停时间问题,给新生代尽量大的空间。
Young Generation 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个目标有一定的矛盾,因此要视具体应用场景,做平衡。
CMS Collector
-XX:+CMSIncrementalMode:启动增量模式
-XX:+CMSIncrementalPacing:依据收集的统计信息启用增量模式自动调节占空比
-XX:ParallelGCThreads=n
-XX:CMSInitiatingOccupancyFraction=n:默认68。
-XX:+UseCMSInitiatingOccupancyOnly:使vm只使用old内存占用比来触发CMS GC。
-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 Management Extensions (JMX)的实时图形化监测工具,这个工具利用了内建到JVM里面的JMX指令来提供实时的性能和资源的监控,包括了Java程序的内存使用,Heap size, 线程的状态,类的分配状态和空间使用等等。
jinfo
jinfo可以从core文件或进程中获得Java应用程序的配置信息,目前只有在Solaris和Linux的JDK版本里面才有。
jmap
jmap 可以从core文件或进程中获得jvm的相关内存信息,包括Heap size, Perm size等等,目前只有在Solaris和Linux的JDK版本里面才有。
参数如下:
-heap:打印jvm heap的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :同上,但是只答应存活对象的情况
-permstat:打印permanent generation heap情况
例子:
jmap -heap 2083
jmap -histo 2083 | jmap -histo:live 2083
jstat
利用了JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控等等。
具体参数如下:
-class:统计class loader行为信息
-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 Number of classes loaded.
Bytes Number of Kbytes loaded.
Unloaded Number of classes unloaded.
Bytes Number of Kbytes unloaded.
Time Time spent performing class load and unload operations.
jstat -gc 2083 2000 20(每隔2秒监控一次,共做10)
输出内容含义如下:
S0C Current survivor space 0 capacity (KB).
EC Current eden space capacity (KB).
EU Eden space utilization (KB).
OC Current old space capacity (KB).
OU Old space utilization (KB).
PC Current permanent space capacity (KB).
PU Permanent space utilization (KB).
YGC Number of young generation GC Events.
YGCT Young generation garbage collection time.
FGC Number of full GC events.
FGCT Full garbage collection time.
GCT Total garbage 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, 1375280k used, 564500k free, 109680k buffers
Swap: 4401800k total, 497456k used, 3904344k free, 848712k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4338 oracle 25 0 627m 209m 207m R 0 11.0 297:14.76 oracle
4267 oracle 25 0 626m 144m 143m R 6 7.6 89:16.62 oracle
3458 oracle 25 0 672m 133m 124m R 0 7.1 1283:08 oracle
3478 oracle 25 0 672m 124m 115m R 0 6.6 1272:30 oracle
3395 oracle 25 0 672m 122m 113m R 0 6.5 1270:03 oracle
3480 oracle 25 0 672m 122m 109m R 8 6.4 1274:13 oracle
3399 oracle 25 0 672m 121m 110m R 0 6.4 1279:37 oracle
4261 oracle 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
7072 oracle 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
786 oracle 25 0 627m 63m 63m R 0 3.4 1:54.93 oracle
4271 oracle 25 0 627m 59m 58m R 8 3.1 86:09.64 oracle
4273 oracle 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
进程状态。
D=不可中断的睡眠状态
R=运行
S=睡眠
T=跟踪/停止
Z=僵尸进程
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:00003 librt-2.5.so
00117000 4 r—- 0000000000006000 008:00003 librt-2.5.so
00118000 4 rw— 0000000000007000 008:00003 librt-2.5.so
00119000 1276 r-x– 0000000000000000 008:00003 libc-2.5.so
00258000 8 r—- 000000000013f000 008:00003 libc-2.5.so
0025a000 4 rw— 0000000000141000 008:00003 libc-2.5.so
0025b000 12 rw— 000000000025b000 000:00000 [ anon ]
0025e000 60 r-x– 0000000000000000 008:00003 libexslt.so.0.8.12
0026d000 4 rw— 000000000000e000 008:00003 libexslt.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:00003 libfreetype.so.6.4.0
00350000 72 r-x– 0000000000000000 008:00003 libz.so.1.2.3
00362000 4 rw— 0000000000011000 008:00003 libz.so.1.2.3
00363000 60 r-x– 0000000000000000 008:00003 libresolv-2.5.so
00372000 4 r—- 000000000000e000 008:00003 libresolv-2.5.so
00373000 4 rw— 000000000000f000 008:00003 libresolv-2.5.so
00374000 8 rw— 0000000000374000 000:00000 [ anon ]
00376000 76 r-x– 0000000000000000 008:00003 libnsl-2.5.so
00389000 4 r—- 0000000000012000 008:00003 libnsl-2.5.so
0038a000 4 rw— 0000000000013000 008:00003 libnsl-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:00003 libcurl.so.3.0.0
003c0000 192 r-x– 0000000000000000 008:00003 libidn.so.11.5.19
003f0000 4 rw— 000000000002f000 008:00003 libidn.so.11.5.19
003f1000 188 r-x– 0000000000000000 008:00003 libxslt.so.1.1.15
00420000 4 rw— 000000000002f000 008:00003 libxslt.so.1.1.15
00421000 588 r-x– 0000000000000000 008:00003 libkrb5.so.3.3
004b4000 12 rw— 0000000000092000 008:00003 libkrb5.so.3.3
004b7000 8 r-x– 0000000000000000 008:00003 libcom_err.so.2.1
004b9000 4 rw— 0000000000001000 008:00003 libcom_err.so.2.1
004ba000 148 r-x– 0000000000000000 008:00003 libk5crypto.so.3.1
004df000 4 rw— 0000000000025000 008:00003 libk5crypto.so.3.1
004e0000 8 r-x– 0000000000000000 008:00003 libkeyutils-1.2.so
004e2000 4 rw— 0000000000001000 008:00003 libkeyutils-1.2.so
004e3000 36 r-x– 0000000000000000 008:00003 libnss_files-2.5.so
004ec000 4 r—- 0000000000008000 008:00003 libnss_files-2.5.so
004ed000 4 rw— 0000000000009000 008:00003 libnss_files-2.5.so
004f4000 124 r-x– 0000000000000000 008:00003 libexpat.so.0.5.0
00513000 8 rw— 000000000001e000 008:00003 libexpat.so.0.5.0
00517000 180 r-x– 0000000000000000 008:00003 libgssapi_krb5.so.2.2
00544000 4 rw— 000000000002d000 008:00003 libgssapi_krb5.so.2.2
00545000 32 r-x– 0000000000000000 008:00003 libkrb5support.so.0.1
0054d000 4 rw— 0000000000007000 008:00003 libkrb5support.so.0.1
0054e000 88 r-x– 0000000000000000 008:00003 libselinux.so.1
00564000 8 rw— 0000000000015000 008:00003 libselinux.so.1
00566000 44 r-x– 0000000000000000 008:00003 memcache.so
00571000 4 rw— 000000000000a000 008:00003 memcache.so
00572000 28 r-x– 0000000000000000 008:00003 mcrypt.so
00579000 4 rw— 0000000000007000 008:00003 mcrypt.so
0057a000 156 r-x– 0000000000000000 008:00003 libmcrypt.so.4.4.8
005a1000 12 rw— 0000000000027000 008:00003 libmcrypt.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:00003 libjpeg.so.62.0.0
00605000 88 r-x– 0000000000000000 008:00003 mysqli.so
0061b000 8 rw— 0000000000016000 008:00003 mysqli.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:00003 ld-2.5.so
007da000 4 rw— 000000000001a000 008:00003 ld-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:00003 libxml2.so.2.6.19
00916000 4 rw— 0000000000916000 000:00000 [ anon ]
00929000 8 r-x– 0000000000000000 008:00003 libdl-2.5.so
0092b000 4 r—- 0000000000001000 008:00003 libdl-2.5.so
0092c000 4 rw— 0000000000002000 008:00003 libdl-2.5.so
0092f000 76 r-x– 0000000000000000 008:00003 libpthread-2.5.so
00942000 4 r—- 0000000000013000 008:00003 libpthread-2.5.so
00943000 4 rw— 0000000000014000 008:00003 libpthread-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:00003 libm-2.5.so
0096e000 4 rw— 0000000000025000 008:00003 libm-2.5.so
00971000 12 r-x– 0000000000000000 008:00003 libuuid.so.1.2
00974000 4 rw— 0000000000003000 008:00003 libuuid.so.1.2
0097b000 152 r-x– 0000000000000000 008:00003 libapr-1.so.0.4.2
009a1000 4 rw— 0000000000025000 008:00003 libapr-1.so.0.4.2
009ab000 236 r-x– 0000000000000000 008:00003 libsepol.so.1
009e6000 4 rw— 000000000003b000 008:00003 libsepol.so.1
009e7000 40 rw— 00000000009e7000 000:00000 [ anon ]
00a2f000 20 r-x– 0000000000000000 008:00003 pdo_mysql.so
00a34000 4 rw— 0000000000005000 008:00003 pdo_mysql.so
00aa1000 36 r-x– 0000000000000000 008:00003 libcrypt-2.5.so
00aaa000 4 r—- 0000000000008000 008:00003 libcrypt-2.5.so
00aab000 4 rw— 0000000000009000 008:00003 libcrypt-2.5.so
00aac000 156 rw— 0000000000aac000 000:00000 [ anon ]
00b78000 108 r-x– 0000000000000000 008:00003 libaprutil-1.so.0.3.9
00b93000 4 rw— 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:00003 libssl.so.0.9.8e
03c71000 12 r-x– 0000000000000000 008:00003 libgpg-error.so.0.3.0
03c74000 4 rw— 0000000000002000 008:00003 libgpg-error.so.0.3.0
03c77000 504 r-x– 0000000000000000 008:00003 libgcrypt.so.11.5.2
03cf5000 12 rw— 000000000007d000 008:00003 libgcrypt.so.11.5.2
05748000 1192 r-x– 0000000000000000 008:00003 libcrypto.so.0.9.8e
05872000 76 rw— 0000000000129000 008:00003 libcrypto.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:00003 locale-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运行时数据区域
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 or Copying
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后还存活的对象可以提升到老生代。
该机制基于以下观察事实:
大部分新分配的对象很快就没有引用了,变成垃圾。
很少有老生代对象引用新生代对象。
基于代内存存储对象的特性,对不同代的内存可以使用不同的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:短暂停,多线程标记在Concurrent marking phase中有变化的相关对象。
Concurrent sweep phase:和程序并发执行,单线程执行,不做compacting。
concurrent reset:单线程,并发执行。
CMS不做compacting,不能使用bump-the-pointer技术,只能使用传统的内存空闲链表技术。
导致内存分配变慢,影响了新生代的GC速度,因为Young的GC如果有对象提升的话依赖于Old的内存分配。
CMS需要更多的内存空间,因为mark phase时程序还是在运行,程序可以申请更多的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:和Parallel Compacting 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或者过长的暂停时间问题,给新生代尽量大的空间。
Young Generation 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个目标有一定的矛盾,因此要视具体应用场景,做平衡。
CMS Collector
-XX:+CMSIncrementalMode:启动增量模式
-XX:+CMSIncrementalPacing:依据收集的统计信息启用增量模式自动调节占空比
-XX:ParallelGCThreads=n
-XX:CMSInitiatingOccupancyFraction=n:默认68。
-XX:+UseCMSInitiatingOccupancyOnly:使vm只使用old内存占用比来触发CMS GC。
-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 Management Extensions (JMX)的实时图形化监测工具,这个工具利用了内建到JVM里面的JMX指令来提供实时的性能和资源的监控,包括了Java程序的内存使用,Heap size, 线程的状态,类的分配状态和空间使用等等。
jinfo
jinfo可以从core文件或进程中获得Java应用程序的配置信息,目前只有在Solaris和Linux的JDK版本里面才有。
jmap
jmap 可以从core文件或进程中获得jvm的相关内存信息,包括Heap size, Perm size等等,目前只有在Solaris和Linux的JDK版本里面才有。
参数如下:
-heap:打印jvm heap的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :同上,但是只答应存活对象的情况
-permstat:打印permanent generation heap情况
例子:
jmap -heap 2083
jmap -histo 2083 | jmap -histo:live 2083
jstat
利用了JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控等等。
具体参数如下:
-class:统计class loader行为信息
-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 Number of classes loaded.
Bytes Number of Kbytes loaded.
Unloaded Number of classes unloaded.
Bytes Number of Kbytes unloaded.
Time Time spent performing class load and unload operations.
jstat -gc 2083 2000 20(每隔2秒监控一次,共做10)
输出内容含义如下:
S0C Current survivor space 0 capacity (KB).
EC Current eden space capacity (KB).
EU Eden space utilization (KB).
OC Current old space capacity (KB).
OU Old space utilization (KB).
PC Current permanent space capacity (KB).
PU Permanent space utilization (KB).
YGC Number of young generation GC Events.
YGCT Young generation garbage collection time.
FGC Number of full GC events.
FGCT Full garbage collection time.
GCT Total garbage 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, 1375280k used, 564500k free, 109680k buffers
Swap: 4401800k total, 497456k used, 3904344k free, 848712k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4338 oracle 25 0 627m 209m 207m R 0 11.0 297:14.76 oracle
4267 oracle 25 0 626m 144m 143m R 6 7.6 89:16.62 oracle
3458 oracle 25 0 672m 133m 124m R 0 7.1 1283:08 oracle
3478 oracle 25 0 672m 124m 115m R 0 6.6 1272:30 oracle
3395 oracle 25 0 672m 122m 113m R 0 6.5 1270:03 oracle
3480 oracle 25 0 672m 122m 109m R 8 6.4 1274:13 oracle
3399 oracle 25 0 672m 121m 110m R 0 6.4 1279:37 oracle
4261 oracle 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
7072 oracle 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
786 oracle 25 0 627m 63m 63m R 0 3.4 1:54.93 oracle
4271 oracle 25 0 627m 59m 58m R 8 3.1 86:09.64 oracle
4273 oracle 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
进程状态。
D=不可中断的睡眠状态
R=运行
S=睡眠
T=跟踪/停止
Z=僵尸进程
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:00003 librt-2.5.so
00117000 4 r—- 0000000000006000 008:00003 librt-2.5.so
00118000 4 rw— 0000000000007000 008:00003 librt-2.5.so
00119000 1276 r-x– 0000000000000000 008:00003 libc-2.5.so
00258000 8 r—- 000000000013f000 008:00003 libc-2.5.so
0025a000 4 rw— 0000000000141000 008:00003 libc-2.5.so
0025b000 12 rw— 000000000025b000 000:00000 [ anon ]
0025e000 60 r-x– 0000000000000000 008:00003 libexslt.so.0.8.12
0026d000 4 rw— 000000000000e000 008:00003 libexslt.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:00003 libfreetype.so.6.4.0
00350000 72 r-x– 0000000000000000 008:00003 libz.so.1.2.3
00362000 4 rw— 0000000000011000 008:00003 libz.so.1.2.3
00363000 60 r-x– 0000000000000000 008:00003 libresolv-2.5.so
00372000 4 r—- 000000000000e000 008:00003 libresolv-2.5.so
00373000 4 rw— 000000000000f000 008:00003 libresolv-2.5.so
00374000 8 rw— 0000000000374000 000:00000 [ anon ]
00376000 76 r-x– 0000000000000000 008:00003 libnsl-2.5.so
00389000 4 r—- 0000000000012000 008:00003 libnsl-2.5.so
0038a000 4 rw— 0000000000013000 008:00003 libnsl-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:00003 libcurl.so.3.0.0
003c0000 192 r-x– 0000000000000000 008:00003 libidn.so.11.5.19
003f0000 4 rw— 000000000002f000 008:00003 libidn.so.11.5.19
003f1000 188 r-x– 0000000000000000 008:00003 libxslt.so.1.1.15
00420000 4 rw— 000000000002f000 008:00003 libxslt.so.1.1.15
00421000 588 r-x– 0000000000000000 008:00003 libkrb5.so.3.3
004b4000 12 rw— 0000000000092000 008:00003 libkrb5.so.3.3
004b7000 8 r-x– 0000000000000000 008:00003 libcom_err.so.2.1
004b9000 4 rw— 0000000000001000 008:00003 libcom_err.so.2.1
004ba000 148 r-x– 0000000000000000 008:00003 libk5crypto.so.3.1
004df000 4 rw— 0000000000025000 008:00003 libk5crypto.so.3.1
004e0000 8 r-x– 0000000000000000 008:00003 libkeyutils-1.2.so
004e2000 4 rw— 0000000000001000 008:00003 libkeyutils-1.2.so
004e3000 36 r-x– 0000000000000000 008:00003 libnss_files-2.5.so
004ec000 4 r—- 0000000000008000 008:00003 libnss_files-2.5.so
004ed000 4 rw— 0000000000009000 008:00003 libnss_files-2.5.so
004f4000 124 r-x– 0000000000000000 008:00003 libexpat.so.0.5.0
00513000 8 rw— 000000000001e000 008:00003 libexpat.so.0.5.0
00517000 180 r-x– 0000000000000000 008:00003 libgssapi_krb5.so.2.2
00544000 4 rw— 000000000002d000 008:00003 libgssapi_krb5.so.2.2
00545000 32 r-x– 0000000000000000 008:00003 libkrb5support.so.0.1
0054d000 4 rw— 0000000000007000 008:00003 libkrb5support.so.0.1
0054e000 88 r-x– 0000000000000000 008:00003 libselinux.so.1
00564000 8 rw— 0000000000015000 008:00003 libselinux.so.1
00566000 44 r-x– 0000000000000000 008:00003 memcache.so
00571000 4 rw— 000000000000a000 008:00003 memcache.so
00572000 28 r-x– 0000000000000000 008:00003 mcrypt.so
00579000 4 rw— 0000000000007000 008:00003 mcrypt.so
0057a000 156 r-x– 0000000000000000 008:00003 libmcrypt.so.4.4.8
005a1000 12 rw— 0000000000027000 008:00003 libmcrypt.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:00003 libjpeg.so.62.0.0
00605000 88 r-x– 0000000000000000 008:00003 mysqli.so
0061b000 8 rw— 0000000000016000 008:00003 mysqli.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:00003 ld-2.5.so
007da000 4 rw— 000000000001a000 008:00003 ld-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:00003 libxml2.so.2.6.19
00916000 4 rw— 0000000000916000 000:00000 [ anon ]
00929000 8 r-x– 0000000000000000 008:00003 libdl-2.5.so
0092b000 4 r—- 0000000000001000 008:00003 libdl-2.5.so
0092c000 4 rw— 0000000000002000 008:00003 libdl-2.5.so
0092f000 76 r-x– 0000000000000000 008:00003 libpthread-2.5.so
00942000 4 r—- 0000000000013000 008:00003 libpthread-2.5.so
00943000 4 rw— 0000000000014000 008:00003 libpthread-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:00003 libm-2.5.so
0096e000 4 rw— 0000000000025000 008:00003 libm-2.5.so
00971000 12 r-x– 0000000000000000 008:00003 libuuid.so.1.2
00974000 4 rw— 0000000000003000 008:00003 libuuid.so.1.2
0097b000 152 r-x– 0000000000000000 008:00003 libapr-1.so.0.4.2
009a1000 4 rw— 0000000000025000 008:00003 libapr-1.so.0.4.2
009ab000 236 r-x– 0000000000000000 008:00003 libsepol.so.1
009e6000 4 rw— 000000000003b000 008:00003 libsepol.so.1
009e7000 40 rw— 00000000009e7000 000:00000 [ anon ]
00a2f000 20 r-x– 0000000000000000 008:00003 pdo_mysql.so
00a34000 4 rw— 0000000000005000 008:00003 pdo_mysql.so
00aa1000 36 r-x– 0000000000000000 008:00003 libcrypt-2.5.so
00aaa000 4 r—- 0000000000008000 008:00003 libcrypt-2.5.so
00aab000 4 rw— 0000000000009000 008:00003 libcrypt-2.5.so
00aac000 156 rw— 0000000000aac000 000:00000 [ anon ]
00b78000 108 r-x– 0000000000000000 008:00003 libaprutil-1.so.0.3.9
00b93000 4 rw— 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:00003 libssl.so.0.9.8e
03c71000 12 r-x– 0000000000000000 008:00003 libgpg-error.so.0.3.0
03c74000 4 rw— 0000000000002000 008:00003 libgpg-error.so.0.3.0
03c77000 504 r-x– 0000000000000000 008:00003 libgcrypt.so.11.5.2
03cf5000 12 rw— 000000000007d000 008:00003 libgcrypt.so.11.5.2
05748000 1192 r-x– 0000000000000000 008:00003 libcrypto.so.0.9.8e
05872000 76 rw— 0000000000129000 008:00003 libcrypto.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:00003 locale-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
发表评论
-
【转】console使用说明(浏览器调试)
2013-08-11 22:35 907转载地址:http://prisonb ... -
【转】JVM监控工具介绍
2013-08-01 16:12 846转:http://www.blogjava.net/ston ... -
【转】Java 语言中 Enum 类型的使用介绍
2013-07-22 09:26 870Enum 类型的介绍枚举类型(Enumerated Type ... -
【转】谈系统设计的一些原则
2013-06-26 10:43 1245在进行系统设计时,不仅要考虑软件的功能性需求,还要考虑非功能 ... -
使用Java开发需要关注的那些事儿
2013-06-17 10:26 833【转载地址】http://blog.csdn.net/fra ... -
【转载】Jvm内存映像分析
2013-05-27 17:41 772转载地址:http://zyn010101.iteye.co ... -
JDBC 设置查询超时()
2013-05-13 15:27 2358最近项目中写了个提数的的系统,该系统架构 ... -
【转】线程池深入分析(上)
2013-05-02 15:11 844转载地址:http://blog.csd ... -
【转】Java 理论与实践: 正确使用 Volatile 变量
2013-04-17 18:29 748转载地址:http://www.ibm.com/develo ... -
【转】listener、 filter、servlet 加载顺序及其详解
2013-04-17 15:17 802转载:http://zhxing.iteye.com/bl ... -
java线程:Atomic原子的(转)
2013-04-09 16:18 695一、何谓Atomic? Atomic一词跟原子有点关系, ... -
【转载】使用JMeter的Java请求功能测试Hetty性能
2013-01-16 10:02 1061转载地址:http://my.oschina.net/xish ... -
【转载】对比Java.nio 和 Java.io
2012-12-11 14:06 733原作者:Davide Pisano,编 ... -
【转载】Spring定时任务时间格式cronExpression设置
2012-09-28 16:27 776【转载地址】:http://hi. ... -
Tomcat6+的内存配置
2012-09-25 11:15 969昨天,在Windows平台上配置Jenkins和Son ...
相关推荐
在这份由Sun Microsystems公司出版的《JVM内存管理白皮书》中,我们可以找到关于Java虚拟机(JVM)内存管理的详细介绍和深入分析。这份文档对于想要深入了解JVM工作原理的读者来说是一份宝贵的学习资料。在这份...
JVM 内存管理之道 JVM垃圾回收机制 JVM GC组合 JVM 内存监控工具
JVM内存管理是Java平台的一个重要特性,其内存空间的分配和回收机制对Java应用程序的性能和稳定性有着至关重要的影响。 首先,JVM内存管理涉及的内存空间主要分为方法区(Method Area)、堆(Heap)、本地方法栈...
### JVM内存管理详解 #### 一、引言 在探讨JVM内存管理之前,我们先来看一下为何要深入了解这一主题。对于深入掌握Java的人来说,内存管理是不可或缺的一部分。随着技术的发展,内存管理变得越来越自动化,但这也...
JVM 内存溢出问题解析 JVM 内存溢出是指程序运行所需的内存大于虚拟机能提供的最大内存的情况。这种情况可能是由于数据量过大、死循环、静态变量和静态方法过多、递归、无法确定是否被引用的对象等原因引起的。同时...
### JVM内存空间分配详解 #### 一、JVM内存模型概览 JVM(Java虚拟机)内存模型主要由以下几个部分组成:程序计数器、Java虚拟机栈、本地方法栈、Java堆以及方法区(在JDK 8之后称为元空间)。下面将对这几个部分...
总结来说,Idea插件JProfiler11是Java开发者的得力助手,它将复杂的JVM内存管理和性能优化变得简单易行。熟练掌握JProfiler11的使用,不仅可以提高Java应用的性能,也能提升开发者的专业技能。在日常开发中,适时...
### Sun JVM原理与内存管理 #### 一、Sun JDK 1.6 GC (Garbage Collector) Sun JDK 1.6 的垃圾收集器(GC)是其内存管理的关键组成部分,它负责自动地回收不再使用的对象所占用的内存。本文将详细介绍Sun JDK 1.6 GC...
JVM内存管理主要包括内存结构、内存分配以及垃圾回收(GC)等方面。了解这些知识对于优化Java应用程序的性能至关重要。 ### 1. JVM内存结构 #### 1.1.1 JVM内存概述 JVM内存分为几个关键区域,每个区域都有特定的...
**JVM内存管理及调优** Java虚拟机(JVM)是Java程序运行的基础,它为Java应用程序提供了运行环境。JVM内存管理是优化Java应用性能的关键环节,涉及到内存分配、垃圾回收以及内存溢出等问题。毕玄,一位在淘宝有着...
在这个资源中,我们将详细讨论 JVM 内存参数的配置和调优,包括 JVM 的结构、内存管理、垃圾回收、堆和非堆内存、内存分配和限制等方面。 JVM 结构 JVM 的结构主要由六个部分组成:JVM API、JVM 内部组件、平台...
在Java编程语言中,了解和控制JVM(Java虚拟机)的内存管理是至关重要的,尤其是在性能调优、资源管理和避免内存泄漏等方面。本文将深入探讨如何在Java中获取JVM内存大小,包括堆内存的总量、最大值以及剩余空间,并...
### JVM内存监控工具详解 #### 引言 Java Virtual Machine (JVM) 是运行 Java 应用程序的核心组件,其性能直接影响应用的响应速度和稳定性。JVM 的内存管理是性能优化的关键,尤其是在高并发环境下,合理的内存...
JVM内存模型深度剖析与优化 JVM内存模型是Java虚拟机的核心组件之一,它直接影响着Java应用程序的性能和可靠性。本文将深入剖析JVM内存模型的结构和工作机理,并讨论如何优化JVM参数以提高Java应用程序的性能。 一...
《JVM内存管理学习笔记》 在Java世界中,JVM(Java Virtual Machine)是运行所有Java应用程序的核心。深入理解JVM内存管理对于优化程序性能、预防和解决内存泄漏问题至关重要。本文将从JVM内存模型、内存区域划分、...
MAT JVM内存分析工具可以帮助开发者深入理解Java虚拟机(JVM)的内存管理机制,通过分析堆内存快照来识别内存消耗异常的情况。 首先,MAT提供了丰富的视图来帮助用户查看内存状态,例如“概述”视图可以快速了解堆...
MAT通过深入分析堆转储(heap dump)文件,提供了丰富的视图和功能,使内存管理变得更加直观和高效。 1. **内存泄漏检测**: 内存泄漏是导致Java应用性能下降和系统资源耗尽的主要原因之一。MAT通过分析堆转储文件...
JVM内存模型是Java虚拟机(JVM)中的一种内存管理机制,它将内存区分为永久区内存(Permanent space)和堆内存(heap space)两大块。永久区内存用于存放加载的Class类级对象,如class本身、method、field等等,而堆...
### JVM内存配置优化 #### 一、理解JVM内存模型 在进行JVM内存配置优化之前,我们需要了解Java虚拟机(JVM)的内存结构。Java的逻辑内存模型大致分为几个部分: 1. **堆内存(Heap)**:主要用于存储对象实例、数组...