首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

java 内存模型-02-数据结构(4)

java 内存模型-02-数据结构(4)

方法区

方法区主要存放的是已被虚拟机加载的类信息、常量、静态变量、编译器编译后的代码等数据。

由于永久代存储的数据生命周期非常长,GC在这个区域消耗时间长且回收效果差,所以方法区GC频率很低。

不同回收策略对方法区的处理:

    G1:只有在Full GC的时候方法区才会被清理。当方法区需要空间时,该空间无法扩展又没有内存空间可以回收,就会抛出OutOfMemory异常。

    CMS:可以使用 -XX:+CMSClassUnloadingEnabled 参数,在CMS并行收集阶段回收 PermGen 空间。

运行时常量池

运行时常量池也是方法区的一部分,用于存放编译器生成的各种字面量和符号引用。

运行时常量池除了编译期产生的Class文件的常量池,还可以在运行期间,将新的常量加入常量池,比较常见的是String类的intern()方法。

    字面量:与Java语言层面的常量概念相近,包含文本字符串、声明为final的常量值等。

    符号引用:编译语言层面的概念,包括以下3类:

    类和接口的全限定名

    字段的名称和描述符

    方法的名称和描述符

但是该区域不会抛出 OutOfMemoryError 异常。
直接内存

直接内存不是虚拟机运行时内存的一部分,该空间划分在虚拟机外。

不过由于直接内存的性能比较好,所以有的工作需要使用直接内存来提高性能。

直接内存会受到物理机剩余可用内存、处理器寻址空间的限制。

可以通过NIO和NIO.2来申请直接内存。如果虚拟机堆内存分配太大,可能会导致直接内存空间不足而出现运行时异常。
变化
元数据区 Metaspace

由于 PermGen 内存管理的效果远没有达到预期,所以JCP已经着手去除PermGen的工作。在JDK7中,字符串常量已经从永久代移除。

现今 JDK8 中 PermGen 已经被彻底移除,取而代之的是metaspace数据区,使用native内存,申请和释放由虚拟机负责管理。

在JDK8下,旧的参数 -XXermSize 和 -XX:MaxPermSize 会被忽略并显示警告。

新的Metaspace通过参数 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 设定。
G1 内存模型

从JDK7开始引入的G1回收机制,到JDK8时G1已经基本稳定。

G1应该是唯一一个能完成新生代到老年代所有管理的GC技术。

之前的技术如上一节图中CMS和PerNew需要互相配合才能完成完整回收工作。

基于G1回收的特殊性,G1的内存模型和上面介绍的内存模型是有差别的。也就是说,上面的内存模型对G1是无效的。

由于现在还没有太多的资料可以参考G1的内存模型。

如果有需要深入了解,请阅读OpenJDK中HotSpot JVM关于G1的源码。

如果没有特殊要求,现时CMS和PerNew已经很好适应大部分应用场景。毕竟CMS用了多年,出现问题也容易找到解决方法。
返回列表