12、jvm-内存管理机制-垃圾收集器

1. 垃圾回收器的工作目标是回收已经无用的对象的内存空间,从而避免内存渗漏体的产生,节省内存资源,避免程序代码的崩溃;  
2. 垃圾回收器判断一个对象的内存空间是否无用的标准是:如果该对象不能再被程序中任何一个“活动的部分”所引用,此时我们就说,该对象的内存空间已经无用。所谓“活动的部分”,是指程序中某部分参与程序的调用,正在执行过程中,尚未执行完毕;
3. 垃圾回收器线程虽然是作为低优先级的线程运行,但在系统可用内存量过低的时候,它可能会突发地执行来挽救内存资源。当然其执行与否也是不可预知的;
4. 垃圾回收器不可以被强制执行,但程序员可以通过调用System.gc()方法来建议(注意,只是“建议”)执行垃圾回收器;
5. 垃圾回收器不能保证一个无用的对象一定会被及时收集,也不能保证垃圾回收器在一段Java语言代码中一定会执行。因此在程序执行过程中被分配出去的内存空间可能会一直保留到该程序执行完毕,除非该空间被重新分配或被其他方法回收。由此可见,完全彻底地根绝内存渗漏体的产生也是不可能的;
6. 我们没有办法预知在一组均符合垃圾回收器收集标准的对象中,哪一个会被首先收集。也就是说,垃圾回收的次序是不确定的;
7. 循环引用对象不会影响其被垃圾回收器收集;
8. 为了更快的让垃圾回收器收集不再有用的对象,可以通过将对象的引用变量(reference variables)设置为null值,来暗示垃圾回收器来收集该对象。

这里重点说明的是,虽然就像你无法直接命令保洁人员倒垃圾一样,你无法直接操作Java进行垃圾回收操作,但并不意味着你对此无能为力。比如上面的第四条,System.gc()方法,但是可以很负责任的说,它,基本,没有用。特别是相对于第八条来说,人家还来得跟实惠些。就是将对象的引用变量(reference variables)设置为null值。至于什么是对象,什么是引用变量什么是null,那些都是浮云,以后你自会清楚地。不过难免有的笔试题里面,特别是有的公司会出一些Java的古老的面试题,你还得直到这个方法。


1960年 MIT(麻省理工学院 Massachusetts Institute of Technology )Lisp语言 第一次使用动态内存分配和垃圾收集技术;
那些内存需要被释放
在什么时候释放
怎样实现释放
程序计数器、jvm栈、本地方法栈随 线程创建和释放(不由GC回收),jvm栈中的栈帧随方法的进入和退出顺序执行入栈和出栈,每个栈帧的大小在编译时确定(无动态扩张情况);
垃圾收集器对堆回收前,判断对象在后面的程序还要被调用,或者不再被调用;
判断方法
1、引用计算法:在调用时,计数器值+1;调用结束时,计数器值-1;当计数器值为0时不能再被调用,适用大部分gc算法;但不能解决对象循环互调;
2、可达性分析算法 通过"GC Roots"对象作为起始点,从起始节点开始向下搜索,走过的路径称为引用链(reference chain),当一个对象与GC Roots没有链接时,则该对象是不可用的。
可以作为GC Roots对象包括:
jvm栈(栈中本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象 (单例模式 final A a;)
JNI(c++)中引用的对象
1.2之后对引用进行看扩充,将引用分为:
强引用(String Reference),类似 A a = new A(),只要a还会使用,收集器不会收集a空间
软引用(Soft Reference), 弱引用被回收后,还是不能消除内存溢出,溢出前回收 软引用空间
弱引用(Weak Reference),下次gc收集垃圾时,被回收
虚引用(Phantom Reference);关联对象,在对象被回收之前返回一个系统信息,不能通过虚引用取得实例,该空间已被回收;


对象的自我救赎finalize()
[color=green]一个对象被回收前至少要经历两次标记,可达性分析后发现与GC Roots没有连接时,将进行第一次标记, 并筛选该对象是否需要执行finalize()方法[/color]; 如果该对象被判定有必要执行finalize方法则将放入F-Queue列队,由低级Finalizer线程去触发它,finalize()提供给对象最后一次不回收的机会,只要和引用链上任何一个对象建立关联即可:

public class Test {
public static Test t=null;
public void isAlive(){
System.out.println("still here");
}
protected void finalize(){
System.out.println("执行finalize方法");
t = this; //自我引用
}
public static void main(String...s) throws Exception{
t = new Test();
t=null;
System.out.println("is here ?");
System.gc();
//执行gc()时触发finalize()方法,finalize方法优先级很低,不设置等待,就会出现没有执行就执行下一条语句了;
Thread.sleep(500);
t.isAlive();
System.out.println(t.hashCode());
//执行了finalize()方法,t复活了,但只能复活一次,若再执行:
t=null;
System.out.println("is here ?");
System.gc();
Thread.sleep(500);
//判定对象t是否还在heap中存在
System.out.println(t==null);
}
}

输出:
is here ?
执行finalize方法
still here //heap中还存在
5629279
is here ?
true //表示已被回收

回收方法区,jvm规范中讲过可以不要求jvm对方法区的垃圾回收,因为能释放的空间很少。永久代的垃圾收集主要有两部分:废弃常量和无用的类。
回收常量与回收heap类似,而回收无用的类比较复杂,判断是否为无用的类:
java heap中不存在该类的任何实例
该类的类类加载已经被回收
该类的Class对象没有被任何地方引用

垃圾收集算法:
标记-清除(Mark- sweep)
标记-整理(Mark- compact)
复制(Copying)(两块内存)
分代收集算法(老年代、新生代)
新生代中98%的会被回收,将新生代分为Eden(大块)、两个survival;每次使用Eden和其中一个survival,当回收时,将Eden和survival中存活的对象一次性的复制到另外一块survival空间上,然后格式化Eden和刚才用过的survival空间,HotSpot默认Eden与survival大小比例8:1,新生代中的90%用来装载新生对象,10%用来转载存活的对象。

垃圾收集器是垃圾收集算法的具体实现。Java规范对垃圾收集器的实现没有做任何规定,因此不同的虚拟机提供的垃圾收集器可能有很大差异。HotSpot虚拟机1.7版本使用了多种收集器。(HotSpot使用G1的垃圾收集器)

[img]http://dl2.iteye.com/upload/attachment/0106/2389/79ccb914-6eda-3838-a73f-b05c0ac56afc.jpg[/img]
共有7种作用不不同分代的收集器,其中Serial、ParNew、Parallel Scavenge(并行清除)属于新生代收集器,CMS、Serial Old(MSC) Parallel Old属于老年代收集器,G1可以作用于这两部分。相互连线表示收集器可以搭配使用。

1、Serial (连续的、串行)收集器
Serial收集器是最基本、发展历史最为悠久的收集器。在曾经的JDK1.3之前是新生代收集的唯一选择。
这个收集器是一个单线程的收集器(即只会使用一个CPU或一条收集线程),在它进行垃圾收集的时,必须暂停其他所有的工作线程(Stop The World),直到它收集结束。这个过程是由虚拟机后台发起并自动完成的,对用户不可见的情况下把用户正常的工作线程全部停掉,这对许多应用是无法接受的。
[img]http://dl2.iteye.com/upload/attachment/0106/2392/e1a05305-684c-3f9f-834b-f9758dee1b5f.jpg[/img]
为了消除或减少“Stop The World”停顿,从Serial 到Parallel(平行的、并行) 收集器,再到Concurrent Mark Sweep(CMS 并发标记-清除)到Garbage First(G1)收集器,越来越复杂,性能也越来越好,用户停顿时间越来越小。虽然Serial有着这一无法消除的影响,但是它仍旧是虚拟机运行在Client 模式下的默认新生代收集器。在单CPU环境来说,Serial 由于没有线程交互的开销,专心做垃圾收集,因而具有最高的收集效率。在用户的桌面应用中,分配给虚拟机的内存一般不会很大,收集一两百M的新生代所用的停顿时间完全可以控制在一百ms之内。所以,Serial收集器对于运行在Client模式下的虚拟机来说是一个很好地选择。收集器可用的控制参数如下:
-XX:+UserSerialGC 在新生代和老年代使用串行收集器
-XX:+SurvivorRatio 设置eden和survivor区大小的比例
-XX:+PretenureSizeThreshold 直接晋升到年老代的对象大小,设置此参数后,超过该大小的对象直接在年老代中分配内存
-XX:+MaxTenuringThreshold 直接晋升到年老代的对象年龄,每个对象在一次Minor GC之后还存活,则年龄加1,当年龄超过该值时进入年老代

2、ParNew收集器
ParNew 收集器其实就是serial 收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为与Serial收集器一样。但它却是Server模式下的虚拟机中首选的新生代收集器,与性能无关的一个原因是,除了Serial收集器外,只有它能与CMS收集器配合工作,后者是HotSpot 虚拟机中第一款真正意义上的并发(Concurrent)收集器,它第一次实现了让垃圾收集线程与用户线程同时工作。
在多核多线程系统中,使用-XX:ParallelGCThreads参数限制垃圾收集线程数。
ParNew收集器也是使用-XX:+UseConcMarkSweepGC选项后的默认新生代收集器,也可以使用-XX:+UseParNewGC来指定它。
关于垃圾收集中的并发和并行,可以解释如下.
并行(Parallel):指多条垃圾收集线程并行工作,用户线程仍处于等待状态。
并发(Concurrent):指用户线程与垃圾收集线程同时执行,用户程序继续运行,而垃圾收集程序运行在另一个cpu上。
3、Parallel Scavenge (并发清除)收集器
Parallel Scavenge收集器也是新生代收集器,使用复制算法,也是并行的多线程收集器,和ParNew 大致一样。但是Parallel Scavenge 的关注点与其他收集器不同,CMS等关注于尽可能缩短用户线程停顿时间,而Parallel Scavenge目标则是达到一个可控制的吞吐量(Throughput)。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗的时间的比值,如虚拟机运行了100分钟,垃圾收集花掉了1分钟,那么吞吐量便是99%。
-XX:+UseParNewGC 打开此开关参数后,使用ParNew+Serial Old收集器组合进行垃圾收集。
-XX:+UseParallelOldGC 打开此开关参数后,使用Parallel Scavenge+Parallel Old收集器组合进行垃圾收集。
-XX:+ParallelGCThreads 设置并行GC时进行内存回收的线程数。

-XX:+MaxGCPauseMillis Parallel Scavenge收集器最大GC停顿时间(>0)。
-XX:GCTimeRatio 直接设置吞吐量大小(0-100)。
-XX:+GCTimeRation Parallel Scavenge收集器运行时间占总时间比率。
-XX:+UseAdaptiveSizePolicy java虚拟机动态自适应策略,动态调整年老代对象年龄和各个区域大小。

4、Serial Old 收集器jdk1.5
Serial Old 收集器是Serial 的老年代版本,同样是一个单线程收集器,使用“标记-整理”算法。主要意义也是在Client 模式下使用。

5、Parallel Old 收集器jdk1.6
Parallel Old是Parallel Scavenge 收集器的老年代版本,使用多线程和“标记-整理”算法。
在它出现之前,由于新生带收集器Paralle Scavenge 只能和Serial Old 配合,老年代Serial Old 收集器是单线程而Paralle Scavenge是多线程,即使使用Parallel Scavenge 收集器也不能在整体应用上获得吞吐量最大化的效果。这种组合甚至不如 ParNew (多线程)+ CMS 的组合给力。直到 Parallel Old的出现。 Parallel Old工作过程如下图。

[img]http://dl2.iteye.com/upload/attachment/0106/2394/b27c988b-56e1-33d7-b19d-ed6f0c7c11fe.jpg[/img]

6、CMS 收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。主要用于互联网或B/S系统的服务端,这类应用尤其重视服务的响应速度。
前面的都是并行收集器,CMS是整体上市并发的(低停顿收集器);
从名字可以看出,CMS是基于“标记-清除”算法的,运作过程更加复杂一些,分为4个步骤:

①.初始标记(CMS initial mark) 标记GC Roots直接关联的对象
②.并发标记(CMS concurrenr mark) 可达性分析算法
③.重新标记(CMS remark) 并发变动修改
④.并发清除(CMS concurrent sweep)
其中初始标记、重新标记这两个步骤任然需要停顿其他用户线程。初始标记仅仅只是标记出GC ROOTS能直接关联到的对象,速度很快,并发标记阶段是进行GC ROOTS 根搜索算法阶段,会判定对象是否存活。而重新标记阶段则是为了修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间会比初始标记阶段稍长,但比并发标记阶段要短。由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以整体来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。执行过程如下图。

[img]http://dl2.iteye.com/upload/attachment/0106/2396/a9372fd6-b770-33a9-a63f-53c72ef423c3.jpg[/img]
CMS收集器的优点:并发收集、低停顿,但是CMS还远远达不到完美,主要有三个显著缺点:
CMS收集器对CPU资源非常敏感。在并发阶段,虽然不会导致用户线程停顿,但是会占用CPU资源而导致引用程序变慢,总吞吐量下降。CMS默认启动的回收线程数是:(CPU数量+3) / 4。
CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure“,失败后而导致另一次Full GC的产生。由于CMS并发清理阶段用户线程还在运行,伴随程序的运行自热会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在本次收集中处理它们,只好留待下一次GC时将其清理掉。这一部分垃圾称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,即需要预留足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分内存空间提供并发收集时的程序运作使用。在默认设置下,CMS收集器在老年代使用了68%的空间时就会被激活,也可以通过参数-XX:CMSInitiatingOccupancyFraction的值来提供触发百分比,以降低内存回收次数提高性能。要是CMS运行期间预留的内存无法满足程序其他线程需要,就会出现“Concurrent Mode Failure”失败,这时候虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。所以说参数-XX:CMSInitiatingOccupancyFraction设置的过高将会很容易导致“Concurrent Mode Failure”失败,性能反而降低。
CMS是基于“标记-清除”算法实现的收集器,使用“标记-清除”算法收集后,会产生大量碎片。空间碎片太多时,将会给对象分配带来很多麻烦,比如说大对象,内存空间找不到连续的空间来分配不得不提前触发一次Full GC。为了解决这个问题,CMS收集器提供了一个-XX:UseCMSCompactAtFullCollection开关参数,用于在Full GC之后增加一个碎片整理过程,还可通过-XX:CMSFullGCBeforeCompaction参数设置执行多少次不压缩的Full GC之后,跟着来一次碎片整理过程。
7、G1 收集器jdk1.7
G1 是面向服务端应用的垃圾收集器。具有如下几个特点。
并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop-The-World停顿的时间,其他(除CMS)收集器原本需要停顿Java线程,G1收集器仍然可以通过并发的方式让Java程序继续执行。
分代收集:与其他收集器一样,分代概念在G1中依然得以保留。虽然G1可以不需其他收集器配合就能独立管理整个GC堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。
空间整合:与CMS的“标记-清理”算法不同,G1从整体看来是基于“标记-整理”算法实现的收集器,从局部(两个Region之间)上看是基于“复制”算法实现,无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。
可预测的停顿:这是G1相对于CMS的另外一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器特征了。
在G1之前的其他收集器进行收集的范围都是新生代和老年代,而G1收集时,java堆的内存布局与其他收集器有很大区别,它将整个java堆划分为多个大小相等的独立区域(region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都属于Region集合。
   G1收集器之所以能建立可预测的停顿时间模型,因为它可以避免全堆内存的垃圾收集(使用Remembered Set避免全堆扫描)。G1跟踪各个Region里面的垃圾堆积的价值大小(回收后会获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回价值最大的Region(这也就是Garbage-First名称的来由)。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内获可以获取尽可能高的收集效率。
G1收集器的运作大致可划分为以下几个步骤:
初始标记(Initial Marking)
并发标记(Concurrent Marking)
最终标记(Final Marking)
筛选回收(Live Data Counting and Evacuation)
[img]http://dl2.iteye.com/upload/attachment/0106/2398/696ec49c-300e-376d-8e48-51b63de9d014.jpg[/img]

gc日志:
JVM的GC日志的主要参数包括如下几个:
-XX:+PrintGC 输出GC日志
-XX:+PrintGCDetails 输出GC的详细日志
-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
-Xloggc:D:/Documents/gc.log 日志文件的输出路径
在eclipse中参数设置中添加:
Java代码 收藏代码
-XX:+PrintGCDetails
-XX:+PrintHeapAtGC
-XX:+PrintGCDateStamps
-XX:+PrintTenuringDistribution
-verbose:gc
-Xloggc:D:/Documents/gc.log
打开文件:
Java代码 收藏代码
Heap
def new generation total 4928K, used 691K [0x248f0000, 0x24e40000, 0x29e40000)
eden space 4416K, 15% used [0x248f0000, 0x2499cf80, 0x24d40000)
from space 512K, 0% used [0x24d40000, 0x24d40000, 0x24dc0000)
to space 512K, 0% used [0x24dc0000, 0x24dc0000, 0x24e40000)
tenured generation total 10944K, used 0K [0x29e40000, 0x2a8f0000, 0x348f0000)
the space 10944K, 0% used [0x29e40000, 0x29e40000, 0x29e40200, 0x2a8f0000)
compacting perm gen total 12288K, used 146K [0x348f0000, 0x354f0000, 0x388f0000)
the space 12288K, 1% used [0x348f0000, 0x34914b50, 0x34914c00, 0x354f0000)
ro space 10240K, 45% used [0x388f0000, 0x38d77290, 0x38d77400, 0x392f0000)
rw space 12288K, 54% used [0x392f0000, 0x3997ace8, 0x3997ae00, 0x39ef0000)
参看:http://blog.csdn.net/huangzhaoyang2009/article/details/11860757
http://wentao365.iteye.com/blog/1142837

对象的内存分配,一般就是在堆上分配空间,对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB(缓存)上分配。也可能会直接分配在老年代中,分配的规则并不是百分之百固定的,其细节取决于当前使用的是哪一种垃圾收集器组合,还有虚拟机中与内存相关的参数的设置。
1、对象优先在Eden分配
大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。
2、大对象直接进入老年代
大对象就是指需要大量连续内存空间的Java对象,典型大对象:长字符串及数组。大对象对虚拟机的内存分配来说就是一个坏消息(遇到一群“朝生夕灭”的“短命大对象”,写程序时应当避免),经常出现大对象容易导致内存还有不少空间时就提前触发垃圾收集以获取足够的连续空间来“安置”它们。
虚拟机提供了一个-XX:PretenureSizeThreshold=3*1024*1024参数,令大于这个设置值的对象直接在老年代中分配。这样做的目的是避免在Eden区及两个Survivor区之间发生大量的内存拷贝
3、长期存活的对象将进入老年代
内存回收时应该识别哪些对象应当放在新生代,哪些对象应放在老年代中。为了做到这点,虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并将对象年龄设为1。对象在Survivor区中每熬过一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁)时,就会被晋升到老年代中。对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold=15来设置。
4、 动态对象年龄判定
为了能更好地适应不同程序的内存状况,虚拟机并不总是要求对象的年龄必须达到MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。
5、空间分配担保
在发生Minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,则改为直接进行一次Full GC。如果小于,则查看HandlePromotionFailure设置是否允许担保失败;如果允许,那只会进行Minor GC;如果不允许,则也要改为进行一次Full GC。大部分情况下都还是会将HandlePromotionFailure开关打开,避免Full GC过于频繁。


在java/bin目录中除了java.exe和javac.exe之外,还有很多exe文件, 这些执行文件大多数是java\lib\tools.jar类库的一层薄包装而已,它们主要的功能代码是在tools类库中实现的。
Sun JDK 监控和故障处理工具
(1)jps:JVM process Status Tool,显示指定系统内所有的HotSpot虚拟机进程
(2)jstat:JVM Statistics(统计) Monitoring(检测) Tool,用于收集HotSpot虚拟机各方面的运行数据
(3)jinfo:Configuration Info for Java,显示虚拟机配置信息
(4)jmap:Memory Map for Java,生成虚拟机的内存转储快照(heapdump文件)
(5)jhat:JVM Heap Dump(仓库) Browser,用于分析headdump文件,它会建立一个HTTP/HTML服务器,让用户可以在浏览器上查看分析结果
(6)jstack:Stack Trace(跟踪) for Java,显示虚拟机的线程快照
1、 jps:虚拟机进程状况工具
它的作用是显示当前系统的java进程情况,及其id号。我们可以通过它来查看我们到底启动了几个java进程(因为每一个java程序都会独占一个java虚拟机),和他们的进程号(为下面几个程序做准备),并可通过opt来查看这些进程的详细启动参数。
使用方法:在当前命令行下打 jps(需要JAVA_HOME,没有的话,到改程序的目录下打) 。

C:\Users\skx>jps
7508 Jps //这个是变化的
4564 org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar
C:\Users\skx>jps -q
1132
4564
C:\Users\skx>jps -m
8116 Jps -m

4564 org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar -os win32 ..... ......
C:\Users\skx>jps -l
4564 D:\ZmyExe\eclipse-jee-luna-R-win32\eclipse\\plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar

3940 sun.tools.jps.Jps
C:\Users\skx>jps -v
2100 Jps -Dapplication.home=D:\ZmyExe\java -Xms8m
4564 org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar -Dosgi.requiredJavaVersion=1.6 -Xms40m -Xmx512m -XX:MaxPermSize=256m

2、jstat:虚拟机统计信息监视工具
用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或远程(需要远程主机提供RMI支持,Sun提供了jstatd工具可以方便地建立远程RMI服务器)虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。

先查出jvm的线程jps 在使用jstat;
格式如:C:\Users\skx>jstat -class 4564
Loaded Bytes Unloaded Bytes Time
17788 21748.5 101 72.7 10.91
jstat命令格式为:
jstat option vmid [interval count]
使用gcutil:
C:\Users\skx>jstat -gcutil 4564
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 0.00 1.68 50.48 99.87 24 0.272 47 11.143 11.415


参数解释:
Options — 选项,上面列出的选项
vmid — VM的进程号,即当前运行的java进程号
interval– 间隔时间,单位为毫秒
count — 打印次数,如果缺省则打印无数次
S0 — Heap上的 Survivor space 0 区已使用空间的百分比
S1 — Heap上的 Survivor space 1 区已使用空间的百分比
E — Heap上的 Eden space 区已使用空间的百分比 (新生代)
O — Heap上的 Old space 区已使用空间的百分比
P — Perm space 区已使用空间的百分比 permanent
YGC — 从应用程序启动到采样时发生 Young GC 的次数
YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC — 从应用程序启动到采样时发生 Full GC 的次数
FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
对于命令格式中的vmid与LVMID需要特别说明一下:如果是本地虚拟机进程,VMID和LVMID是一致的,如果是远程虚拟机进程,那VMID的格式应该是:
[protoco:][//]lvmid[@hostname[:port]/servername]
参数interval和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次,假设需要每秒查询一次进程号4564垃圾收集的情况,一个查询10次,那命令应该是
C:\Users\skx>jstat -gc 4564 1000 10

3、 jinfo:Java配置信息工具
jinfo命令格式:
jinfo [ option ] pid
Java代码 收藏代码
where <option> is one of:
-flag <name> to print the value of the named VM flag
-flag [+|-]<name> to enable or disable the named VM flag
-flag <name>=<value> to set the named VM flag to the given value
-flags to print VM flags
-sysprops to print Java system properties
<no option> to print both of the above
-h | -help to print this help message
4、 jmap:Java内存映像工具
jmap命令格式:
jmap [ option ] vmid


5、jhat:虚拟机堆转储快照分析工具
Sun JDK提供jhat(JVM Heap Analysis Tool)命令与jmap命令搭配使用,来分析jmap生成的堆存储快照。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看。
6、jstack:Java堆栈跟踪工具
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法的堆栈的机会,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者等待着什么资源。
jstack命令格式:
jstack [ option ] vmid
option选项的合法值与具体含义为:
(1)-F : 当正常输出的请求不被响应时,强制输出线程堆栈
(2)-l:除堆栈外,显示关于锁的附加信息
(3)-m:如果调用到本地方法的话,可以显示C/C++的堆栈

JDK的可视化工具
1、JConsole:Java监视与管理控制台
2、VisualVM:多合一故障处理工具(需要下载安装)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值