您的位置:首页 > 其它

JVM内存模型和性能优化

2015-04-19 09:54 375 查看
JVM内存区域模型








1.方法区

也称"永久代” 、“非堆”,  它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。默认最小值为16MB,最大值为64MB,可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小。

运行时常量池:是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中。


2.虚拟机栈

描述的是java 方法执行的内存模型:每个方法被执行的时候 都会创建一个“栈帧”用于存储局部变量表(包括参数)、操作栈、方法出口等信息。每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。声明周期与线程相同,是线程私有的。

 局部变量表存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、 double)、对象引用(引用指针,并非对象本身),其中64位长度的long和double类型的数据会占用2个局部变量的空间,其余数据类型只占1 个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量是完全确定的,在运行期间栈帧不会改变局部 变量表的大小空间。

栈中会存放基本数据类型、对象引用、常量。


3.本地方法栈

与虚拟机栈基本类似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务。


4.堆 

也叫做java 堆、GC堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,在JVM启动时创建。该内存区域存放了对象实例及数组(所有new的对象)。其大小通过-Xms(最小值)和-Xmx(最大值)参数设置,-Xms为JVM启动时申请的最小内存,-Xmx为JVM可申请的最大内存,对于运行系统,为避免在运行时频繁调整Heap的大小,通常-Xms与-Xmx的值设成一样。

由于现在收集器都是采用分代收集算法,堆被划分为新生代和老年代。新生代主要存储新创建的对象和尚未进入老年代的对象。老年代存储经过多次新生代GC(Minor
GC)任然存活的对象。

新生代:

 程序新创建的对象都是从新生代分配内存,新生代由Eden Space和两块相同大小的Survivor Space(通常又称S0和S1或From和To)构成,可通过-Xmn参数来指定新生代的大小,也可以通过-XX:SurvivorRation来调整Eden
Space及Survivor Space的大小。

老年代:

用于存放经过多次新生代GC任然存活的对象,例如缓存对象,新建的对象也有 可能直接进入老年代,主要有两种情况:①.大对象,可通过启动参数设置-XX:PretenureSizeThreshold=1024(单位为字节,默 认为0)来代表超过多大时就不在新生代分配,而是直接在老年代分配。②.大的数组对象,切数组中无引用外部对象。

老年代所占的内存大小为-Xmx对应的值减去-Xmn对应的值。


5.程序计数器 

它的作用是当前线程所执行的字节码的行号指示器,在虚拟机的模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、异常处理、线程恢复等基础功能都需要依赖计数器完成。

以上转载地址为: http://www.open-open.com/lib/view/open1348919888275.html 

JVM优化:
1、-Xms、-Xmx 堆内存大小
把Xms与Xmx两个值设成一样是最优的做法。有人说Xms为最小值,Xmx为最大值不是挺好的,这样设置还比较人性化,科学化。人性?科学?你个头啊。

大家想一下这样的场景:

一个系统随着并发数越来越高,它的内存使用情况逐步上升,上升到最高点不能上升了,开始回落,你们不要认为这个回落就是好事情,由其是大起大落,在内存回落时它付出的代价是CPU高速开始运转进行垃圾回收,此时严重的甚至会造成你的系统出现“卡壳”就是你在好好的操作,突然网页像死在那边一样几秒甚至十几秒时间,因为JVM正在进行垃圾回收。

因此一开始我们就把这两个设成一样,这个道理和jdbcconnection pool里的minpool size与maxpool size的需要设成一个数量是一样的原理。

2、-Xmn 堆内存中年轻代(新生代)大小

设置年轻代大小为512m。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。

3、-Xss 线程的堆栈大小
是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程
大约需要占用多少内存,可能会有多少线程同时运行等。一般不易设置超过1M,要不然容易出现out ofmemory。
4、-XX:+AggressiveOpts 
启用这个参数,则每当JDK版本升级时,你的JVM都会使用最新加入的优化技术(如果有的话)。
5、-XX:+UseBiasedLocking
启用一个优化了的线程锁,我们知道在我们的appserver,每个http请求就是一个线程,有的请求短有的请求长,就会有请求排队的现象,甚至还会出现线程阻塞,这个优化了的线程锁使得你的appserver内对线程处理自动进行最优调配。

6、-XX:PermSize=128M
-XX:MaxPermSize=256M
JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;

在数据量的很大的文件导出时,一定要把这两个值设置上,否则会出现内存溢出的错误。

由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

那么,如果是物理内存4GB,那么64分之一就是64MB,这就是PermSize默认值,也就是永生代内存初始大小;

四分之一是1024MB,这就是MaxPermSize默认大小。

7、-XX:+DisableExplicitGC在程序代码中不允许有显示的调用”System.gc()”。

8、-XX:+UseParNewGC对年轻代采用多线程并行回收,这样收得快。

9、-XX:+UseConcMarkSweepGC

即CMS gc,这一特性只有jdk1.5即后续版本才具有的功能,它使用的是gc估算触发和heap占用触发。

我们知道频频繁的GC会造面JVM的大起大落从而影响到系统的效率,因此使用了CMS GC后可以在GC次数增多的情况下,每次GC的响应时间却很短,比如说使用了CMS GC后经过jprofiler的观察,GC被触发次数非常多,而每次GC耗时仅为几毫秒。

10、-XX:MaxTenuringThreshold

设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概率。

这个值的设置是根据本地的jprofiler监控后得到的一个理想的值,不能一概而论原搬照抄。
11、 -XX:+CMSParallelRemarkEnabled在使用UseParNewGC 的情况下, 尽量减少
mark 的时间。

12、 -XX:+UseCMSCompactAtFullCollection 

在使用concurrent gc 的情况下, 防止 memoryfragmention, 对live object 进行整理, 使 memory 碎片减少。

13、-XX:LargePageSizeInBytes 指定 Java heap的分页页面大小

14、-XX:+UseFastAccessorMethods get,set 方法转成本地代码

15、-XX:+UseCMSInitiatingOccupancyOnly 指示只有在 oldgeneration 在使用了初始化的比例后concurrent collector 启动收集

16、-XX:CMSInitiatingOccupancyFraction=70

CMSInitiatingOccupancyFraction,这个参数设置有很大技巧,基本上满足(Xmx-Xmn)*(100- CMSInitiatingOccupancyFraction)/100>=Xmn就不会出现promotion failed。在我的应用中Xmx是6000,Xmn是512,那么Xmx-Xmn是5488兆,也就是年老代有5488 兆,CMSInitiatingOccupancyFraction=90说明年老代到90%满的时候开始执行对年老代的并发垃圾回收(CMS),这时还
剩10%的空间是5488*10%=548兆,所以即使Xmn(也就是年轻代共512兆)里所有对象都搬到年老代里,548兆的空间也足够了,所以只要满 足上面的公式,就不会出现垃圾回收时的promotion failed;

因此这个参数的设置必须与Xmn关联在一起。

17、-Djava.awt.headless=true

这个参数一般我们都是放在最后使用的,这全参数的作用是这样的,有时我们会在我们的J2EE工程中使用一些图表工具如:jfreechart,用于在web网页输出GIF/JPG等流,在winodws环境下,一般我们的app server在输出图形时不会碰到什么问题,但是在linux/unix环境下经常会碰到一个exception导致你在winodws开发环境下图片显示的好好可是在linux/unix下却显示不出来,因此加上这个参数以免避这样的情况出现。

上述这样的配置,基本上可以达到:

1、系统响应时间增快

2、JVM回收速度增快同时又不影响系统的响应率

3、JVM内存最大化利用

4、线程阻塞情况最小化

以上转载地址: http://blog.csdn.net/dengsilinming/article/details/8660211
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jvm