java与C++之间有一堵内存动态分配和垃圾收集技术所围成的高墙,墙外的人想进去,墙里的人却想出来。 --摘自《深入理解Java虚拟机》
C++认为内存很重要,所以一定要给人管理,java同样认为内存很重要,所以一定不能给人管理。 --忘了哪看来的
计算机的世界中,所有问题都可以通过引入一个中间角色来解决(jvm就是典型)。
a.为什么做内存划分?
java进程下的占用的一块内存,划分成5个逻辑空间,对每一块做特定的处理数据方式和内存管理方式,会大大提升内存效率。
b.划分情况
上边提到的5个内存空间分别为
栈、堆、方法区、程序计数器、本地方法栈 (注:此逻辑为划分规范,即各个JVM虚拟机(eg : HotSpot和此规范可理解为接口和实现类的关系)实现需参考此规范)
堆:所有几乎所有new出来的东西,GC的主要作案地点非常血腥,然而真实情况是随着新技术方案的出现未必所有new的对象都会在堆申请内存,后面展开讨论。
-
Exception in thread “main”: java.lang.OutOfMemoryError: Java heap space
(对象不能分配在堆中,可能程序出现死循环)
栈:存放的是一个个方法对应的栈桢,而各个栈桢存的是局部变量表、操作数栈、动态链接、方法出口,方法调用链结束对应栈桢压栈和弹栈,线程结束当前栈销毁。
此区域会出现两种OOM情况StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度;OutOfMemoryError:当扩展时无法申请到足够的内存(当前大部分的虚拟机 都会动态扩展,然而单线程情况下只能实验出StackOverflowError异常)
Exception in thread "main" java.lang.StackOverflowError
方法区:虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等
JDK8后此区域的hotspot实现由永久带换为元空间
-
Exception in thread “main”: java.lang.OutOfMemoryError: PermGen space
(类或者方法不能被加载到老年代。它可能出现在一个程序加载很多类的时候,比如引用了很多第三方的库、或者使用了类似CGlib技术动态生成大量字节码文件)
程序计数器:指向下一条指令的地址,每个线程有一个(唯一无OOM情况的区域)
本地方法栈:native方法,本地实现,当调用native方法时,程序计数器值为undefined
Exception in thread “main”: java.lang.OutOfMemoryError: unable to create new native thread
(没有空间给新的线程使用,可看情况适当调小栈大小或堆大小等方法换取更多有效线程并发)
还有几种OOM异常不再逐个列举,重点只需对异常产生区域和原因的理解,来快速排查及做出相应策略,然而最好的状态是不要给机会让OOM出现,做好合理架构和监控。
还有一块不在JVM规范中的堆外内存,也称作直接内存。
NIO中一般使用直接内存与外界通讯并作为缓存使用,目的是避免在java堆和native堆来回复制数据,速度快。
相关推荐
"JVM内存区域划分" JVM内存区域划分是Java虚拟机(JVM)中的一种内存管理机制,...JVM内存区域划分是Java虚拟机中的一种重要机制,通过不同的区域来管理内存,避免内存溢出和其他问题,从而确保Java程序的正确执行。
在Java的学习过程中,我们不可避免地需要了解JVM(Java虚拟机)的工作原理,尤其是内存区域的划分。JVM的内存区域主要分为以下几个部分:程序计数器、Java虚拟机栈、本地方法栈、堆以及方法区。这些部分共同协作,...
JVM内存区域划分详细解析: JVM(Java Virtual Machine,Java虚拟机)是运行Java字节码的虚拟机进程。在JVM中,内存区域被划分为几个不同的部分,每一个部分有着不同的用途,从而实现了JVM的稳定和高效运行。根据...
2. **内存区域划分**:JVM内存分为堆内存和栈内存,其中栈内存又包括方法区、虚拟机栈、本地方法栈。堆内存用于存储对象实例,而栈内存则存储线程私有的局部变量、方法参数和运算结果。方法区存储类的信息,如常量池...
总结来说,理解和掌握JVM内存区域的划分以及如何避免内存溢出是Java开发中至关重要的知识点,这有助于优化程序性能和解决运行时的内存问题。通过深入学习JVM的内存管理机制,开发者可以更好地控制和调优Java应用程序...
这些内存空间的划分与管理对于理解和优化JVM的性能至关重要。 2. Java堆内存空间:Java堆内存是运行时Java程序的内存容器,它由JVM管理,并提供了Java程序所需的所有内存空间。了解Java堆内存对于识别和解决内存...
理解JVM内存结构和内存分配机制对于避免内存溢出(OutOfMemoryError)、提升程序性能、减少垃圾回收开销至关重要。开发者应关注内存配置、对象生命周期管理以及适当的垃圾回收策略,以优化应用程序的性能和稳定性。
根据《Java虚拟机规范》,Java虚拟机在运行时会使用到多个类型的内存区域,这些区域根据其性质的不同,可以划分为全局共享或线程私有。 ##### 4.1 程序计数器(Program Counter Register) 程序计数器是一块较小的...
JVM 内存区域是 Java 虚拟机在执行 Java 程序的过程中所管理的内存划分。这些区域都有自己的用途,以及创建和销毁的时间。有的区域随着虚拟机的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。 ### ...
本文主要探讨了JVM的内存区域、线程私有部分、内存溢出异常、垃圾回收机制及其重要性。 首先,JVM内存区域可以分为五个主要部分: 1. **程序计数器**:这是一个线程私有的内存区域,用于存储当前线程执行的字节码...
在JVM运行过程中,可能会遇到各种异常情况,如内存溢出、类加载异常等。理解这些异常的含义和处理方法,对于快速定位和解决问题非常关键。同时,掌握JVM的调试工具,如jstack、jmap、jhat等,可以帮助我们在开发过程...
当线程请求的栈深度超过虚拟机允许的最大深度时,例如递归调用过深,就会发生栈溢出异常(StackOverflowError)。此外,如果线程数量过多,导致分配给每个线程的栈空间不足,也会引发此错误。JVM可以通过参数 `-Xss`...
3. **内存区域**:JVM内存被划分为堆、栈、方法区、程序计数器、本地方法栈等几个区域。其中,堆用于存储对象实例,栈用于处理方法调用,方法区存储类信息,程序计数器记录下一条指令地址,本地方法栈则服务于Java...
法区的描述是“线程共享的”,但不同的JVM实现可能会有不同的策略。...理解JVM的内存区域对于优化程序性能、理解和解决内存溢出等问题至关重要。通过合理配置和管理这些区域,可以提高应用程序的稳定性和效率。
在JVM内存模型方面,本书讲解了JVM内存区域的划分,包括堆(Heap)、栈(Stack)、方法区(Method Area)、程序计数器(Program Counter)和本地方法栈(Native Method Stack)等部分。作者详细解释了这些内存区域的...
5. **内存管理(Memory Management)**:包括对象的分配与回收,内存的分配策略,如新生代、老年代、永久代的划分,以及内存池的概念。 淘宝作为大型电商平台,其内部对JVM的优化和管理有着深入研究。学习这份资料...
在现代JVM中,垃圾回收通常采用分区处理的方式,即将堆空间划分为几个区域,比如年轻代、老年代等,根据不同区域的特点采用不同的回收策略。这种分区处理方式使得垃圾回收更加高效和灵活。 1. **年轻代**:新创建的...
7. **内存溢出与泄漏**:如果JVM内存分配不当,可能导致内存溢出(Out of Memory,OOM),如堆溢出、栈溢出或直接内存溢出。内存泄漏是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,导致系统内存...
2. **运行时数据区(Runtime Data Areas)**:JVM在运行过程中会划分多个区域来存储不同类型的对象和数据,包括方法区、堆、栈、程序计数器和本地方法栈。 - **方法区**:存储类的元数据,如类名、方法信息等。在...