要了解Java垃圾收集机制,先理解JVM内存模式是非常重要的。今天我们将会了解JVM内存的各个部分、如何监控以及垃圾收集调优。
创新互联公司专注于三沙企业网站建设,响应式网站开发,商城网站制作。三沙网站建设公司,为三沙等地区提供建站服务。全流程定制开发,专业设计,全程项目跟踪,创新互联公司专业和态度为您提供的服务
Java(JVM)内存模型
正如你从上面的图片看到的,JVM内存被分成多个独立的部分。广泛地说,JVM堆内存被分为两部分——年轻代(Young Generation)和老年代(Old Generation)。
年轻代
年轻代是所有新对象产生的地方。当年轻代内存空间被用完时,就会触发垃圾回收。这个垃圾回收叫做Minor GC。年轻代被分为3个部分——Enden区和两个Survivor区。
年轻代空间的要点:
年老代
年老代内存里包含了长期存活的对象和经过多次Minor GC后依然存活下来的对象。通常会在老年代内存被占满时进行垃圾回收。老年代的垃圾收集叫做Major GC。Major GC会花费更多的时间。
Stop the World事件
所有的垃圾收集都是“Stop the World”事件,因为所有的应用线程都会停下来直到操作完成(所以叫“Stop the World”)。
因为年轻代里的对象都是一些临时(short-lived )对象,执行Minor GC非常快,所以应用不会受到(“Stop the World”)影响。
由于Major GC会检查所有存活的对象,因此会花费更长的时间。应该尽量减少Major GC。因为Major GC会在垃圾回收期间让你的应用反应迟钝,所以如果你有一个需要快速响应的应用发生多次Major GC,你会看到超时错误。
垃圾回收时间取决于垃圾回收策略。这就是为什么有必要去监控垃圾收集和对垃圾收集进行调优。从而避免要求快速响应的应用出现超时错误。
***代
***代或者“Perm Gen”包含了JVM需要的应用元数据,这些元数据描述了在应用里使用的类和方法。注意,***代不是Java堆内存的一部分。
***代存放JVM运行时使用的类。***代同样包含了Java SE库的类和方法。***代的对象在full GC时进行垃圾收集。
方法区
方法区是***代空间的一部分,并用来存储类型信息(运行时常量和静态变量)和方法代码和构造函数代码。
内存池
如果JVM实现支持,JVM内存管理会为创建内存池,用来为不变对象创建对象池。字符串池就是内存池类型的一个很好的例子。内存池可以属于堆或者***代,这取决于JVM内存管理的实现。
运行时常量池
运行时常量池是每个类常量池的运行时代表。它包含了类的运行时常量和静态方法。运行时常量池是方法区的一部分。
Java栈内存
Java栈内存用于运行线程。它们包含了方法里的临时数据、堆里其它对象引用的特定数据。你可以阅读栈内存和堆内存的区别。
Java 堆内存开关
Java提供了大量的内存开关(参数),我们可以用它来设置内存大小和它们的比例。下面是一些常用的开关:
VM 开关 | VM 开关描述 |
---|---|
-Xms | 设置JVM启动时堆的初始化大小。 |
-Xmx | 设置堆***值。 |
-Xmn | 设置年轻代的空间大小,剩下的为老年代的空间大小。 |
-XX:PermGen | 设置***代内存的初始化大小。 |
-XX:MaxPermGen | 设置***代的***值。 |
-XX:SurvivorRatio | 提供Eden区和survivor区的空间比例。比如,如果年轻代的大小为10m并且VM开关是-XX:SurvivorRatio=2,那么将会保留5m内存给Eden区和每个Survivor区分配2.5m内存。默认比例是8。 |
-XX:NewRatio | 提供年老代和年轻代的比例大小。默认值是2。 |
Java垃圾回收大多数时候,上面的选项已经足够使用了。但是如果你还想了解其他的选项,那么请查看JVM选项官方网页。
Java垃圾回收会找出没用的对象,把它从内存中移除并释放出内存给以后创建的对象使用。Java程序语言中的一个***优点是自动垃圾回收,不像其他的程序语言那样需要手动分配和释放内存,比如C语言。
垃圾收集器是一个后台运行程序。它管理着内存中的所有对象并找出没被引用的对象。所有的这些未引用的对象都会被删除,回收它们的空间并分配给其他对象。
一个基本的垃圾回收过程涉及三个步骤:
简单标记和清除方法存在两个问题:
上面简单清除方法的问题在于Java垃圾收集的分代回收的,而且在堆内存里有年轻代和年老代两个区域。我已经在上面解释了Minor GC和Major GC是怎样扫描对象,以及如何把对象从一个分代空间移到另外一个分代空间。
Java垃圾回收类型
这里有五种可以在应用里使用的垃圾回收类型。仅需要使用JVM开关就可以在我们的应用里启用垃圾回收策略。让我们一起来逐一了解:
Java垃圾收集监控
我们可以使用命令行和图形工具来监控监控应用垃圾回收。例如,我使用Java SE下载页中的一个demo来实验。
如果你想使用同样的应用,可以到Java SE下载页面下载JDK 7和JavaFX演示和示例。我使用的示例应用是Java2Demo.jar,它位于 jdk1.7.0_55/demo/jfc/Java2D 目录下。这只是一个可选步骤,你可以运行GC监控命令监控任何Java应用。
我打开演示应用使用的命令是:
- 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
jsat
可以使用jstat命令行工具监控JVM内存和垃圾回收。标准的JDK已经附带了jstat,所以不需要做任何额外的事情就可以得到它。
要运行jstat你需要知道应用的进程id,你可以使用 ps -eaf | grep java 命令获取进程id。
- 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命令了,就像下面展示的一样:
- pankaj@Pankaj:~$ jstat -gc 9582 1000
- S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
- 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
- 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
- 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
- 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
- 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
- 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
- 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的远程服务器上运行jstat。注意:我们是通过 -Xmn10m 选项来指定S0C、S1C和EC的总和为10m的。
Java VisualVM及Visual GC插件
如果你想在GUI里查看内存和GC,那么可以使用jvisualvm工具。Java VisualVM同样是JDK的一部分,所以你不需要单独去下载。
在终端运行jvisualvm命令启动Java VisualVM程序。一旦启动程序,你需要从Tools->Plugins选项安装Visual GC插件,就像下面图片展示的。
安装完Visual GC插件后,从左边栏打开应用并把视角转到Visual GC部分。你将会得到关于JVM内存和垃圾收集详情,如下图所示。
Java垃圾回收调优
Java垃圾回收调优应该是提升应用吞吐量的***一个选择。在你发现应用由于长时间垃圾回收导致了应用性能下降、出现超时的时候,应该考虑Java垃圾收集调优。
如果你在日志里看到 java.lang.OutOfMemoryError: PermGen space错误,那么可以尝试使用 -XX:PermGen 和 -XX:MaxPermGen JVM选项去监控并增加Perm Gen内存空间。你也可以尝试使用-XX:+CMSClassUnloadingEnabled并查看使用CMS垃圾收集器的执行性能。
如果你看到了大量的Full GC操作,那么你应该尝试增大老年代的内存空间。
全面垃圾收集调优要花费大量的努力和时间,这里没有一尘不变的硬性调优规则。你需要去尝试不同的选项并且对这些选项进行对比,从而找出最适合自己应用的方案。
这就是所有的Java内存模型和垃圾回收内容。希望对你理解JVM内存和垃圾收集过程有所帮助。
原文链接: journaldev 翻译: ImportNew.com - 进林
译文链接: http://www.importnew.com/14086.html
当前标题:Java内存与垃圾回收调优
文章来源:http://www.mswzjz.cn/qtweb/news11/45611.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能