java eden space_想理解Java内存模型?这里有一看就懂的Java内存模型总结

本文研究了java8的内存模型,此外还包括内存相关参数配置.

新生代/老生代/永久代/元空间/GC/收集器这些概念你想了解吗?

63d5d86b21fc6ca272a037de1fe9cbb5.png

JVM内存模型

根据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(老生代/老年代)0313b4b1e699ba42cee195755fa4dda7.png

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,如果空闲空间大于这个值,就会释放部分

GC

*-XX:+PrintGC/-XX:+PrintGCDetails: 输出GC日志/详细日志

* -XX:+PrintGCTimeStamps: 输出GC的时间戳(单位秒,从JVM启动开始计算)

* -XX:+PrintGCDateStamps: 输出GC的时间点(日期的格式)

* -XX:+PrintHeapAtGC: 在GC前后打印堆信息

* -Xloggc:: GC日志文件输出路径

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值