JVM学习系列(一) JAVA内存区域和内存溢出异常

JAVA内存区域介绍

程序计数器:

  • 线程私有,很小的内存空间,可以看做是当前线程所执行的字节码的行号指示器;
  • 每个线程都有一个独立的程序计数器,各个线程之间的计数器相互不影响,独立存储;
  • 如果线程执行的是Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址,如果是一个Native方法,那么这个计数器的值则为undefined;
  • 该内存区域不会发生任何的OutOfMemoryError的情况(JAVA虚拟机规范中未规范)。
  • goto 保留字(Java当前版本暂且不用,也不让别人用),具体跳转到某一行,其实就是在操作程序计数器。

    在虚拟机的概念模型中,字节码解释器的工作就是通过改变程序计数器的值来取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复都等都需要依赖这个程序计数器。

Java 虚拟机栈

  • 线程私有,生命周期和线程相同;
  • 为虚拟机执行JAVA方法服务;
  • 描述JAVA方法执行的动态内存模型;
  • 栈帧:每个方法在执行时都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息,每一个方法的从调用到完成的过程,都对应对的虚拟机栈的入栈到出栈的过程。
  • 局部变量表:
    • 存放编译期可知的各种基本数据类型,引用类型,returnAddress类型
    • 局部变量表的内存空间是在编译期完成分配,当进入一个方法时,这个方法需要在帧分配多少内存是固定的, 在方法运行期间是不会改变局部变量表的内存大小的。
  • 如果线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常;
  • 如果虚拟机栈可以动态扩展(Jvm可动态也可以动态长度的虚拟机栈),当扩展到无法申请到足够的内存时,抛出OutOfMemoryError异常。

本地方法栈

  • 线程私有
  • 为虚拟机执行Native方法服务;
  • 作用与JAVA虚拟机栈相同,只是作用域的区别;
  • 如果本地方法请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常;
  • 如果虚拟机栈可以动态扩展(Jvm可动态也可以动态长度的虚拟机栈),当扩展到无法申请到足够的内存时,抛出OutOfMemoryError异常。

JAVA堆

  • 线程共享
  • JAVA虚拟机所管理的内存中最大的一块;
  • 在虚拟机启动时创建;
  • 存放对象实例(所有的对象实例和数组);
  • 垃圾收集器管理的主要区域;
  • 新生代、老年代、Eden空间;
  • 可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可;
  • 可选择固定大小或者动态扩展;
  • -Xms -Xmx 调整堆初始化大小和扩展大小;
  • 在堆中没有内存完成实例分配并且堆无法继续扩展时,抛出OutOfMemoryError异常。

方法区

  • 线程共享;
  • 存储已被虚拟机加载的类信息,常量,静态变量,即时编辑器编译后的代码等数据;
  • 类信息:
    • 类的版本
    • 字段
    • 方法
    • 接口
  • 可选择固定大小或者动态扩展;
  • 可选择不实现垃圾回收;
  • 当无法满足内存分配的时,抛出OutOfMemoryError异常。

运行时常量区

  • 方法区的一部分;
  • Class文件中除了有类的版本、字段、方法等描述信息外,还有常量池,这个主要用于存放编译期生成的各种字面量和符号引用,在类加载时进入方法区的运行时常量池中;
  • 因为属于方法区的一部分,所以当无法满足内存分配的时,抛出OutOfMemoryError异常。

直接内存

  • 不属于运行时数据区的一部分,也不是JAVA虚拟机规范中定义的内存区域;
  • 不收JAVA内存限制,但是受物理内存的限制,各个内存总和大约物理内存限制,在动态扩展时出现OutOfMemoryError异常。

    在JDK1.4中新加入NIO(new Input/Output)类,引入了一种基于通道(Channel)与缓存区(Buffer)的I/O方式,他可以使用Native函数库直接分配堆外内存,然后通过一个存储在JAVA堆中的DirectByteBuffer对象作为这块内存的引用进行操作,这样可以显著提高性能,因为避免了在JAVA堆中和Native堆中来回复制数据。

疑问点

  • String intern

原文地址:https://www.cnblogs.com/jakaBlog/p/11767881.html

时间: 2024-12-13 16:15:16

JVM学习系列(一) JAVA内存区域和内存溢出异常的相关文章

深入理解java虚拟机系列(一):java内存区域与内存溢出异常

文章主要是阅读<深入理解java虚拟机:JVM高级特性与最佳实践>第二章:Java内存区域与内存溢出异常 的一些笔记以及概括. 好了开始.如果有什么错误或者遗漏,欢迎指出. 一.概述 先上一张图 这张图主要列出了Java虚拟机管理的内存的几个区域. 常有人把Java内存区分为堆内存(Heap)和栈内存(Stack),这种分法比较粗糙,Java内存区域的划分实际上远比这复杂,从上图就可以看出了.堆栈分法中所指的"栈"实际上只是虚拟机栈,或者说是虚拟机栈中的局部变量表部分.接下

深入理解JVM之JVM内存区域与内存分配

深入理解JVM之JVM内存区域与内存分配 在学习jvm的内存分配的时候,看到的这篇博客,该博客对jvm的内存分配总结的很好,同时也利用jvm的内存模型解释了java程序中有关参数传递的问题. 博客出处: http://www.cnblogs.com/hellocsl/p/3969768.html?utm_source=tuicool&utm_medium=referral 看了此博客后,发现应该去深入学习下jvm的内存模型,就是去认真学习下<深入理解Java虚拟机>,其内容可能会<

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

Java内存区域与内存溢出异常 概述 对于 C 和 C++程序开发的开发人员来说,在内存管理领域,程序员对内存拥有绝对的使用权,但是也要主要到正确的使用和清理内存,这就要求程序员有较高的水平. 而对于 Java 程序员来说,在虚拟机的自动内存管理机制的帮助下,不再需要为每一个 new 操作去写配对的 delete/free 代码,而且不容易出现内存泄漏和内存溢出问题,看起来由虚拟机管理内存一切都很美好.不过,也正是因为 Java 程序员把内存控制的权力交给了 Java 虚拟机,一旦出现内存泄漏和

【深入Java虚拟机】之一:Java内存区域与内存溢出

[深入Java虚拟机]之:Java内存区域与内存溢出 内存区域 Java虚拟机在执行Java程序的过程中会把他所管理的内存划分为若干个不同的数据区域.Java虚拟机规范将JVM所管理的内存分为以下几个运行时数据区:程序计数器.Java虚拟机栈.本地方法栈.Java堆.方法区.下面详细阐述各数据区所存储的数据类型. 程序计数器(Program Counter Register) 一块较小的内存空间,它是当前线程所执行的字节码的行号指示器,字节码解释器工作时通过改变该计数器的值来选择下一条需要执行的

深入理解jvm之内存区域与内存溢出

文章目录 1. Java内存区域与内存溢出异常 1.1. 运行时数据区域 1.1.1. 程序计数器 1.1.2. java虚拟机栈 1.1.3. 本地方法栈 1.1.4. Java堆(Java Heap) 1.1.5. 方法区 1.1.6. 运行时常量池 1.1.7. 直接内存 1.2. HotSpot虚拟机 1.2.1. 对象的创建 1.2.2. 对象的访问定位 1.3. OOM异常的解决思路 1.4. 参考 Java内存区域与内存溢出异常 运行时数据区域 程序计数器 当前线程所执行的字节码的

图解Java内存区域及内存溢出异常

图解 Java 内存区域及内存溢出异常 在阅读 <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版) >后,为了加深对 Java 内存区域的印象及理解,特意做成了思维导图. 名词解释 线程共享数据区域 直接内存 并不是虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区.NIO 中使用 Native 函数直接分配堆外内存 方法区 Method Area 用于存放已被虚拟机加载的类信息.常量.静态变量.JIT 编译后的代码等 也称作 永久代,在这块容易遇到 OOM 问题

Java内存区域的划分和异常

Java内存区域的划分和异常 运行时数据区域 JVM在运行Java程序时候会将内存划分为若干个不同的数据区域. 打开百度App,看更多美图 程序计数器 线程私有.可看作是当前线程所执行的字节码的行号指示器,字节码解释器的工作是通过改变这个计数值来读取下一条要执行的字节码指令. 多线程是通过线程轮流切换并分配处理器执行时间来实现的,任何一个时刻,一个内核只能执行一条线程中的指令.为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器.这就是一开始说的"线程私有".如果线

深入了解Java虚拟机(1)java内存区域与内存溢出异常

java内存区域与内存溢出异常 一.运行时数据区域 1.程序计数器:线程私有,用于存储当前所执行的指令位置 2.Java虚拟机栈:线程私有,描叙Java方法执行模型:执行方法时都会创建一个栈帧,存储局部变量,基本类型变量,引用等信息 3.Java本地方法栈:线程私有,为虚拟机使用到的Native方法服务 4.Java堆:线程共享,是垃圾收集器的主要工作地方:存储对象实例等 5.方法区:线程共享:存储类信息,常量,静态变量等 运行时常量:存放编译时生成的各种字面量和符号引用 6.直接内存:机器的内

《深入理解Java虚拟机》读书笔记---第二章 Java内存区域与内存溢出异常

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来.这一章就是给大家介绍Java虚拟机内存的各个区域,讲解这些区域的作用,服务对象以及其中可能产生的问题. 1.运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 1.1程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型中里,字