java gc的工做原理、如何优化GC的性能、如何和GC进行有效的交互

java gc的工做原理、如何优化GC的性能、如何和GC进行有效的交互

    一个优秀的Java 程序员必须了解GC 的工做原理、如何优化GC的性能、如何和GC进行有效的交互,由于有一些应用程序对性能要求较高,例如嵌入式系统、实时系统等。只有全面提高内存的管理效 率,才能提升整个应用程序的性能。 本篇文章首先简单介绍GC的工做原理,而后再对GC的几个关键问题进行深刻探讨,最后提出一些Java程序设计建议,从GC角度提升Java程序的性能。
GC的基本原理
    Java 的内存管理实际上就是对象的管理,其中包括对象的分配和释放,对于程序员来讲,分配对象使用new关键字;释放对象时,只要将对象全部引用赋值为null,让程序不可以再访问到这个对象,咱们称该对象为"不可达的".GC将负责回收全部"不可达"对象的内存空间。
对于GC来讲,当程序员建立对象时,GC就开始监控这个对象的地址、大小以及使用状况。一般,GC采用有向图的方式记录和管理堆(heap)中的全部对 象,经过这种方式肯定哪些对象是"可达的",哪些对象是"不可达的"。当GC肯定一些对象为"不可达"时,GC就有责任回收这些内存空间。可是,为了保证 GC可以区别平台实现的问题,Java规范标准对GC的不少行为都没有进行严格的规定。例如,对于采用什么类型的回收算法、何时进行回收等重要问题都 没有明确的规定。所以,不一样的JVM的实现者每每有不一样的实现算法。这也给Java程序员的开发带来不少不肯定性。本文研究了几个和GC工做相关的问题, 努力减小这种不肯定性给Java程序带来的负面影响。
@@增量式GC( Incremental GC )
    GC在JVM中一般由一个或一组进程来实现,它自己也和用户程序同样占用heap空间,运行时也占用CPU,当GC进程运行时,应用程序中止运行。所以, 当GC运行时间较长时,用户可以感到Java程序的停顿,另外一方面,若是GC运行时间过短,可能对象回收率过低,这意味着还有不少应该回收的对象没有被回 收,仍然占用大量内存。所以,在设计GC的时候,就必须在停顿时间和回收率之间进行权衡。
一个好的GC实现容许用户定义本身所须要的设置,例如内存有限的设备,对内存的使用量很是敏感,但愿GC可以准确的回收内存,它并不在乎程序速度的放慢, 另一些实时网络游戏,就不可以容许程序有长时间的中断。 增量式GC就是经过必定的回收算法,把一个长时间的中断,划分为不少个小的中断,经过这种方式减小GC对用户程序的影响。虽然,增量式GC在总体性能上可 能不如普通GC的效率高,可是它可以减小程序的最长停顿时间。
Sun JDK提供的HotSpot JVM就能支持增量式GC。HotSpot JVM缺省GC方式为不使用增量GC,为了启动增量GC,咱们必须在运行Java程序时增长-Xincgc的参数。HotSpot JVM增量式GC,实现是采用Train GC算法,它的基本想法:将堆中的全部对象按照建立和使用状况进行分组(分层),将使用频繁和具备相关性的对象放在一队中,随着程序的运行,不断对组进行 调整,当GC运行时,它老是先回收最老的(最近不多访问的)对象,若是整组都为可回收对象,GC将整组回收,这样,每次GC运行只回收必定比例的不可达对 象,保证程序的顺畅运行。
finalize()函数
    finalize是位于Object类的一个思路方法,该思路方法的访问修饰符为protected,因为全部类为Object的子类,所以用户类很容易 访问到这个思路方法。因为,finalize函数没有自动实现链式调用,咱们必须手动实现,所以finalize函数的最后一个语句一般是 super.finalize()。经过这种方式,咱们能够实现从下到上实现finalize的调用,即先释放本身的资源,而后再释放父类的资源。
根据Java语言规范标准,JVM保证调用finalize函数以前,这个对象是不可达的,可是,JVM不保证这个函数必定会被调用。另外,规范标准还保证finalize函数最多运行一次。
不少Java初学者会认为这个思路方法相似和C++中的析构函数,将不少对象、资源的释放都放在这一函数里面。其实,这不是一种很好的方式,缘由以下:其 一,GC为了可以支持finalize函数,要对覆盖这个函数的对象做不少附加的工做;其二,在finalize运行完成以后,该对象可能变成可达 的,GC还要再检查一次该对象是不是可达的,所以,使用finalize会下降GC的运行性能;其三,因为GC调用finalize的时间是不肯定的,因 此经过这种方式释放资源也是不肯定的。
一般,finalize用于一些不容易控制,而且很是重要资源的释放,例如一些I/O操做、数据链接等,这些资源的释放对整个应用程序是很是关键的。在这 种状况下,程序员应该以经过程序自己管理(包括释放)这些资源为主,以finalize函数释放资源方式为辅,造成一种双保险的管理机制,而不该该仅仅依 靠finalize来释放资源。
 程序如何和GC进行交互(不懂...)
    Java2加强了内存管理功能,增长了一个java.lang.ref包,其中定义了3种引用类。这3种引用类分别为SoftReference、 WeakReference和PhantomReference.经过使用这些引用类,程序员能够在必定程度和GC进行交互,以便改善GC的工做效率。这 些引用类的引用强度介于可达对象和不可达对象之间。
 一些Java编码的建议
    根据GC的工做原理,咱们能够经过一些窍门技巧和方式,让GC运行更加有效率,更加符合应用程序的要求。如下就是一些程序设计的几点建议:
一、最基本的建议就是尽早释放无用对象的引用。大多数程序员在使用临时变量的时候,都是让引用变量在退出活动域(scope)后自动设置为null。咱们 在使用这种方式时候,必须特别注意一些复杂的对象图,例如数组、队列、树、图等,这些对象之间有相互引用,关系较为复杂。对于这类对象,GC回收它们通常 效率较低。若是程序容许,尽早将不用的引用对象赋为null。这样能够加速GC的工做。
二、尽可能少用finalize函数。Finalize函数是Java提供给程序员一个释放对象或资源的机会,可是,它会加大GC的工做量,所以尽可能少采用finalize方式回收资源。
三、注意集合数据类型,包括数组、树、图、链表等数据结构,这些数据结构对GC来讲回收更为复杂。另外,注意一些全局的变量,以及静态变量,这些变量每每容易引发悬挂对象(dangling reference),形成内存浪费。
四、当程序有必定的等待时间,程序员能够手动执行System.gc(),通知GC运行,可是Java语言规范标准并不保证GC必定会执行,此时使用增量式GC能够缩短Java程序的暂停时间。
html

 

 

java 当GC进程运行时,应用程序中止运行吗??

对于建立大量对象的大型应用程序,JVM 花在垃圾收集(GC)上的时间会很是多。默认状况下,进行 GC 时,整个应用程序都必须等待它完成,这可能要有几秒钟甚至更长的时间(Java 应用程序启动器的命令行选项 -verbose:gc 将致使向控制台报告每一次 GC 事件)。要将这些由 GC 引发的暂停(这可能会影响快速任务的执行)降至最少,应该将应用程序建立的对象的数目降至最低。一样,在单独的 JVM 中运行计划代码是有帮助的。同时,能够试用几个微调选项以尽量地减小 GC 暂停。例如,增量 GC 会尽可能将主收集的代价分散到几个小的收集上。固然这会下降 GC 的效率,可是这多是时间计划的一个可接受的代价
资料引用:http://www.knowsky.com/362375.html
java

 

 

Java虚拟机优化选项,GC说明

引用 http://blog.sina.com.cn/s/blog_6d003f3f0100lmkn.html 程序员

 

 

有许多 JVM 选项会影响基准测试。比较重要的选项包括:算法

   * JVM 的类型:服务器(-server)与客户机(-client)。
    * 确保有足够的内存可用(-Xmx)。
    * 使用的垃圾收集器类型(高级的 JVM 提供许多调优选项,可是要当心使用)。
    * 是否容许类垃圾收集(-Xnoclassgc)。默认设置是容许类 GC;使用 -Xnoclassgc 可能会损害性能。
    * 是否执行 escape 分析(-XX:+DoEscapeAnalysis)。
    * 是否支持大页面堆(-XX:+UseLargePages)。
    * 是否改变了线程堆栈大小(例如,-Xss128k)。
    * 使用 JIT 编译的方式:老是使用(-Xcomp)、从不使用(-Xint)或只对热点使用(-Xmixed;这是默认选项,产生的性能最好)。
    * 在执行 JIT 编译以前(-XX:CompileThreshold)、后台 JIT 编译期间(-Xbatch)或分级的 JIT 编译期间(-XX:+TieredCompilation)收集的剖析数据量。
    * 是否执行偏向锁(biased locking,-XX:+UseBiasedLocking);注意,JDK 1.6 及更高版本会自动执行这个特性。
    * 是否激活最近的试验性性能调整(-XX:+AggressiveOpts)。
    * 启用仍是禁用断言(-enableassertions 和 -enablesystemassertions)。
    * 启用仍是禁用严格的本机调用检查(-Xcheck:jni)。
    * 为 NUMA 多 CPU 系统启用内存位置优化(-XX:+UseNUMA)。

Class Data Sharing类共享.
java5引入了类共享机制,指在java程序第一次启动时, 优化一些最经常使用的基础类到一个共享文件中,暂只支持Client VM和serialGC.存放在client/classes.jsa中, 这就是为何程序在第一次执行较慢的缘由.  开启参数-Xshare.

J2SE 6(代号:Mustang野马)主要设计原则之一就是提高J2SE的性能和扩展能力,主要经过最大程度提高运行效率,更好的垃圾收集和一些客户端性能来达到。

一、偏向锁(Biased locking)
Java 6之前加锁操做都会致使一次原子CAS(Compare-And-Set)操做,CAS操做是比较耗时的,即便这个锁上实际上没有冲突,只被一个线程拥 有,也会带来较大开销。为解决这一问题,Java 6中引入偏向锁技术,即一个锁偏向于第一个加锁的线程,该线程后续加锁操做不须要同步。大概的实现以下:一个锁最初为NEUTRAL状态,当第一个线程加 锁时,将该锁的状态修改成BIASED,并记录线程ID,当这一线程进行后续加锁操做时,若发现状态是BIASED而且线程ID是当前线程ID,则只设置 一下加锁标志,不须要进行CAS操做。其它线程若要加这个锁,须要使用CAS操做将状态替换为REVOKE,并等待加锁标志清零,之后该锁的状态就变成 DEFAULT,经常使用旧的算法处理。这一功能可用-XX:-UseBiasedLocking命令禁止。

二、锁粗化(Lock coarsening)
若是一段代码常常性的加锁和解锁,在解锁与下次加锁之间又没干什么事情,则能够将屡次加加锁解锁操做合并成一对。这一功能可用-XX:-EliminateLocks禁止。

三、自适应自旋(Adaptive spinning)
通常在多CPU的机器上加锁实现都会包含一个短时间的自旋过程。自旋的次数不太好决定,自旋少了会致使线程被挂起和上下文切换增长,自旋多了耗CPU。为此Java 6中引入自适应自旋技术,即根据一个锁最近自旋加锁成功几率动态调整自旋次数。

四、经常使用大内存分布的堆(large page heap)
在大内分页是x86/amd64架构上用来减少TLB(虚拟地址到物理地址翻译缓存)大小的TLB失配率。Java 6中的内存堆可使用这一技术。

五、提升数组拷贝性能
对每种类型大小写一个定制的汇编数组拷贝程序。

六、后台进行代码优化
Background Compilation in HotSpot™ Client Compiler: 后台进行代码优化

七、线性扫描寄存器分配算法(Linear Scan Register Allocation):
一种新的寄存器分配策略,基于SSA(static single assignment),性能提升10%左右。经常使用的寄存器分配算法将寄存器分配看做图着色问题,时间复杂度是O(n^4),不适用于Java的JIT编译。原来的JVM里是根据一些本地启发式规则来分配寄存器,效果不太好,Java 6中使用的线性扫描寄存器算法可以达到与图颜色算法类似的效果,而且时间复杂度是线性的。

八、并行缩并垃圾收集器(Parallel Compaction Collector)
进行Full GC时使用并行垃圾收集(JDK 5里原来非Full GC是并行的但Full GC是串行的),使用-XX:+UseParallelOldGC开启这一功能

九、并行低停顿垃圾收集器(Concurrent Low Pause Collector)
显式调用gc(如System.gc)时也能够并行进行标记-清扫式垃圾收集,使用-XX:+ExplicitGCInvokesConcurrent开启。

十、Ergonomics in the 6.0 Java Virtual Machine
自动调整垃圾收集策略、堆大小等配置,这一功能在JDK 5中加入,JDK 6中获得显著加强,SPECjbb2005性能提升70%。

十一、boot类装载器的优化
jre中增长一个描述package所在jar文件的元索引文件,加快classloader加载类性能,提升桌面Java应用启动速度(+15%)。内存占用也减小了10%

十二、图形程序优化
在jvm启动以前显示splash。

OutOfMemoryError是内存溢出, 有多种状况会出现内存溢出.
1.java堆溢出java.lang.OutOfMemoryError: Java heap space.
2.java永久堆溢出,一般是反射,代理用的较多致使类生成过多,java.lang.OutOfMemoryError: PermGen space.
3.本地堆溢出,这多是因为操做系统没法分配足够的内存,多是系统已无内存,还多是java进程内存空间耗尽,这里有点意思,通常32位系统进程只 有4G地址空间,而又由于java实现使用本地堆或内存映射区做为java堆的存储空间,再去除内核映射区,java使用的堆通常只有2G之内,而若是 java堆xmx占的过大,致使jni的本地堆太小,也会生成内存溢出.本地堆能够是jni用new, malloc,也多是DirectBuffer等实例.
java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space?
这时候,若是java堆足够用的话, 减小xmx的值,反而会解决这种问题.
4.jni方法的溢出.而前者是由jvm检测的本地溢出,而此是在jni方法调用时,没法分配内存.
java.lang.OutOfMemoryError: <reason> <stack trace> (Native method)

   
JDK7性能优化.

1.(Zero Based )Compressed OOPS
在64位CPU中, JVM的OOP(Ordinary object pointer)为64位, 简单的讲,OOP能够被认为为对象的引用,虽然java中基本类型位数是固定的, 但引用类型(简化的C语言指针)用于指向堆中的地址很天然的会被扩展成机器的字长. 32位系统最大可访问内存为4G,为了突破这个限制64位系统已经很常见,可是单单引用从32位转为64位,堆空间占用大概会增长一半,虽然内存已经很便宜, 可是内存带宽,CPU缓存代价是很昂贵的.

Compressed OOPS压缩可管理的引用到32位以下降堆的占用空间,在JVM执行时加入编/解码指令,相似于8086的段管理,其使用
<narrow-oop-base(64bits)> + (<narrow-oop(32bits)> << 3) + <field-offset>公式肯定内存地址.
JVM在将对象存入堆时编码,在堆中读取对象时解码.

而Zero based compressed oops则进一步将基地址置为0(并不必定是内存空间地址为0, 只是JVM相对的逻辑地址为0,如可用CPU的寄存器相对寻址) 这样转换公式变为:
(<narrow-oop << 3) + <field-offset>
从而进一步提升了性能.不过这须要OS的支持.
若是java堆<4G,oops使用低虚拟地址空间,而并不须要编/解码而直接使用.

Zero based compressed oops针对不一样的堆大小使用多种策略.
1.堆小于4G,无需编/解码操做.
2.小于32G而大于4G,使用Zero based compressed oops
3.大于32G, 不使用compressed oops.

Escape Analysis Improvements
当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其余过程或者线程所引用,这种现象称做指针(或者引用)的逃逸 (Escape),也就是说变量不只仅在本方法内使用. Java对象通常被认为老是在堆中分配的, 这使得任何对象都须要进行垃圾回收.而大多数状况下,方法内的对象仅在本方法中使用,彻底可使用栈来存储,栈内变量释放是最天然,性能最好的,C中的 struct即在分配在栈中.若是实现引用逃逸分析,即可以把没有引用逃逸的对象分配在栈中,并且没必要在语言上加入新的定义方法,引用逃逸分析是自动 了.JDK7已经开始缺省支持的逃逸分析了.另此还能够消除同步,若是其分析得知对象为非引用逃逸,则全部该对象的同步操做均可以被取消(固然这本是程序 员的任务,好比StringBuffer),另可优化对象的部分甚至所有都保存在CPU寄存器内.

NUMA Collector Enhancements
NUMA(Non Uniform Memory Access),NUMA在多种计算机系统中都获得实现,简而言之,就是将内存分段访问,相似于硬盘的RAID,Oracle中的分簇,JVM只不过对此加以应用而矣.

以上三个特性也能在有些JDK6中打开,具体须要看各版本的changenotes. java6中加入了诸如如下的性能优化手段:
轻量锁 使用cas机制减小锁的性能消耗.
偏向锁(biased locking)
锁粗化(lock coarsening)
由逸出(escape)分析产生的锁省略    逸出分析还可以分配内存在栈中,以减小内存回收的压力.
自适应自旋锁(adaptive spinning) 自旋锁只有在物理多CPU中才会效果.
锁消除(lock elimination)

在多核CPU中,锁的获取比单核系统耗费资源相对大的多, 由于在多核系统中,锁的获取须要CPU阻塞数据总线,高速缓存写回.
这样有时候, 咱们在单核系统中,常常会获得StringBuffer与StringBuilder性能差很少的用例,  并且因为有了锁消除等技术, 有些状况在多核CPU中也会获得性能相差很少的状况.

据信Java7还将缺省支持OpenGL的加速功能.

在JDK1.5中加入了Class Data Sharing, 也就是把部分经常使用的java基本类,缓存在文件或共享内存中, 以供全部java进程使用.

从JRE1.5中,java程序启动时,如非使用-client|server指令显示指定,虚拟机会自动选择对应的VM,如在64位系统中,只实现了serverVM,全部的虚拟机都会使用server VM. 32位的系统则windows缺省使用clientVM,而Linux,solaris则根据CPU个数和内存来肯定是否使用serverVM,如jre6以2CPU,2GB物理内存为界.

GC
衡量GC效率的参数主要有两个,一个是吞吐量(即效率),一个是停顿时间,另外还有footprint,就是占用的堆大小.

GC算法.
  1.拷贝,将全部仍然生存的对象搬到另一块内存后,整块内存就可回收。这种方法有效率,但须要有必定的空闲内存,拷贝也有开销.
  2.跟踪收集器,跟踪收集成追踪从根节点开始的对象引用图。基本的追踪算法叫做“标记并清除”,也就是垃圾收集的两个阶段。标记阶段,垃圾收集器遍历引用 数,标记每个遇到的对象。清除阶段,未被标记的对象被释放。可能在对象自己设置标记,要么就是用一个独立的位图来设置标记。 压缩(可选),垃圾收集同 时要应对碎片整理的任务。标记和清除一般使用两种策略来消除堆碎片:压缩和拷贝,这两种方法都是快速移动对象来减少碎片, 加在一块儿叫作mark-sweep-compact.
  3.还有一种引用计数收集器,这种方法时堆中的每一个对象都有一个引用计数,在引用赋值时加1,置空或做为基本类型的引用超出生命期(如方法退出而栈回收)时减1,其对多个对象的循环引用无能为力,但引用计数都不为0 ,还有引用数的增减带来额外开销,故已再也不使用.
 
分代收集器
   根据程序的统计, 大多数对象生命周期都很短,都很快被释放掉.但也有部分对象生命周期较长, 甚至永久有效. 对于拷贝算法来讲,每次收集时,全部的活动对象都要移动来移动去。对于短生命的对象还好说,常常能够就地解决掉,但是对于长生命周期的对象就纯粹是个体力 劳动了,把它挪来挪去除消耗大量的时间,没有产生任何效益。分代收集能直接让长生命周期的对象长时间的呆在一个地方按兵不动。GC 的精力能够更多的花在收集短命对象上。
  这种方法里,堆被分红两个或更多的子堆,每个堆为一“代”对象服务。最年幼的那一代进行最频繁的垃圾收集。由于多数对象是短命的,只有很小部分的年 幼对象能够在经历第一次收集后还存活。若是一个最年幼的对象经历了好几回垃圾收集后还是活着的,那这个对象就成为寿命更高的一代,它被转移到另一个子堆 中去。年龄更高一代的收集没有年轻一代来得频繁。每当对象在所属的年龄代中变得成熟(屡次垃圾收集后仍幸存)以后,就能够转移到更高年龄的一代中去。
  分代收集通常在年轻堆中应用于拷贝算法,年老代应用于标记清除算法。无论在哪一种状况下,把堆按照对象年龄分组能够提升最基本的垃圾收集的性能。 

通常java中分代收集器将堆分为年轻代, 年老代和永久代. 年轻代的收回称为minorGC,由于在此期内,对象生命周期很较,故效率较高, 年老代称为FullGC,对应的效率较低,用时较长,应尽可能减小FullGC的次数.

VM,
Client VM 适合桌面程序,启动快, 运行时间短, 故其不会预先装入太多的类,对类进行过多优化.
Server VM 适合服务程序,启动时间不重要,运行时间较长, 会预先装入大多基础类,对类进行优化.

GC种类.
Serial 串行回收器(缺省)
在GC运行时, 应用逻辑所有暂停,利用单线程经过"拷贝"进行年轻代的垃圾收集,单线程使用"标记-清除-压缩"进行年老代(tenured)垃圾回收. 吞吐率较高.适合单CPU硬件.

Parallel  并行回收器
针对年轻代使用多个GC线程进行"拷贝"垃圾收集,针对年轻代的GC运行时,程序暂停, 年老代依然是单线程使用"标记-清除-压缩"进行年老代垃圾回收,GC运行时, 应用一样暂停.在大内存,多处理器的机器上,能够考虑使用此Parallel GC(使用参数-XX:+UseParallelGC指定),这种GC在对YoungGen进行GC时,能够对多处理器加以利用,从而相对下降了停顿时间,但重点是提升了吞吐量,可是,在其对OldGen进行GC时,依然使用了和Serial GC一样的算法。因此在Jdk5U6中,又引入了Parallel Compacting Collector(使用参数-XX:+UseParallelOldGC指定),这种GC对OldGen的GC也能够受益于多处理器。因为对OldGen的GC远比YoungGen更耗时间,因此理论上这种Garbage Collector能够提供更优的性能,并且,值得注意的是,Parallel Compacting GC最终会取代Parallel GC。

Concurrent mark-sweep 并发回收器.
对于年轻代使用和多GC线程"拷贝"回收,此GC也须要暂停应用,但因为minorGC效率较高,故不会产生大的停顿,对于年老代使用与应用程序同时运行 的并发方式标记-回收机制,其将步骤再次分细,部分阶段(初始标记,从新标记)也会彻底致使应用暂停,但时间较短,大部分时间都是应用程序与单GC线程并 发,下降了应用程序暂停的时间。这种GC使用了和Parallel GC一致的YoungGen的收集算法,而在对OldGen进行GC时,它采用了较为复杂的算法,提供了极短的停顿时间。可是,复杂的算法也形成了更大的 开销,并且这种 Parallel GC是non-compacting的,因此它使用一个空闲块链表来管理OldGen Heap,分配空间的开销也加大了.在某些场景中,较短的停顿时间比较大的吞吐量更加剧要,这时能够考虑使用此GC,即所谓的CMS GC。

增量收集器(Train算法)已逐渐被弃用,-XincGC 在1.5中会选中并发GC.

在SUN J2SE 5.0中,引入了所谓Behavior-based Parallel Collector Tuning,这种调优方式基于三个Goal:

Maximum Pause Time Goal: 使用参数-XX:MaxGCPauseMillis=n指定,默认值为空。这个参数被指定后,三个内存区的GC停顿时间都会尽力的保持在n毫秒之内,若是没法知足,则相应的内存区会缩小,以缩短GC的停顿时间;

Throughput Goal: 使用参数-XX:GCTimeRatio=n指定,默认值为99,即GC时间占总的应用运行时间为1%。若是没法知足,相应的内存区会扩大,以提升应用在两次GC间的运行时间;

Footprint Goal: 因为眼下内存泛滥,因此这个Goal通常就不值得关注了;

这三个Goal的优先级为从上到下,即首先知足Maximum Pause Time Goal,再知足Throughput Goal,最后再知足Footprint Goal。

 
使用参数-Xloggc:file和-XX:+PrintGCDetails打印gclog,而后使用gcviewer对gclog进行查看,它的优点在于能够生成统计数据,吞吐量,最大的和最小的停顿时间,Full GC时间占整个GC时间的百分比等,均可以使用这个工具查看,但目前只支持到1.5。

JConsole是容许您监测各类各样的VM资源运行时使用状况的Java监视和管理控制台。实际在java5中, 须要加一个参数, 在java6中因为支持了attach API,jconsole会自动加载JVM内部的JMX代理.
jstat命令打印各类各样的VM统计数据,包括内存使用、垃圾回收时间、类加载和及时编译器统计。 jmap 命令容许您得到运行时的堆直方图和堆转储。jhat命令容许您分析堆转储。jstack命令容许您得到线程堆栈跟踪。这些诊断工具能够附加到任何应用程序,不须要以特别方式启动。
 

引用 http://blog.sina.com.cn/s/blog_6d003f3f0100lmkn.htmlwindows

相关:触发Full GC执行的状况四种状况数组

相关文章
相关标签/搜索