您的位置:首页 > 其它

JVM配置参数详解

2018-03-31 22:19 309 查看
一、堆参数设置

-XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志

-XX:+UseSerialGC 配置串行回收器

-XX:+PrintGCDetails 可以查看详细信息,包括各个区的情况

-Xms:设置Java程序启动时初始化堆大小

-Xmx:设置Java程序能获得最大的堆大小

-Xmx20m -Xms5m -XX:+PrintCommandLineFlags:可以将隐式或者显示传给虚拟机的参数输出

在实际工作中,我们可以直接将初始的堆大小与最大堆大小设置相等,这样的好处是可以减少程序运行时的垃圾回收次数,从而提高性能。

配置运行时参数:-XX:+PrintGC -Xms5m -Xmx20m -XX:+UseSerialGC -XX:+PrintGCDetails -XX:+PrintCommandLineFlags

运行一下Demo:

?
21
程序输出:

?
在此程序输出的结果中,可以看到堆的详细信息,比如可以看到它的新生代信息、老年代信息、永久区信息等。

二、新生代参数配置

-Xmn:可以设置新生代的大小,设置一个比较大的新生代会减少老年代的大小,这个参数对系统性能以及GC行为有很大的影响,新生代大小一般会设置整个堆空间的1/3到1/4左右。

-XX:SurvivorRatio:用来设置新生代中eden空间和from/to空间的比例。含义:-XX:SurvivorRatio=eden/from=eden/to。

不同的堆分布情况,对系统执行会产生一定的影响,在实际工作中,应该根据系统的特点做出合理的配置,基本策略:尽可能将对象预留在新生代,减少老年代的GC次数。

除了可以设置新生代的绝对大小(-Xmn),还可以使用(-XX:NewRatio)设置新生代和老年代的比例:-XX:NewRatio=老年代/新生代。

配置运行时参数:

-Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails

-XX:+UseSerialGC

运行Demo:

?
package
com.ietree.basicskill.jvm;
程序运行结果:

?
可以看到,在新生代种,eden区域内存是from和to区域内存的2倍。即-XX:SurvivorRatio=2参数起了作用。

配置运行参数:-Xms20m -Xmx20m -XX:NewRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC

运行以上Demo可以得到一下输出:

?
发现tenured generation老年代的内存是new generation 新生代内存的2倍。

三、堆溢出参数配置

在Java程序的运行过程中,如果对空间不足,则会抛出内存溢出的错误(Out Of Memory)OOM,一旦这类问题发生在生产环境,则可能引起严重的业务中断,Java虚拟机提供了-XX:+HeapDumpOnOutOfMemoryError,

使用该参数可以在内存溢出时导出整个堆信息,与之配合使用的还有参数-XX:HeapDumpPath,可以设置导出堆的存放路径。

内存分析工具:Memory Analyzer

配置运行时参数-Xms1m -Xmx1m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/Demo3.dump

运行Demo:

?
程序输出的结果:

?
在d:/Demo3.dump可以找到对应的文件,使用内存分析工具(Memory analyzer)打开:

如图:





四、栈参数配置

Java虚拟机提供了参数-Xss来指定线程的最大栈空间,整个参数也直接决定了函数可调用的最大深度。

配置运行时参数:-Xss1m

运行Demo:

?
程序输出:

?
五、方法区参数配置

和Java堆一样,方法区是一块所有线程共享的内存区域,它用于保存系统的类信息,方法区(永久区)可以保存多少信息可以对其进行配置,在默认情况下,-XX:MaxPermSize为64M,

如果系统运行时生产大量的类,就需要设置一个相对合适的方法区,以免出现永久区内存溢出的问题。

-XX:PermSize=64M -XX:MaxPermSize=64M

六、直接内存参数配置

直接内存也是Java程序中非常重要的组成部分,特别是广泛用在NIO中,直接内存跳过了Java堆,使用Java程序可以直接访问原生堆空间,因此在一定程度上加快了内存空间的访问速度。

但是说直接内存一定就可以提高内存访问速度也不见得,具体情况具体分析。

相关配置参数:-XX:MaxDirectMemorySize,如果不设置,默认值为最大堆空间,即-Xmx。直接内存使用达到上限时,就会触发垃圾回收,如果不能有效的释放空间,就会引起系统的OOM。

七、对象进入老年代的参数配置

一般而言,对象首次创建会被放置在新生代的eden区,如果没有GC介入,则对象不会离开eden区,那么eden区的对象如何进入老年代呢?

通常情况下,只要对象的年龄达到一定的大小,就会自动离开年轻代进入老年代,对象年龄是由对象经历数次GC决定的,在新生代每次GC之后如果对象没有被回收,则年龄加1。

虚拟机提供了一个参数来控制新生代对象的最大年龄,当超过这个年龄范围就会晋升老年代。

-XX:MaxTenuringThreshold,默认情况下为15

配置运行时参数:-Xmx64M -Xms64M -XX:+PrintGCDetails

运行Demo:

?
程序输出:

?
结论:对象首次创建会被放置在新生代的eden区,因此输出结果中from和to区都为0%。

根据设置MaxTenuringThreshold参数,可以指定新生代对象经过多少次回收后进入老年代。另外,大对象新生代eden区无法装入时,也会直接进入老年代。

JVM里有个参数可以设置对象的大小超过在指定的大小之后,直接晋升老年代。

-XX:PretenureSizeThreshold=15

参数:-Xmx1024M -Xms1024M -XX:+UseSerialGC -XX:MaxTenuringThreshold=15 -XX:+PrintGCDetails

使用PretenureSizeThreshold可以进行指定进入老年代的对象大小,但是要注意TLAB区域优先分配空间。虚拟机对于体积不大的对象 会优先把数据分配到TLAB区域中,因此就失去了在老年代分配的机会.

参数:-Xmx30M -Xms30M -XX:+UseSerialGC -XX:+PrintGCDetails -XX:PretenureSizeThreshold=1000 -XX:-UseTLAB

八、TLAB参数配置

TLAB全称是Thread Local Allocation Buffer即线程本地分配缓存,从名字上看是一个线程专用的内存分配区域,是为了加速对象分配对象而生的。

每一个线程都会产生一个TLAB,该线程独享的工作区域,Java虚拟机使用这种TLAB区来避免多线程冲突问题,提高了对象分配的效率。

TLAB空间一般不会太大,当大对象无法在TLAB分配时,则会直接分配到堆上。

-XX:+UseTLAB使用TLAB

-XX:+TLABSize设置TLAB大小

-XX:TLABRefillWasteFraction设置维护进入TLAB空间的单个对象大小,它是一个比例值,默认为64,即如果对象大于整个空间的1/64,则在堆创建对象。

-XX:+PrintTLAB查看TLAB信息

-XX:ResizeTLAB自调整TLABRefillWasteFraction阈值。

参数:-XX:+UseTLAB -XX:+PrintTLAB -XX:+PrintGC -XX:TLABSize=102400 -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=100 -XX:-DoEscapeAnalysis -server
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: