jvm学习笔记1--内存区域与内存溢出
-
运行时数据区域组成
1.1 程序计数器
-
当前线程所执行的字节码的行号指示器。字节码解释器工作时通过改变这个计数器的值来选取下一条需要执行的字节码指令。
-
为了线程切换后能恢复到正确的执行位置,每条线程都有一个独立的程序计数器,因此属于“线程私有”的内存。
-
执行 java方法,则记录的是虚拟机字节码的地址;如果执行的是 native方法,则值为空( Undefined)
-
异常:唯一一个在 Java虚拟机规范中没有规定任何 OutOfMemoryError情况的区域。
1.2 Java虚拟机栈( java virtual machine stacks)
-
Java虚拟机栈是线程私有的,生命周期与线程相同。
-
栈帧( stack frame):每个方法被执行的时候会创建一个栈帧,存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
-
局部变量表:存放编译器可知的各种基本数据类型、对象引用(根据不同的虚拟机实现,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄)、 returnAddress类型(指向一条字节码指令的地址)。局部变量表的空间在编译期是完全确定的,所以在编译期间完成分配,在运行期间不会再改变大小。
-
异常:
1) 如果线程请求的栈深度大于虚拟机所允许的深度,抛出 StackOverflowError
2) 如果虚拟机栈可以动态扩展,当扩展时无法申请到足够内存,则抛出 OutOfMemoryError异常。
1.3 本地方法栈
1.4 Java堆
1.5 方法区
1) 属于方法区的一部分。
2) 存放内容: Class文件中的常量池(存放编译期生成的各种字面量和符号引用);翻译出来的直接引用;运行期间产生的新的常量(譬如 String类的 intern()方法)
1.6 直接内存:
2. 对象访问
2.1 Object obj = new Object
-
Object obj:作为一个reference类型数据存储在栈帧的本地变量表中;
-
new Object():作为一个Object类型的实例数据存在在java堆中;同时,还必须包含能找到Object类型数据(如对象类型、父类、实现的接口、方法等)的地址信息;
-
Object类型数据(如对象类型、父类、实现的接口、方法等)存储在方法区中;
2.2 两种访问对象的方式:句柄、直接指针
Java堆中会划分出一块内存来作为句柄池;栈帧中存储的reference值就是对象的句柄地址;句柄中包含了对象实例数据和类型数据各自的具体地址信息
优点:对象被移动时,只需要改变句柄中的实例数据指针,而reference本身不需要被修改。
Java堆对象的布局必须考虑如何放置类型数据的相关信息;栈帧中存储的reference值就是对象地址。
优点:速度更快,节省了一次指针定位的时间开销。Sun HotSpot使用该方式。
3. 内存溢出
3.1 Java堆溢出
1)通过内存映像分析工具(如Eclipse Memory Analyzer)对dump出来的堆转储快照进行分析,确认是内存泄漏还是内存溢出
2) 如果是内存泄漏,则查看泄漏对象到GC Roots的引用链,得知泄漏对象通过怎样的路径与GC Roots相关联导致无法回收。
3)如果是内存溢出(即对象确实都还必须存活着),则检查堆参数(-Xmx与-Xms)与机器物理内存对比看是否可以调大;从代码上检查是否存在某些对象生命周期过长的情况,尝试优化减少程序运行期的内存消耗。
3.2 虚拟机栈溢出
1)StackOverflowError
Exception in thread “main” java.lang.StackOverflowError
说明:单线程情况下,不管是由于栈帧太大,还是由于虚拟机栈容量太小,当内存无法分配的时候,都抛出StackOverflowError
2)OutOfMemoryError
Exception in thread “main” java.lang.OutOfMemoryError:unable to create new native thread
多线程情况下,通过不断地建立线程的方式可以产生该异常,而且,为每个线程的栈分配的内存越大,越容易产生该异常。
1) StackOverflowError
有错误堆栈可以阅读,容易找到问题所在。而且,如果使用虚拟机默认参数,栈深度对于正常的方法调用是完全够用的。
2) OutOfMemoryError
由于虚拟机提供了参数来控制Java堆和方法区这两部分内存的最大值,而程序计数器消耗的内存很小可以忽略掉,因此用本机内存扣除掉这两部分内存后,剩下的内存就由虚拟机栈和本地方法栈瓜分了。所以对于建立多个线程导致的内存溢出,有两个措施解决:
2.1 减少最大堆内存
2.2 减少栈容量(是为了能够创建更多的线程)
3.3 运行时常量池溢出
-
Vm args: -XX:PermSize=10M -XX:MaxPermSize=10M
-
可能原因:运行时产生了大量的新的常量(譬如String类的intern()方法)
-
异常堆栈信息: Exception in thread “main” java.lang.OutOfMemoryError:PermGen space
3.4 方法区溢出
-
Vm args: -XX:PermSize=10M -XX:MaxPermSize=10M
-
可能原因:运行时产生了大量的类,导致在方法区存储了大量的类型数据信息(譬如CGLIB动态生成子类、动态产生JSP、OSGI应用(即使是同一个类文件,不同的classloader也会视为不同的类))
-
异常堆栈信息:Exception in thread “main” java.lang.OutOfMemoryError:PermGen space
3.5 本机直接内存溢出
注:本笔记主要参考:深入理解Java虚拟机--Jvm高级特性与最佳实践一书及网络资料
分享到:
相关推荐
**JVM学习笔记(Java虚拟机)** Java虚拟机(JVM)是Java语言的核心组成部分,它是Java程序运行的平台,负责解释和执行字节码。深入理解JVM对于优化Java应用程序性能至关重要。本笔记将从以下几个方面详细介绍JVM:...
在JVM的学习中,理解其内存模型、垃圾收集算法以及类加载机制至关重要。 1. **JVM内存模型** - **方法区**:也称为“永久代”,存储虚拟机加载的类信息、常量、静态变量等,是线程共享的区域。在Java 8之后,这...
虚拟机学习笔记 Java 虚拟机(JVM)是 Java 语言的 runtime 环境,负责加载、验证、执行 Java 字节码。以下是 JVM 相关知识点的总结。 1. 运行时数据区域 JVM 的运行时数据区域主要包括: * 堆(Heap):...
"jvm视频及笔记"这个资源显然是一份全面学习JVM的材料,结合了视频教程和书面笔记,帮助学习者深入理解JVM的工作原理及其在实际开发中的应用。 JVM的学习可以从以下几个重要的知识点开始: 1. **JVM架构**:JVM...
3. **内存区域**: - 程序计数器:记录当前线程执行的字节码指令地址。 - Java虚拟机栈:每个方法对应一个栈帧,存储局部变量表、操作数栈、动态链接和方法出口等信息。 - 本地方法栈:与JVM栈类似,但服务于Java...
《JVM学习笔记》 Java虚拟机(JVM)是Java平台的核心组成部分,它负责运行所有的Java应用程序。这篇笔记将深入探讨JVM的工作原理、内存管理、类加载机制以及优化策略,帮助读者全面理解JVM并提升Java程序的性能。 ...
1. **合理设置堆大小**:根据应用的特性和预期的负载,适当调整堆大小以避免内存溢出或频繁的垃圾收集。 2. **选择合适的垃圾收集器**:不同的GC算法适用于不同的应用场景,选择能平衡吞吐量和响应时间的收集器。 ...
此外,JVM还有一块特殊的内存区域——方法区,用于存储类的信息,如类的静态变量和常量池等。理解这些内存区域的划分和工作方式,对于优化内存使用和避免内存泄漏至关重要。 三、类加载机制 JVM的类加载机制包括...
### 深入解析 JVM 内存区域 #### 一、Java内存区域概述 Java虚拟机(JVM)作为Java程序的运行环境,负责管理和分配内存资源。为了更好地理解和掌握JVM内部的工作机制,本篇文章将重点介绍JVM中的几个关键内存区域:...
### JAVA学习经典笔记知识点概述 #### 一、Java与C++的区别 1. **内存管理:** Java自动管理内存,通过垃圾回收机制自动清理不再使用的对象;而C++需要程序员手动管理内存,容易出现内存泄漏等问题。 2. **平台...
理解这些内存区域的工作原理对于识别和解决内存泄漏、性能瓶颈以及理解垃圾收集机制至关重要。例如,新生代的对象如果频繁存活,可能会导致大量对象晋升到老年代,进而可能导致老年代过早耗尽,引发Full GC。通过...
这份“JVM的学习笔记PDF版”应该包含了关于JVM的详细信息,帮助学习者深入理解这个复杂的系统。JVM允许Java代码跨平台运行,通过解释器、类加载器、垃圾收集器等组件实现“一次编写,到处运行”的理念。 1. **JVM...
本学习笔记旨在全面解析JVM的工作原理,涵盖内存管理、类加载机制、垃圾收集、性能调优等多个关键领域,帮助读者从基础到深入地掌握JVM。 1. **JVM结构与运行过程** - JVM由类装载器、运行时数据区、执行引擎、...
4. 内存溢出:了解各种内存溢出异常,如OOM(Out Of Memory),并针对性地解决。 六、JVM监控与诊断工具 JDK提供了一些工具帮助开发者监控和诊断JVM,如JConsole、VisualVM和JProfiler,它们可以显示JVM内存状态、...
这份"Java学习笔记_内存管理.pdf"很可能是详细解析了Java如何进行内存分配、垃圾回收以及内存泄漏等相关概念。下面,我们将深入探讨Java内存管理的一些核心知识点。 1. **Java内存模型**: - **堆内存(Heap)**:...
值得注意的是,程序计数器是JVM规范中唯一一个不会出现内存溢出的区域。 虚拟机栈是每个线程在运行时所需的内存空间,它由多个栈帧组成。每个栈帧对应一个Java方法的调用,包括参数、局部变量和返回地址等。当一个...
本思维导图及学习笔记将深入探讨JVM的工作原理、内存模型、垃圾收集机制以及性能优化等方面,帮助你全面理解这个至关重要的技术。 一、JVM概述 Java虚拟机是Java平台的一部分,它负责解析字节码并执行Java程序。JVM...
《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)周志明.pdf》这本书是Java开发者深入理解JVM(Java Virtual ...而“新建文本文档.txt”可能包含个人笔记或者临时记录,对于JVM学习的具体内容没有直接关系。
了解这些内存区域的分配与回收机制,有助于我们理解和解决内存溢出、内存泄漏等问题。 其次,JVM的类加载机制也十分关键。类加载过程包括加载、验证、准备、解析和初始化五个阶段。每个阶段都有其特定的任务,比如...
《JVM与性能优化:深度探索思维导图与学习笔记》 在Java世界里,JVM(Java Virtual Machine)是程序执行的核心,它负责解析字节码并将其转化为机器指令,使得Java具备“一次编写,到处运行”的特性。而性能优化则是...