java 内存模型

一、Java内存模型

JVM主要管理两种类型内存:堆和非堆,堆内存(Heap Memory)是在 Java 虚拟机启动时创建,非堆内存(Non-heap Memory)是在JVM堆之外的内存。
简单来说,堆是Java代码可及的内存,留给开发人员使用的;非堆是JVM留给自己用的,包含方法区、JVM内部处理或优化所需的内存(如 JIT Compiler,Just-in-time Compiler,即时编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码。
JVM 内存包含如下几个部分:
堆内存(Heap Memory): 存放Java对象
非堆内存(Non-Heap Memory): 存放类加载信息和其它meta-data
其它(Other): 存放JVM 自身代码等

在JVM启动时,就已经保留了固定的内存空间给Heap内存,这部分内存并不一定都会被JVM使用,但是可以确定的是这部分保留的内存不会被其他进程使用,这部分内存大小由-Xmx 参数指定。而另一部分内存在JVM启动时就分配给JVM,作为JVM的初始Heap内存使用,这部分内存是由 -Xms 参数指定

默认空余堆内存小于40%时,JVM 就会增大堆直到-Xmx 的最大限制,可以由 -XX:MinHeapFreeRatio 指定。
默认空余堆内存大于70%时,JVM 会减少堆直到-Xms的最小限制,可以由 -XX:MaxHeapFreeRatio 指定。可以通过 -XX:MaxPermSize

二、Java内存分配
Java的内存管理实际上就是变量和对象的管理,其中包括对象的分配和释放。

可以看出:
  堆内存 = 年轻代 + 年老代 + 永久代
  年轻代 = Eden区 + 两个Survivor区(From和To)

JVM内存申请过程如下:
JVM 会试图为相关Java对象在Eden中初始化一块内存区域
当Eden空间足够时,内存申请结束;否则到下一步
JVM 试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区
Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区
当OLD区空间不够时,JVM 会在OLD区进行完全的垃圾收集(0级)
完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory”错误

原文地址:https://www.cnblogs.com/sprinng/p/6612642.html