Java虚拟机内存模型及垃圾回收监控调优html
若是你想理解Java垃圾回收若是工做,那么理解JVM的内存模型就显的很是重要。今天咱们就来看看JVM内存的各不一样部分及若是监控和实现垃圾回收调优。java
JVM内存模型 算法
正如你上图所看到的,JVM内存能够划分为不一样的部分,广义上,JVM堆内存能够划分为两部分:年轻代和老年代(Young Generation and Old Generation)编程
年轻代(Young Generation)服务器
年轻代用于存放由new所生成的对象。当年轻代空间满时,垃圾回收就会执行。这个垃圾回收咱们称之为 最小化垃圾回收(Minor GC)。年轻代又能够分为三分部: 一个Eden内存区(Eden Memory)和两个Survivor 内存区(Survivor Memory)。多线程
关于年轻代的重点:并发
老年代(Old Generation)oracle
老年代内存包含那些通过屡次最小化GC且存活的对象。 一般当老年代内存满时垃圾回收会被执行。咱们称之为大GC (Major GC),一般这个过程会花费很长的时间。jvm
Stop the World Eventjsp
全部的垃圾回收都是“阻塞”事件(“Stop the World” events) ,由于全部应用程序线程必须中止,直到垃圾回收操做完成以后才能继续。
因为年轻代老是保存着短时间存活的对象,最小化GC很是快,应用程序也不会受到影响。然而大GC(Major GC)因为它要检查全部存活的对象,因此须要花费很长的时间。 大GC会在垃圾回收期间使得你的应用程序没有任何响应,应最大化的减小此类GC。若是你有一个即时响应应用程序且老是有不少的大GC在执行。你会发现存在超时错误。
垃圾回器扫行的时间依赖于GC所使用的策略。这就是为何对于那些高响应用程序来讲,GC的监控与调优显得很是必要。
永久代(Permanent Generation)
永久代或持久代包含JVM用来描述应用程序中使用的类和方法的元数据。注意 永久代不是JAVA堆内存的一部分。
JVM在运行期间依据应用程序所使用的类来存入永久代,同时也包含Java SE库类各方法。 永久代中的对象经过全GC(Full GC)来进行垃圾回收。
方法区Method Area
方法区是永久代的一部分,用于存储类结构(运行时的常量和静态变量)及方法和构造的代码。
运行时常量池Runtime Constant Pool
运行时常量池是类中常量池在编译期的表示,它包含类的运行时常量,静态方法,它是方法区的一部分。
Java栈内存Java Stack Memory
Java 栈内存用于执行线程。包含方法短时间存活的特定值及方法中所涉及的指向堆中其它对象的引用。
Java 堆内存Switches(Java Heap Memory Switches)
提供了大量的内存Switch,咱们能够用来设置内存大小及它们的比率。一此经常使用的内存Switches以下。
VM Switch | VM Switch 描述 |
---|---|
-Xms | 设置JVM启动时堆初始值。 |
-Xmx | 设置堆的最大值 |
-Xmn | 设置年轻代的大小 |
-XX:PermGen | 设置永久代内存的初始值 |
-XX:MaxPermGen | 设置永久代内存的最大值 |
-XX:SurvivorRatio | 用于提供Eden区和Survivor区的比例, 例如,若是年轻代的大小为 10M,VM switch is -XX:SurvivorRatio=2 那么 5 M 分配给 Eden 区,每个Survivor 区为 2.5 M .默认比例大小为 8。 |
-XX:NewRatio | 老年代/新生代的比例. 默认值是 2. |
大多数状况下,上述选项是很是有用的。若是你也想试试其它参数能够查看 JVM 官方主页
JAVA GC
Java GC是从内存中标记、移除非可用对象并释放所分配的空间用于后续建立对像的过程。Java编程语言最大的功能之一就是自动垃圾回收。不像其它相似C的编程语言,它们的内存分配与回收能够人为操做。
GC是后台执行用于检查内存中的全部对象并找出未被任务程序所引用的对象。全部这些未引用的对象将被删除,同时空间也会被回收用于分配给其它对象。
关于标记、删除方法有两个问题:
1.因为新建立的对象将会变成不可用,全部效率上不是很高。
2.屡次GC后可用的对象很能在后续的GC后仍然可用。
上述方法的不足在于Java的GC是分代的,在堆内存中分年轻代和老年代。 前面我已经解释过基于最小化GC(Minor GC)和大GC(Major GC)对象是若是被扫描并从一个分代区移到别一个分区。
Java GC的类型
在应用程序中咱们可使用以下五种类型的GC。咱们可使用JVM相关设置为应用程序开启GC策略,如今咱们就来具体的看看.
G1垃圾收集器不一样于其它收集器,它没有年轻代、老年代空间,它将堆空间划分红多个相同大小的堆区域(heap regions),当调用一次垃圾回收,它首先收集实时性不是很高的区域的数据,所以称为”Garbage First”。有关详细的可参考个人另一篇Blog:Java垃圾收集器之--Garbage-First Collector 。
JAVA 垃圾收集监控
咱们可使用Java命令行和UI工具来监控应用程序的垃圾收集活动。下面的例子中,我使用Java SE Downloads 中一个演示程序。
若是你想使用一样的程序,前往 Java SE Downloads 页面下载JDK 7 and JavaFX Demos and Samples。 我使用的和序示例是Java2Demo.jar 能够在jdk1.7.0_55/demo/jfc/Java2D 目录中找到。固然了这步可选。你能够选用任何Java程序执行GC监控命令。
我使用的启动演示程序的命令是:
1
|
pankaj@Pankaj:~
/Downloads/jdk1
.7.0_55
/demo/jfc/Java2D
$ java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar Java2Demo.jar
|
JSTAT
咱们可使用 jstat 命令行工具来监控JVM内存和GC活动。标准的JDK中含有此命令。所以能够直接使用。
运行 jstat 以前你须要知道程序的进程ID号。你能够运行 ps -eaf | grep java 命令来获取。
1
2
3
|
pankaj@Pankaj:~$
ps -eaf | grep Java2Demo.jar
501 9582 11579 0 9:48PM ttys000 0:21.66
/usr/bin/java
-Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseG1GC -jar Java2Demo.jar
501 14073 14045 0 9:48PM ttys002 0:00.00
grep
Java2Demo.jar
|
个人Java程序的进程ID号为 9582.如今咱们能够以下执行jstat 命令。
1 pankaj@Pankaj:~$ jstat -gc 9582 1000 2 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 3 1024.0 1024.0 0.0 0.0 8192.0 7933.3 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 4 1024.0 1024.0 0.0 0.0 8192.0 8026.5 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 5 1024.0 1024.0 0.0 0.0 8192.0 8030.0 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 6 1024.0 1024.0 0.0 0.0 8192.0 8122.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 7 1024.0 1024.0 0.0 0.0 8192.0 8171.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 8 1024.0 1024.0 48.7 0.0 8192.0 106.7 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656 9 1024.0 1024.0 48.7 0.0 8192.0 145.8 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656
jstat命令的最后一个参数是每次输出的时间间隔,所以它会每隔一秒打印内存及垃圾回收数据。下面详细看看每列。
jstat的优势在于它能够在无GUI的远程服务器上执行。注意S0C, S1C 和EC之和为 10M ,与咱们经过JVM选项 -Xmn10m 设置的值同样。
Java VisualVM with Visual GC
若是你想在GUI下查看内存及GC操做。 那么你可使用 jvisualvm 工具。Java VisualVM 也一样包含在JDK中,你不须要单独下载。
只须要运行在终端上执行jvisualvm 命令来启动Java VisualVM程序。一旦启动,你须要经过Tools--》Plugins选项安装Visual GC 插件,正以下图所示。
Visual GC 安装完毕后,左边列中打开程序前往Visual GC 部分。你将会获得以下图所示的JVM内存及GC截图。
Java GC 调优是提升应用程序吞吐量的最后选择,只有当你发现长时间的GC致使性能降低而产生应用程序超时。
你会在日志中看到java.lang.OutOfMemoryError: PermGen space的错误信息。而后能够尝试监控并经过使用JVM 选项 -XX:PermGen and -XX:MaxPermGen 来增长Perm Gen内存空间。你或许也能够尝试使用-XX:+CMSClassUnloadingEnabled 来检查使用CMS垃圾收集的性能如何?
若是你发现大量的FUll GC操做,你能够试着增长老年代内存空间。
总之GC调优须要花费大量的精力和时间,这里绝没有什么硬性或者快速的规则。你须要尝试不一样的选项,比较他们,并找对你应用程序来讲最好的那个。
这就是全部有关Java内存模型和垃圾回收。我但愿这有助于你理解JVM内存模型及垃圾回收的过程。谢谢。
原文连接: JournalDev 翻译: TonySpark
译文连接: http://www.cnblogs.com/tonyspark/p/3731696.html
[ 转载请保留原文出处、译者和译文连接。]