深入理解Java 虚拟机 之自动内存管理

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

1. 运行时数据区域

Java 虚拟机在执行Java 程序的过程中慧把它所管理的内存划分为若干个不同的数据区域。如下图所示:

(1).程序计数器:较小的内存空间,可以看作时当前线程所执行的字节码的行号指示器。(是唯一一个不会OOM 的区域)

(2).Java 虚拟栈:存储局部变量、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成,对应一个栈帧在虚拟机栈中入栈和出栈的过程。

(3).本地方法栈:类似与虚拟机栈,只不过两者执行的服务不一样,前者时虚拟机栈为虚拟机执行Java 方法(也就是字节码)服务,后者为虚拟机使用到的Native 方法服务。

(4).Java 堆(也叫GC 堆):虚拟机管理的内存中最大的一块,唯一目的就是存放实例对象。

(5).方法区:存储常量、静态变量等。

(6).运行时常量池:属于方法区的一部分

(7).直接内存:既不属于虚拟机也不是Java 虚拟机规范中定义的内存区域。NIO 的时候会用到

2. HotSpot 虚拟机对象

进一步了解这些虚拟机内存中的数据的其他细节。包括创建----布局----访问

(1).对象的创建

在语言层面上,创建对象(例如:克隆、反序列化)通常仅仅是一个new 关键字而已,而在虚拟机中对象创建要复杂的多,如下图所示:

(2).对象的内存布局:三块区域----对象头、实例数据和对齐填充

  • 对象头

    ①用于存储对象自身的运行时数据:哈希码、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等;

    ②对象指向它的类元数据的类型指针(但是不一定每个对象都有),如果对象时数组那么对象头中还包括一块用于记录数组长度的数据;

  • 实例数据:是对象真正存储的有效信息,也是程序代码中所定义的哥中类型的字段内容;
  • 对齐填充:不是必然存在,也没有特别的含义,仅仅起着占位符的作用;

(3).对象的访问定位:原理:栈上的reference 数据来操作堆上的具体对象,有两种方式----句柄和直接指针

  • 句柄:Java 堆中划分一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息,如下图所示

  

  • 直接指针:Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference 中存储的直接就是对象地址,如下图所示

   

  • 两种访问的区别:句柄:reference记录的是句柄地址,对象改变时只需要改变句柄中实例数据的指针,不影响reference指向,更稳定;直接指针:直接访问对象,相对句柄访问中间少了一层句柄池,因此更快,但是开销会积少成多,增加执行成本。
3. OutOfMemoryError 异常

(1).Java 堆溢出:使用Eclipse Memory Analyzer 分析堆转储快照文件,详细见Eclipse Memory Analyzer,内存泄漏插件,安装使用一条龙

(2).虚拟机栈和本地方法栈溢出:

①如果线程请求的栈深度大于虚拟机所运行的最大深度,将抛出StackOverflowError 异常(内存泄漏)

②如果虚拟机在扩展时无法申请到足够的内存空间,则抛出OutOfMemoryError 异常(内存溢出)

(3).方法区和运行时常量池溢出

(4).本机直接内存溢出

4. 总结

1. 虚拟机中的内存是如何划分

2. 异常产生的原因

  

原文地址:https://www.cnblogs.com/hellovoyager1/p/9153434.html

时间: 2024-11-10 16:43:20

深入理解Java 虚拟机 之自动内存管理的相关文章

深入理解java虚拟机二,内存管理机制

java 虚拟机自动内存管理. java虚拟机在执行java程序的过程中会把它所管理的内存划分为若干个不同区域 1 程序计数器 每个线程都有一个独立的计数器,用来指示需要执行的字节码的位置. 2 虚拟机栈 虚拟机栈是用来描述java方法执行的内存模型,每个方法被执行的时候都会同时创建一个栈帧用于储存局部变量表,操作栈,动态链接,方法出口等信息. 每一个方法被调用直至执行完成的过程,就对应着一个栈帧从虚拟机栈中从入栈到出栈的过程. 虚拟机栈线程私有,声明周期和线程一样. 局部变量表所需的内存空间在

java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)

概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又是执行最基础工作的劳动人民——拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的维护责任. 对于Java程序员来说,不需要在为每一个new操作去写配对的delete/free,不容易出现内容泄漏和内存溢出错误,看起来由JVM管理内存一切都很美好.不过,也正是因为Java程序员把内存控制的

java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项技术当做Java语言的伴生产物.事实上GC的历史远远比Java来得久远,在1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.当Lisp还在胚胎时期,人们就在思考GC需要完成的3件事情:哪些内存需要回收?什么时候回收?怎么样回收? 经过半个世纪的发展,目前的内存分配策略

挑战高薪必看:《深入理解java虚拟机 jvm高级特性与最佳实践》

Java是目前用户最多.使用范围最广的软件开发技术之一.Java 的技术体系主要由支撑 Java程序运行的虚拟机.提供各开发领域接口支持的Java API.Java 编程语言及许多第三方 Java框架(如Spring.Struts 等)构成.在国内,有关Java API.Java语言语法及第三方框 架的技术资料和书籍非常丰富,相比之下,有关Java虚拟机的资料却显得异常贫乏. 资料获取方法 内容特色 第一部分走近 Java 本书的第部分为后文的讲解建立了良好的基础.尽管了解Java技术的来龙去脉

【深入理解Java虚拟机】Java内存区域模型、对象创建过程、常见OOM

本文内容来源于<深入理解Java虚拟机>一书,非常推荐大家去看一下这本书.最近开始看这本书,打算再开一个相关系列,来总结一下这本书中的重要知识点.呃呃呃,说好的那个图片请求框架呢~  不要急哈,因为这个请求框架设计的内容还是比较广的,目前业余时间正在编写当中,弄好了之后就会放上来.在完成之前,咱还是先来学习一下其他知识. 1.内存模型 java虚拟机在执行java程序的过程中会把它说管理的内存划分为若干个不同的数据区域,如下图所示: 图片来源于网络 (1)程序计数器(Program Count

深入理解java虚拟机-----&gt;垃圾收集器与内存分配策略(下)

1.  前言 内存分配与回收策略 JVM堆的结构分析(新生代.老年代.永久代) 对象优先在Eden分配 大对象直接进入老年代 长期存活的对象将进入老年代 动态对象年龄判定 空间分配担保  2.  垃圾收集器与内存分配策略 Java技术体系中所提倡的自动内存管理最终可以归结为自动化地解决两个问题: 给对象分配内存; 回收分配给对象的内存. 对象的内存分配,往大方向上讲就是在堆上的分配,对象主要分配在新生代的Eden区上.少数也可能分配在老年代,取决于哪一种垃圾收集器组合,还有虚拟机中的相关内存的参

Java自动内存管理机制学习(一):Java内存区域与内存溢出异常

备注:本文引用自<深入理解Java虚拟机第二版> 2.1 运行时数据区域 Java虚拟机在执行Java程序的过程中把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁.如下图所示: 2.1.1 程序计数器 程序计数器是一块较小的内存空间,它是线程的私有内存,可以看作时当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去

JVM自动内存管理机制——Java内存区域

一.JVM运行时数据区域概述 Java相比较于C/C++的一个特点就是,在虚拟机自动内存管理机制的帮助下,我们不需要为每一个操作都写像C/C++一样的delete/free代码,所以也不容易出现内存泄漏和内存溢出的问题.显然,这里的不容易只是相对而言的,如果我们想要降低这种代码隐患的发生,就需要对Java虚拟机怎样使用内存有了解,这样的话就算产生错误,排查起来也会相对容易.下面我们来说一说JVM运行时数据区域 1.程序计数器(PC寄存器): 被看作是当前线程所执行的字节码的行号指示器,字节码解析

深入理解java虚拟机笔记(一)-java内存区域与内存溢出

1. 前言 这是深入理解java虚拟机一书的笔记,来自第二章.因为这本书讲的比较深奥,这是第二次看,需要记录一下笔记. 2. 运行时数据区域 java虚拟机所管理的内存分为以下几个区域. ps:图片来自网络 2.1 程序计数器 程序计数器是一块较小的内存空间,他可以看做是当前线程所执行字节码的行号指示器.字节码解释器工作时就是通过改变这个计数器的值来选去下一条要执行的字节码指令,分之.循环.跳转.异常处理.线程恢复等基础功能都需要依赖这个计数器来完成. 这块内存是线程私有的内存. 如果线程在执行