了解 Java 内存模型
对于 Java 开发人员来说,了解 Java 内存模型是必不可少的,他们需要开发,部署,监视,测试和调整 Java 应用程序的性能。
Java Memory Model
运行资源密集型Java程序时,您必须使用以下某些JVM内存配置。
-XmsSetting - 初始化堆大小
-XmxSetting - 最大堆大小
-XX:NewSizeSetting - 新一代堆大小
-XX:MaxNewSizeSetting - 最大新生代堆大小
-XX:MaxPermGenSetting - 永久代的最大大小
-XX:SurvivorRatioSetting - 新的堆大小比率(例如,如果Young Gen大小为10m,并且内存开关为–XX:SurvivorRatio = 2,则将为Eden空间保留5m,为两个Survivor空间分别保留2.5m,默认值为8)
-XX:NewRatio - 提供新旧大小的比率(默认值= 2)
那么 JVM 如何驻留在内存中?就像任何其他软件一样,JVM占用主机OS内存上的可用空间。
但是,在 JVM 内部,存在单独的内存空间(堆,非堆,缓存),以便存储运行时数据和编译后的代码。
1 堆内4存
堆分为两部分 - 年轻一代和老年一代
JVM 启动时分配堆(初始大小:-Xms)
应用程序运行时堆大小增加/减少
最大大小:-Xmx
1.1 新生代(Young Gen)
保留用于包含新分配的对象
Young Gen 包括三个部分 - Eden Memory 和两个 Survivor Memory 空间(S0,S1)
大多数新创建的对象进入 Eden 空间。
当 Eden 空间中装满对象时,将执行次要 GC(又称 Young Collection),并将所有幸存者对象移至其中一个幸存者空间。
次要 GC 还可以检查幸存者对象并将其移至其他幸存者空间。因此,一个幸存者空间始终是空的。
在许多次 GC 循环后仍然存在的对象将移至老年代存储空间。通常,可以通过设置年轻一代对象的年龄阈值,然后才有资格晋升为老年代对象。
1.2 老年代(Old Generation)
这是为包含可能在多轮次要 GC 中存活下来的长寿命对象而保留的
当老年代空间已满时,将执行主要 GC(又称 Old Collection)(通常需要更长的时间)
2 非堆内存(Non-Heap Memory)
包括永久代( Permanent Generation 从 Java 8 开始由元空间 - Metaspace 替换)
Perm Gen 存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码以及内部字符串
可以使用 -XX:PermSize 和 -XX:MaxPermSize 更改其大小
3 缓存内存
包括代码缓存.
存储由 JIT 编译器生成的已编译代码(即原生代码 Machine Code),JVM 内部结构,已加载的探查器代理代码和数据等。
当代码缓存超过阈值时,它将被刷新(并且 GC 不会重新定位对象)。
4 栈
这是一个很好的示例(来自 baeldung.com),说明了 Stack 和 Heap 如何有助于执行一个简单的程序(使用代码检查堆栈顺序)
注:仔细阅读供应商文档,以了解适用于您的 JVM 版本的工具。
5 常见内存相关问题
java.lang.StackOverFlowError - 栈内存已满
java.lang.OutOfMemoryError: Java heap space - 堆内存已满
java.lang.OutOfMemoryError: GC Overhead limit exceeded - GC已达到其开销限制
java.lang.OutOfMemoryError: Permgen space - 永久代空间已满
java.lang.OutOfMemoryError: Metaspace - 元空间已满(从 JDK8 开始)
java.lang.OutOfMemoryError: Unable to create new native thread - JVM 本机代码无法再从底层操作系统创建新的本机线程,因为已经创建了这么多线程,并且它们消耗了 JVM 的所有可用内存
java.lang.OutOfMemoryError: request size bytes for reason - 交换内存空间已被应用程序完全消耗
java.lang.OutOfMemoryError: Requested array size exceeds VM limit - 我们的应用程序使用的数组大小大于基础平台允许的大小
但是,这些输出只能指示 JVM 的影响,而不能指示实际的错误。实际错误及其根本原因可能会出现在代码中的某处(例如内存泄漏,GC 问题,同步问题),资源分配甚至硬件设置。不建议您简单地增加受影响的资源来解决问题。需要监视资源使用情况,分析每个类别,进行堆转储,检查和调试、优化代码等。如果行不通再加资源。
References
版权声明: 本文为 InfoQ 作者【陈皮】的原创文章。
原文链接:【http://xie.infoq.cn/article/e1ae467a0bd2da2583c077f3b】。文章转载请联系作者。
评论