1 Java内存区域与内存溢出异常

九路 等级 989 0 0

1 java虚拟机对内存的管理

java虚拟机在执行java程序的时候把内存分为若干个不同的区,这些区各自有不同的用处,以及创建和销毁时间. 有的区随着虚拟机的启动而启动,有的区则依赖用户线程的启动和结束而启动和结束. 根据java虚拟机规范,java虚拟机将内存分为下面几个部分:如下图

1 Java内存区域与内存溢出异常

下面是对这些区的介绍 1 程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器。字节码解释器就是通过改变该计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需依赖计数器来完成。 每一个JVM线程都有独立的程序计数器,各线程间的计数器互不影响,独立存储,确保线程切换后能够恢复到正确的执行位置。 在任意时刻,一条JVM线程只会执行一个方法的代码。该方法称为该线程的当前方法(Current Method),如果该方法是Java方法,那计数器保存JVM正在执行的字节码指令的地址;如果该方法是Native,那PC寄存器的值为空(Undefined)。 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

2 Java虚拟机栈(Java Virtual Machine Stack)

Java虚拟机栈与程序计数器一样,也是线程私有的,其生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型)和returnAddress类型(指向了一条字节码指令的地址)。其中64位长度的long和double会占用2个局部变量空间(Slot),其余数据类型只占用1个。局部变量表所需的空间在编译期间完成分配,当进入一个方法时,其需要在帧中分配多大的局部变量空间是确定的,方法运行期间不会改变局部变量表的大小。
Java虚拟机规范中对该区域规定了两种异常情况:
1)如线程请求的深度大于虚拟机所允许的深度,抛出StackOverflowError异常。
2)虚拟机栈动态扩展无法申请到足够的内存时,抛出OutOfMemoryError异常。

3 本地方法栈(Native Method Stack)

Java虚拟机可能会使用到传统的栈来支持native方法(使用Java语言以外的其它语言编写的方法)的执行,这个栈就是本地方法栈(Native Method Stack)。本地方法栈与虚拟机栈非常类似,区别是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,二本地方法栈则为虚拟机使用到的Native方法服务。虚拟机规范对本地方法栈中的方法是用语言、使用方式与数据结构没强制规定,因此虚拟机可以自由实现,如Sun HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一。 Java虚拟机规范中对该区域规定了两种异常情况: 1)如线程请求的深度大于虚拟机所允许的深度,抛出StackOverflowError异常。 2)虚拟机栈动态扩展无法申请到足够的内存时,抛出OutOfMemoryError异常。

4 Java堆(Java Heap)

Java堆是Java虚拟机管理内存中最大的一块,是所有线程共享的内存区域,随虚拟机的启动而创建。该区域唯一目的是存放对象实例,几乎所有对象的实例都在堆里面分配。Java堆是垃圾收集器管理的主要区域,被称作“GC堆”。 Java虚拟机规范规定,Java堆可以出于物理上物理上不连续的内存空间中,只要逻辑上连续即可,如同磁盘空间一样,既可以实现成固定大小,也可以是扩展的,当前主流虚拟机都是按照扩展来实现的(通过-Xmx和-Xms控制)。 Java虚拟机规范中对该区域规定了OutOfMemoryError异常:如果堆中没有内存完成实例分配,并且堆无法再扩展则抛出OutOfMemoryError异常。

5 方法区(Method Area)

方法区与Java堆一样,是各个线程共享的内存区域,用于存储一杯虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。Java虚拟机对这个区域的限制非常宽松,处理和Java对一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。 Java虚拟机规范中对该区域规定了OutOfMemoryError异常: 如果方法区的内存空间不能满足内存分配请求,那Java虚拟机将抛出一个OutOfMemoryError异常。

注: 运行时常量池(Runtime Constant Pool) 运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等信息外,还有一项信息是常量池,用于存放编译期生成的各种字面常量和符号引用,这部分内容在类加载后存放到方法区的常量池中。 Java虚拟机规范中对该区域规定了OutOfMemoryError异常: 当常量池无法申请到内存时抛出OutOfMemoryError异常。 直接内存 直接内存并不是虚拟机运行时数据区域的一部分,也非Java虚拟规范中定义的内存区域,但这部分内存也被频繁使用,并且可能导致OutOfMemoryError异常出现。Java虚拟机需要根据实际内存的大小来设置-Xmx等参数信息,如果忽略了直接内存,使得各个内存区域的总和大于物理内存限制,从而导致动态扩展时抛出OutOfMemoryError异常。

一句代码说明Java栈、Java堆和方法区三个最重要的内存区域之间的关联关系 Object obj = new Object();

假设这句代码出现在方法体中:

  • 1)“Object obj”这部分的语义反映到Java栈的本地变量表中,作为一个reference类型数据出现。
  • 2)“new Object()”这个部分的语义反映到Java堆中,形成一块存储了Object类型所有实例数据值的结构化 内存,以及查找到此对象类型的地址信息。
  • 3)Object类的类型数据(如对象类型、父类、接口的实现、方法等)存储在方法区中。
收藏
评论区

相关推荐

1 Java内存区域与内存溢出异常
1 java虚拟机对内存的管理 java虚拟机在执行java程序的时候把内存分为若干个不同的区,这些区各自有不同的用处,以及创建和销毁时间. 有的区随着虚拟机的启动而启动,有的区则依赖用户线程的启动和结束而启动和结束. 根据java虚拟机规范,java虚拟机将内存分为下面几个部分:如下图 image(https://imghelloworld.o
1.0Java基础入门【第一个java程序与注释】
第一个Java程序 ========= 1.安装JRE,JDK,配置环境变量 2.创建**编写**一个java文件,**编译**生成字节码文件(.class),最后**运行** javac helloworld.java **注**:**windows下不区分大小写** java helloworld \------_以下代码是在IDEA编辑器中
JAVA Spring RMI(1)
在Spring整合Rmi中:  服务端使用了org.springframework.remoting.rmi.RmiServiceExporter  RmiServiceExporter把任何Spring管理的Bean输出成一个RMI服务。通过把Bean包装在一个适配器类中工作。适配器类被绑定到RMI注册表中,并且将请求代理给服务类。  客户端使
JDK核心JAVA源码解析(1)
想写这个系列很久了,对自己也是个总结与提高。原来在学JAVA时,那些JAVA入门书籍会告诉你一些规律还有法则,但是用的时候我们一般很难想起来,因为我们用的少并且不知道为什么。知其所以然方能印象深刻并学以致用。 首先我们从所有类的父类Object开始: 1\. Object类 =========== (1)hashCode方法和equals方法 ---
Java 基本功 (基础概念与常识)
### 主要涉及知识点: JVM JDK 和 JRE 最详细通俗的解答Oracle JDK 和 OpenJDK 的对比Java 和 C++的区别?什么是 Java 程序的主类 应用程序和小程序的主类有何不同?Java 应用程序与小程序之间有哪些差别?import java 和 javax 有什么区别?为什么说 Java 语言“编译与解释并存”?
Java程序运行机制及开发环境
### **Java既是编译型语言,又是解释型语言** java源文件首先需要通过javac编译生成后缀名为.class的字节码文件(与平台无关,只面向JVM),然后使用Java虚拟机将字节码解释成特定平台上的机器码运行。 ###**Java虚拟机JVM** 不同平台上的JVM不同,但是都提供了相同的接口。 ###**开发Java准备** 1. 下
java中的类与对象(1)
       首先理解一下类和对象的关系,可以说:类是对象的抽象,对象是类的实例。 **类** ===== 一个类中,通常上包含了属性和功能。属性通常用变量表达,功能通常上用函数表达。编写一个类 class 类名{ //属性,用变量表达 // 功能,用函数表达 } **对象** 实例化对象的方法及含义:类名 对象名 = new 
java复习(1)
这几天开学,很多知识点还很生疏,这两天先把java基础复习一下,有段时间没有写博客了,今天就先谈谈进制转换吧。 * * *   1.二进制数的原码,补码和反码 -----------------     1):对于正数的原码,补码和反码均是相同的,这里不讨论了。     2)接下来我们讨论负数的二进制的原码、反码和补码     负数二进制的原码:先
java字节码操作
你知道如何操作**JAVA**字节码文件吗,这里将介绍与操作Java字节码有关的基本知识和操作Java字节码的方法及Demo,首先我们来看一下AOP的概念,AOP是OOP的延续,是AspectOrientedProgramming的缩写,意思是面向方面编程。 **如何操作JAVA字节码文件**   本文将介绍与操作Java字节码有关的基本知识和操作Ja
java学习(1)
转自: https://blog.csdn.net/qq\_36443736/article/details/82890011 **getMethod():**获取自身能用所有的public公共方法。1.类本身的public 2.继承父类的public 3.实现接口的public **getDeclaredMethod():**获取类自身声明的所有方法,
java面试(1)
1.面向对象的基本特征   封装、继承、多态、   封装:把客观事物封装成类   继承:继承一个类,就可以使用这个类的所有功能,并且在无需编写原来类的情况下对这些功能进行扩展   多态:子对象调用父对象,父对象会根据当前调用的子对象以不同的方式运作   实现多态:覆盖,重载 2.final\\finally\\finalize的区别   fin
JVM入门到放弃之基本概念
### 1\. 基本概念 jvm 是可运行Java代码的假想计算机,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 jvm 是运行在操作系统之上的,屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在 jvm 上运行的字节码,就可以在多种平台上不加修改地运行。 Java 语言的一个非常重要的特点就是与平台的无关性(
Serializable详解(1):代码验证Java序列化与反序列化
![](https://oscimg.oschina.net/oscnet/12f0b4e392b3baa7cae3807718f181a2c4e.png) > **说明:**本文为Serializable详解(1),最后两段内容在翻译上出现歧义(暂时未翻译),将在后续的Serializable(2)文中补充。 > > **介绍:**本文根据JD
Skynet 代码(1)
服务端: #main local skynet = require "skynet" local function action() skynet.uniqueservice("debug_console",8000) skynet.uniqueservice "watchdog" skynet.e
Inside Java Newscast #1 深度解读
本文是 的个人体验与解读。视频地址:⎯⎯⎯⎯⎯⎯ Chapters ⎯⎯⎯⎯⎯⎯ 0:00 Intro 0:57 Java 16 – Intro 1:16 Java 16 – Records 1:43 Java 16 – Type Pattern Matching 1:58 Java 16 – Sealed Classes Previ