深入理解Java虚拟机02--Java内存区域与内存溢出异常
一.概述
我们在进行 Java 开发的时候,很少关心 Java 的内存分配等等,因为这些活都让 JVM 给我们做了。不仅自动给我们分配内存,还有自动的回收无需再占用的内存空间,以腾出内存供其他人使用。但是我们经常面临的一个问题就是内存泄漏,JVM无法完成回收工作,导致内存占用暴涨,最后可能让程序奔溃。本章主要了解下运行时数据区域分布情况以及溢出异常。
二.运行时数据区域

1、程序计数器
- 线程私有
- 当前线程所执行的字节码的行号指示器
- Java 多线程是通过再一个内核中轮流执行实现的,计数器就保证了切换线程的时候可以回到原来正确的执行位置
- 程序计数器必须每个线程单独一个,是线程私有的内存区域
- 程序计数器是唯一一个 JVM 没有规范 OutOfMemoryError 的区域
2、Java虚拟机栈(java方法)
- 线程私有
- Java方法执行的内存模型,即方法执行时会创建一个栈帧,保存了需要的局部变量表、操作数栈、动态链接、方法出口等信息;
- 线程请求的栈深度>JVM允许的深度时,报StackOverflowError;
- 大多数的 JVM 可以动态扩展内存,如果无法申请到足够的内存时,报 OutOfMemoryError;
3、本地方法栈(native方法)
- 同Java虚拟机栈
4、Java堆
- 线程共享
- 唯一目的:存放对象实例
- 分类:新生代、老生代,或者 Eden 空间、From Survior 空间、To Survivor 空间
- 分类目的:更好的回收和分配内存
- 没有内存完成实例分配,或者不能再扩展,报OutOfMemoryError 异常
- 可以自己配置大小(-Xmx和-Xms)
5、方法区
- 线程共享
- 目的:存储类信息、常量、静态变量、即时编译器编译后的代码等数据;
- 该区内存回收目标:主要针对常量池的回收和对类型的卸载;
- 无法满足内存分配要求时,报 OutOfMemoryError 异常
6、运行时常量池
- 注意:运行时常量池属于方法区
- 目的:存储编译期生成的各种字面量和符号引用
- 特征:并非只有编译期置入 Class 文件中的常量池内容才能进入运行时常量池,在运行期间也可以置入新的常量,比如 String 的intern() 方法;
- 无法申请足够内存时,报 OutOfMemoryError 异常
三.直接内存
- 非运行时数据区域内存
- Native 函数分配堆外内存,堆内的 DirectByteBuffer 作为这块内存的引用
- 性能显著提高,避免了 Java 堆和 native 之间来回复制数据
四.HotSpot虚拟机对象探秘
1、New对象过程
- new 指令发出
- 检查 new 的参数是否在常量池中存在这个 Class 的符号引用
- 检查对应的 Class 是否已经初始化
- 若没有则先执行初始化过程
- 分配内存,检查堆是否规整(垃圾收集器是否带有压缩整理功能决定)
- 规整:指针碰撞方式分配内存
- 不规整:空闲列表方式分配内存
- 内存空间初始化为零值(不包括对象头)
- 对对象进行重要的配置
- 执行 < init > 方法
2、对象的内存布局
对象头(Mark Word)
- 自身运行时数据
- GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID
- 类型指针:确定对象是哪个Class的实例
实例数据
- 存储有效信息,定义的各种字段
- 相同宽度的字段总是被分配到一起
对齐填充
- 不一定存在
- 实例数据没有对齐,需要填充
3、对象的访问定位
句柄(reference):
- 堆中划分句柄池
- 句柄地址
- 到对象实例数据的地址
- 到对象类型的地址
- 优势:稳定,对象移动时,(如GC时会移动),这个时候只改变指针地址。句柄信息不变,相对稳定;
指针:
- 直接存储了上述的对象地址
- 优势:速度快
五.OOM
- 堆溢出:举例一直 new 新的实例对象
- 栈溢出:举例无限循环调用执行某个方法
- 方法区和运行时常量池溢出:
- String.intern():如果常量池已存在,则返回 String 对象,如果不存在,则先添加到常量池,再返回 String 对象。
- 动态定义大量的 Class,需要注意内存的回收情况。
深入理解Java虚拟机02--Java内存区域与内存溢出异常的更多相关文章
- 深入理解java虚拟机系列(一):java内存区域与内存溢出异常
文章主要是阅读<深入理解java虚拟机:JVM高级特性与最佳实践>第二章:Java内存区域与内存溢出异常 的一些笔记以及概括. 好了開始.假设有什么错误或者遗漏,欢迎指出. 一.概述 先上 ...
- 深入理解Java虚拟机之Java内存区域与内存溢出异常
Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...
- 深入理解Java虚拟机之图解Java内存区域与内存溢出异常
Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...
- 深入理解Java虚拟机之Java内存区域随笔
1.java内存区域与内存溢出异常 Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域:1.程序计数器,2.栈(虚拟机栈和本地方法栈 ),3.堆,4.方法区(包含 ...
- 《深入理解java虚拟机》第二章 Java内存区域与内存溢出异常
第二章 Java内存区域与内存溢出异常 2.2 运行时数据区域
- 深入理解java虚拟机-第二章:java内存区域与内存泄露异常
2.1概述: java将内存的管理(主要是回收工作),交由jvm管理,确实很省事,但是一点jvm因内存出现问题,排查起来将会很困难,为了能够成为独当一面的大牛呢,自然要了解vm是怎么去使用内存的. 2 ...
- 深入理解Java虚拟机(1)--Java内存区域
运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用 ...
- 深入理解java虚拟机---->java内存区域与内存溢出异常
2. java内存区域于内存溢出异常 2.1 概述: 对于C/C++而言,内存管理具有最高的权利,既拥有每一个对象的“所有权”,又担负着每一个对象生命开始到结束的维护责任. 对于java而言,则把内存 ...
- 《深入理解Java虚拟机》之(一、内存区域)
一.java的体系构成: Java的技术体系主要由支撑java程序运行的虚拟机.提供各种开发领域接口支持的java api.java编程语言及许多第三方java框架(如Spring .Struts等) ...
- 深入了解Java虚拟机(1)java内存区域与内存溢出异常
java内存区域与内存溢出异常 一.运行时数据区域 1.程序计数器:线程私有,用于存储当前所执行的指令位置 2.Java虚拟机栈:线程私有,描叙Java方法执行模型:执行方法时都会创建一个栈帧,存储局 ...
随机推荐
- IDEA整合Junit详细步骤
一.添加Junit插件. 1.file-->setting-->plugins-->搜索Junit-->安装插件(一般已默认安装,无需手动安装). 二.设置Junit测试参数: ...
- [CERC2014] Virus synthesis
设f[i]为形成极长回文串i的最小操作数.答案为min f[i]+n-len[i]. 在不形成偶回文的情况下形成奇回文的最小操作数为该串长度.可以不考虑(但ans赋为len). 正确性基于: 1)奇. ...
- 一道关于:ArrayList、Vector、LinkedList的存储性能和特性 的面试题
ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动等内存操作,所以索引数据快插入数据慢 ...
- CentOS7.0小随笔——运行级别
一.Linux运行级别(通用) 0:关机(halt) 1:单用户模式(无需用户名和密码的登录,用于紧急维护系统时用,类似于Windows中的安全模式) 2:不启用网络功能的多用户模式 3:启用网络功能 ...
- Linux软件包管理之源码包、脚本安装包
目录 1.源码包和RPM包的区别 RPM包和源码包默认安装位置: 由于安装位置不同带来的影响 2.源码包安装 ①.安装准备 ②.安装注意事项 ③.安装源码包 3.源码包卸载 4.脚本安装包 5.总结 ...
- Java BIO、NIO、AIO
同步与异步 同步与异步的概念, 关注的是 消息通信机制 同步是指发出一个请求, 在没有得到结果之前该请求就不返回结果, 请求返回时, 也就得到结果了. 比如洗衣服, 把衣服放在洗衣机里, 没有洗好之前 ...
- spring-boot(二)
学习文章来自:http://www.ityouknow.com/spring-boot.html web开发 spring boot web开发非常的简单,其中包括常用的json输出.filters. ...
- Go语言学习笔记(六) [包]
日期:2014年7月30日 1.定义:包时函数和数据的集合.使用package关键字定义一个包,文件名不需要与包名一致,包名约定使用小写字符,Go包可以由多个文件组成,但是需要使用相同的packa ...
- Python面向对象基础:编码细节和注意事项
在前面,我用了3篇文章解释python的面向对象: 面向对象:从代码复用开始 面向对象:设置对象属性 类和对象的名称空间 本篇是第4篇,用一个完整的示例来解释面向对象的一些细节. 例子的模型是父类Em ...
- Zookeeper(一) —— 环境搭建
一.概述 集中式 向 分布式演变,高并发.海量存储 应用场景: * 数据发布.订阅的两种方式:推模式.拉模式 * 命名服务 * 分布式协调/通知(心跳检测) * 负载均衡 自增长id和uuid的缺点, ...