java old区域_Java 内存区域详解

Java 虚拟机所管理的内存中最大的一块, Java 堆是所有线程共享的一块内存区域, 在虚拟机启动时创建. 此内存区域的唯一目的就是存放对象实例, 几乎所有的对象实例以及数组都在这里分配内存.

Java 堆是垃圾收集器管理的主要区域, 因此也被称作GC 堆(Garbage Collected Heap).从垃圾回收的角度, 由于现在收集器基本都采用分代垃圾收集算法, 所以 Java 堆还可以细分为: 新生代和老年代: 再细致一点有: Eden 空间、From Survivor、To Survivor 空间等. 进一步划分的目的是更好地回收内存, 或者更快地分配内存.

在 JDK 7 版本及JDK 7 版本之前, 堆内存被通常被分为下面三部分:

新生代内存(Young Generation)

老生代(Old Generation)

永生代(Permanent Generation)

40798ccf395093420ea669d008dbb570.png

JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了), 取而代之是元空间, 元空间使用的是直接内存.

30fb974d17f80eae669e15f8bffc293a.png

上图所示的 Eden 区、两个 Survivor 区都属于新生代(为了区分, 这两个 Survivor 区域按照顺序被命名为 from 和 to), 中间一层属于老年代.

大部分情况, 对象都会首先在 Eden 区域分配, 在一次新生代垃圾回收后, 如果对象还存活, 则会进入 s0 或者 s1, 并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1), 当它的年龄增加到一定程度(默认为 15 岁), 就会被晋升到老年代中. 对象晋升到老年代的年龄阈值, 可以通过参数 -XX:MaxTenuringThreshold 来设置.

修正(issue552): "Hotspot遍历所有对象时, 按照年龄从小到大对其所占用的大小进行累积, 当累积的某个年龄大小超过了survivor区的一半时, 取这个年龄和MaxTenuringThreshold中更小的一个值, 作为新的晋升年龄阈值".

动态年龄计算的代码如下

uintageTable::compute_tenuring_threshold(size_t survivor_capacity) {

//survivor_capacity是survivor空间的大小

size_t desired_survivor_size = (size_t)((((double)survivor_capacity)*TargetSurvivorRatio)/100);

size_t total = 0;

uintage = 1;

while (age

total +=sizes[age];//sizes数组是每个年龄段对象大小

if (total >desired_survivor_size) break;

age++;

}

uintresult =age

...

}

堆这里最容易出现的就是 OutOfMemoryError 错误, 并且出现这种错误之后的表现形式还会有几种, 比如:

OutOfMemoryError: GC Overhead Limit Exceeded : 当JVM花太多时间执行垃圾回收并且只能回收很少的堆空间时, 就会发生此错误.

java.lang.OutOfMemoryError: Java heap space :假如在创建新的对象时, 堆内存中的空间不足以存放新创建的对象, 就会引发java.lang.OutOfMemoryError: Java heap space 错误. (和本机物理内存无关, 和你配置的内存大小有关!)

......

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值