本文研究了java8的内存模型,此外还包括内存相关参数配置.
新生代/老生代/永久代/元空间/GC/收集器这些概念你想了解吗?
根据java8的JVM规范,JVM内存分为:
1. VM Stacks(虚拟机栈): 每个线程都有一个私有的栈
* 栈帧: 每个方法都有个栈帧,里面存放了局部变量表,操作数栈,方法出口等信息
2. Native Method Stack(本地方法栈): 与虚拟机栈类似,区别是虚拟机栈执行java方法,本地方法栈执行native方法
3. PC Register(PC寄存器/程序计数器): 每个线程都有一个PC寄存器,指示当前线程执行到哪里了
如果当前线程执行的是java方法,则寄存器中保存当前指令地址;
如果当前线程执行的是native方法,则寄存器中保存的值为空.
4. Heap(堆): 所有线程共享,所有对象和数组都在堆上分配,堆可以通过GC进行回收.
5. Method Area(方法区/非堆): 所有线程共享,主要存储类的信息,常量池,变量池,静态变量,方法代码等.
Heap(堆)内存池模型为:
* Young Generation(新生代/年轻代)
* Eden Space(伊甸园区): 新对象会放到这个区,GC后未回收的进入Survivor Space(幸存者区)
* Survivor Space(幸存者区)
* From Survivor
* To Survivor: 大小与From Survivor相同
* Old Generation(老生代/老年代)
PermGen(永久代)与Metaspace(元空间)
PermGen(永久代)是HotSpot对JVM规范中的Method Area(方法区)的具体实现.
对于动态生成类的情况比较容易出现永久代的溢出,如jsp页面比较多时.
java8中移除了PermGen(永久代),使用Metaspace(元空间)代替.
最大区别在于: `元空间使用本地内存,而不在虚拟机中`.
默认情况下,Metaspace(元空间)的上限没有限制,只受制于本地内存大小.
使用Metaspace(元空间)的优点:
1. 字符串存在永久代中,容易出现性能问题和内存溢出.
2. 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出.
3. 永久代会为GC带来不必要的复杂度,并且回收效率偏低.
以下只介绍一些常用的参数
堆参数
* -Xms/-Xmx: 初始堆大小(默认为物理内存的1/64)/最大堆大小(默认为物理内存的1/4)
* -Xss: 每个线程堆栈大小.jdk5以后线程堆栈大小为1M,如果栈不是很深,一般128k够用了,大的应用建议256k(这个选项对性能影响比较大,需要严格测试)
* -XX:MinHeapFreeRatio/-XX:MaxHeapFreeRatio: 堆空间的最小空闲比例(默认40),空闲的小于这个值就会进行扩展/最大空闲比例(默认70),空闲的超过这个值时就释放掉部分
在xmx与xms大小相同时,此配置将无效果.
* -XX:SurvivorRatio: 伊甸园与(一个)幸存者大小的比值(而幸存者有两个: From与To,并且永远一样大)
比如5,表示伊甸园与From幸存者比例为5:1,与To幸存者比例也是5:1,即伊甸园占总的比例为5/(5+1+1)=5/7
如果比例太小,即伊甸园太小,那么新生代GC次数将增加;如果比例太大,那么大部分幸存对象会过早转移到老生代.
* -XX:PretenureSizeThreshold: 大对象直接进入老生代的阀值,单位Byte
年龄
* -XX:TargetSurvivorRatio: 幸存者区目标使用率,默认50(大致表示达到50%使用率时对象会向老生代压缩)
* -XX:MaxTenuringThreshold: 晋升年龄阀值,默认15(即对象在15次Minor GC后会进入老生代)
新生代/老生代大小
关于新生代/老生代大小设置,按优先级顺序(从高到低)有以下几种参数:
1. -XX:NewSize 初始新生代大小/-XX:MaxNewSize 最大新生代大小
2. -Xmn: 新生代大小(相当于初始值与最大值相同)
3. -XX:NewRatio: 老生代与新生代的比例(如4表示老生代:新生代=4:1=4,即新生代占整个堆的1/5)
此值对系统性能影响较大,官方推荐新生代为堆大小的`3/8`(即老生代占5/8)
元空间
(一般不需要设置)
* -XX:MetaspaceSize: 初始空间
* -XX:MaxMetaspaceSize: 最大空间
* -XX:MinMetaspaceFreeRatio: GC后,最小的空闲空间百分比,如40,如果空闲空间小于这个值,就会增加内存(值设太小可能会影响后面类加载效率,设太大会浪费内存)
* -XX:MaxMetaspaceFreeRatio: GC后,最大的空间空间百分比,如70,如果空闲空间大于这个值,就会释放部分
* -XX:+PrintGC/-XX:+PrintGCDetails: 输出GC日志/详细日志
* -XX:+PrintGCTimeStamps: 输出GC的时间戳(单位秒,从JVM启动开始计算)
* -XX:+PrintGCDateStamps: 输出GC的时间点(日期的格式)
* -XX:+PrintHeapAtGC: 在GC前后打印堆信息
* -Xloggc:<文件名>: GC日志文件输出路径
* -XX:+UseSerialGC: 使用 Serial(新生代) + SerialOld(老生代)
* -XX:+UseParNewGC: 使用 ParallelNew(新生代) + SerialOld(老生代)
* -XX:+UseParallelGC: 使用 ParallelScavenge(新生代) + SerialOld(老生代)
* -XX:+UseParallelOldGC: 如果这个参数一起开启,则会使用 ParallelScavenge(新生代) + ParallelOld(老生代),这样老生代效率也更好
* -XX:+UseAdaptiveSizePolicy: 开启自适应调节策略,这个参数打开后,新生代大小,伊甸园与幸存者区比例,晋升年龄阀值等就不需要手动指定了(默认开启)
* XX:+UseConcMarkSweepGC: 使用 ParallelNew(新生代) + CMS(老生代) + SerialOld(老生代备用,CMS失败时启用)
而在生产环境上,一般使用的是以下几种组合:
* -XX:+UseSerialGC
* -XX:+UseParallelGC -XX:+UseParallelOldGC
* -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
* -XX:+UseG1GC
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/sjkxydsj/54860.html