博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
转载:JVM GC机制
阅读量:5281 次
发布时间:2019-06-14

本文共 2706 字,大约阅读时间需要 9 分钟。

转载于:

       内存管理和垃圾回收是JVM 非常关键的点,对Java性能的剖析而言,了解内存管理和垃圾回收的基本策略非常重要。本篇对Sun JVM 6.0的内存管理和垃圾回收做大概的描述。

      1.内存管理 

      在程序运行过程当中,会创建大量的对象,这些对象,大部分是短周期的对象,小部分是长周期的对象,对于短周期的对象,需要频繁地进行垃圾回收以保证无用对 象尽早被释放掉,对于长周期对象,则不需要频率垃圾回收以确保无谓地垃圾扫描检测。为解决这种矛盾,Sun JVM 的内存管理采用分代的策略。 
      1)年轻代(Young Gen):年轻代主要存放新创建的对象,内存大小相对会比较小,垃圾回收会比较频繁。年轻代分成1个Eden Space和2个Suvivor Space(命名为A和B) 
当对象在堆创建时,将进入年轻代的Eden Space。 
垃圾回收器进行垃圾回收时,扫描Eden Space和A Suvivor Space,如果对象仍然存活,则复制到B Suvivor Space,如果B Suvivor Space已经满,则复制 Old Gen 
扫描A Suvivor Space时,如果对象已经经过了几次的扫描仍然存活,JVM 认为其为一个Old对象,则将其移到Old Gen。 
扫描完毕后,JVM 将Eden Space和A Suvivor Space清空,然后交换A和B的角色(即下次垃圾回收时会扫描Eden Space和BSuvivor Space。

      我们可以看到:Young Gen垃圾回收时,采用将存活对象复制到到空的Suvivor Space的方式来确保不存在内存碎片,采用空间换时间的方式来加速内存垃圾回收。 

      2)年老代(Tenured Gen):年老代主要存放JVM 认 为比较old的对象(经过几次的Young Gen的垃圾回收后仍然存在),内存大小相对会比较大,垃圾回收也相对没有那么频繁(譬如可能几个小时一次)。年老代主要采用压缩的方式来避免内存碎片 (将存活对象移动到内存片的一边),当然,有些垃圾回收器(譬如CMS垃圾回收器)出于效率的原因,可能会不进行压缩。 
      3)持久代(Perm Gen):持久代主要存放类定义、字节码和常量等很少会变更的信息

1. Heap设定与垃圾回收
Java Heap分为3个区,Young,Old和Permanent。Young保存刚实例化的对象。当该区被填满时,
GC 会将对象移到Old区。Permanent区则负责保存反射对象,本文不讨论该区。
JVM 的Heap分配可以使用-X参数设定,
-Xms 初始Heap大小
-Xmx java heap最大值
-Xmn young generation的heap大小

 JVM 有2个GC 线程。第一个线程负责回收Heap的Young区。第二个线程在Heap不足时,遍历Heap,将Young 区升级为Older区。Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,因为第二个线程被迫运行会降低JVM 的性能。

为什么一些程序频繁发生
GC ?有如下原因:
l         程序内调用了System.
gc ()或Runtime.
gc ()。
l         一些中间件软件调用自己的
GC 方法,此时需要设置参数禁止这些
GC 。
l         Java的Heap太小,一般默认的Heap值都很小。
l         频繁实例化对象,Release对象。此时尽量保存并重用对象,例如使用StringBuffer()和String()。
如果你发现每次
GC 后,Heap的剩余空间会是总空间的50%,这表示你的Heap处于健康状态。许多Server端的Java程序每次
GC 后最好能有65%的剩余空间。
经验之谈:
1 . Server 端 JVM 最好将 -Xms 和 -Xmx 设为相同值。为了优化 GC ,最好让 -Xmn 值约等于 -Xmx 的 1/3[2]。
2 .一个 GUI 程序最好是每 10 到 20 秒间运行一次 GC ,每次在半秒之内完成 [2] 。
注意:
1.增加Heap的大小虽然会降低GC 的频率,但也增加了每次GC 的时间。并且GC 运行时,所有的用户线程将暂停,也就是GC 期间,Java应用程序不做任何工作。
2.Heap大小并不决定进程的内存使用量。进程的内存使用量要大于-Xmx定义的值,因为Java为其他任务分配内存,例如每个线程的Stack等。
 
2.Stack的设定
每个线程都有他自己的Stack。 
-Xss 每个线的 Stack 大小

 Stack的大小限制着线程的数量。如果Stack过大就好导致内存溢漏。-Xss参数决定Stack大小,例如-Xss1024K。如果Stack太小,也会导致Stack溢漏。

3.硬件环境
硬件环境也影响
GC 的效率,例如机器的种类,内存,swap空间,和CPU的数量。
如果你的程序需要频繁创建很多transient对象,会导致
JVM 频繁
GC 。这种情况你可以增加机器的内存,来减少Swap空间的使用[2]。
4.4种
GC
第一种为单线程
GC ,也是默认的
GC 。,该
GC 适用于单CPU机器。
第二种为Throughput 
GC ,是多线程的
GC ,适用于多CPU,使用大量线程的程序。第二种
GC 与第一种
GC 相似,不同在于
GC 在收集Young区是多线程的,但在Old区和第一种一样,仍然采用单线程。-XX:+UseParallelGC参数启动该
GC 。
第三种为Concurrent Low Pause 
GC ,类似于第一种,适用于多CPU,并要求缩短因
GC 造成程序停滞的时间。这种
GC 可以在Old区的回收同时,运行应用程序。-XX:+UseConcMarkSweepGC参数启动该
GC 。
第四种为Incremental Low Pause 
GC ,适用于要求缩短因
GC 造成程序停滞的时间。这种
GC 可以在Young区回收的同时,回收一部分Old区对象。-Xincgc参数启动该
GC 。
4种
GC 的具体描述参见[3]。
 
参考文章:
1. 
JVM Tuning. 
2. Performance tuning Java: Tuning steps
3. Tuning Garbage Collection with the 1.4.2 JavaTM Virtual Machine .

转载于:https://www.cnblogs.com/wrencai/articles/4232239.html

你可能感兴趣的文章
Struts2中国际化
查看>>
MySql允许远程访问
查看>>
Ubuntu下Zabbix安装及使用问题
查看>>
.NET 页面跳转、返回与刷新
查看>>
4.14 上午
查看>>
PHP漏洞全解(详细介绍)
查看>>
[LeetCode] Spiral Matrix II 螺旋矩阵之二
查看>>
[LeetCode] Longest Increasing Path in a Matrix 矩阵中的最长递增路径
查看>>
[LeetCode] Read N Characters Given Read4 II - Call multiple times 用Read4来读取N个字符之二 - 多次调用...
查看>>
利用cmd实现组网产品任务
查看>>
飞思卡尔笔记3
查看>>
java实现最大堆
查看>>
sharepoint 2007和2010 在新建页面隐藏标题字段
查看>>
ORACLE日期时间函数大全
查看>>
c语言 保留两位小数
查看>>
分布式文件系统HDFS 练习
查看>>
正则表达式的数字验证 实例 验证电话号码 身份证号码
查看>>
unity, 在编辑界面中隐藏公开变量
查看>>
[读书笔记] CSS揭秘-背景与边框
查看>>
把多条成绩单(不同学科,同一个人),合并成一条记录 用case when group by
查看>>