JVM内存区域详解(2)

JVM内存区域详解(1)

本地方法栈

​ 和虚拟机栈发挥的作用非常相似,区别是:虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。 在 HotSpot 虚拟机中和 Java 虚拟机栈合二为一。

​ 本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态连接、方法返回地址。

​ 方法执行完毕后相应的栈帧也会出栈并释放内存空间,也会出现 StackOverFlowErrerOutOfMemoryEror两种错误

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

​ Java 世界中 “几乎” 所有的对象都在堆中分配,但是,随着 JIT 编译器的罚站与逃逸分析技术的逐渐成熟,栈上分配,标量替换优化技术将会导致一些微妙的变化,所有的对象都分配在堆上也渐渐变得不那么绝对了。从 JDK 1.7 开始已经默认开启了逃逸分析,如果某些方法中的对象引用没有被返回或者未被外面使用(也就是未逃逸出去,那么可以直接在栈上分配内存)

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

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

  1. 新生代内存(Young Generation)
  2. 老生代(Old Generation)
  3. 永久代(Permanent Generation)

​ 下图所示的 Eden 区、两个 Survivor 区 S0 和 S1 都属于新生代,中间一层属于老年代,最下面一层属于永久代。

堆内存结构

JDK 8 版本以后 PermGen(永久代)已被 MetaSpace 元空间取代,元空间使用的本地内存。

​ 大部分情况,对象都会首先再 Eden 区分配内存,再一次新生代垃圾回收后,如果对象还存活,则会进入 S0 或者称作 from 区,并且对象的年龄还会加1,当它的年龄增长到一定程度(默认为15岁),就会被晋升到老年代中。对象晋升到老年代的阈值可以通过调整参数来实现

方法区

​ 方法区属于 JVM 运行时数据区域的一块逻辑区域,是各个线程共享的内存区域。

​ 《Java 虚拟机规范》 只是规定了有方法区的概念和它的作用,方法区到底要如何实现那就是各个虚拟机需要自己考虑的事情了。也就是说在不同的虚拟机实现上,方法区的实现是不同的。

​ 当虚拟机要使用一个类的时候,它需要读取并解析 Class 文件获取相关信息,再将信息存入方法区。方法区会存储已被虚拟机加载的 类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据。**

方法区和永久代以及元空间是什么关系呢? 方法区和永久代以及元空间的关系很像 Java 中接口和类的关系,类实现了接口,这里的类就可以看作是永久代和元空间,接口可以看作是方法区,也就是说永久代以及元空间是 HotSpot 虚拟机对虚拟机规范中方法区的两种实现方式。并且,永久代是 JDK 1.8 之前的方法区实现,JDK 1.8 及以后方法区的实现变成了元空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值