一.概述

  我们在进行 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 是否已经初始化
  1. 若没有则先执行初始化过程
  • 分配内存,检查堆是否规整(垃圾收集器是否带有压缩整理功能决定)
  1. 规整:指针碰撞方式分配内存
  2. 不规整:空闲列表方式分配内存
  • 内存空间初始化为零值(不包括对象头)
  • 对对象进行重要的配置
  • 执行 < init > 方法

2、对象的内存布局

对象头(Mark Word)

  • 自身运行时数据
  1. GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID
  2. 类型指针:确定对象是哪个Class的实例

实例数据

  • 存储有效信息,定义的各种字段
  • 相同宽度的字段总是被分配到一起

对齐填充

  • 不一定存在
  • 实例数据没有对齐,需要填充

3、对象的访问定位
句柄(reference):

  • 堆中划分句柄池
  • 句柄地址
  1. 到对象实例数据的地址
  2. 到对象类型的地址
  • 优势:稳定,对象移动时,(如GC时会移动),这个时候只改变指针地址。句柄信息不变,相对稳定;

指针:

  • 直接存储了上述的对象地址
  • 优势:速度快

五.OOM

  • 堆溢出:举例一直 new 新的实例对象
  • 栈溢出:举例无限循环调用执行某个方法
  • 方法区和运行时常量池溢出:
  1. String.intern():如果常量池已存在,则返回 String 对象,如果不存在,则先添加到常量池,再返回 String 对象。
  2. 动态定义大量的 Class,需要注意内存的回收情况。

深入理解Java虚拟机02--Java内存区域与内存溢出异常的更多相关文章

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

    文章主要是阅读<深入理解java虚拟机:JVM高级特性与最佳实践>第二章:Java内存区域与内存溢出异常 的一些笔记以及概括. 好了開始.假设有什么错误或者遗漏,欢迎指出. 一.概述 先上 ...

  2. 深入理解Java虚拟机之Java内存区域与内存溢出异常

    Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...

  3. 深入理解Java虚拟机之图解Java内存区域与内存溢出异常

    Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...

  4. 深入理解Java虚拟机之Java内存区域随笔

    1.java内存区域与内存溢出异常 Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域:1.程序计数器,2.栈(虚拟机栈和本地方法栈 ),3.堆,4.方法区(包含 ...

  5. 《深入理解java虚拟机》第二章 Java内存区域与内存溢出异常

    第二章 Java内存区域与内存溢出异常 2.2 运行时数据区域  

  6. 深入理解java虚拟机-第二章:java内存区域与内存泄露异常

    2.1概述: java将内存的管理(主要是回收工作),交由jvm管理,确实很省事,但是一点jvm因内存出现问题,排查起来将会很困难,为了能够成为独当一面的大牛呢,自然要了解vm是怎么去使用内存的. 2 ...

  7. 深入理解Java虚拟机(1)--Java内存区域

    运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用 ...

  8. 深入理解java虚拟机---->java内存区域与内存溢出异常

    2. java内存区域于内存溢出异常 2.1 概述: 对于C/C++而言,内存管理具有最高的权利,既拥有每一个对象的“所有权”,又担负着每一个对象生命开始到结束的维护责任. 对于java而言,则把内存 ...

  9. 《深入理解Java虚拟机》之(一、内存区域)

    一.java的体系构成: Java的技术体系主要由支撑java程序运行的虚拟机.提供各种开发领域接口支持的java api.java编程语言及许多第三方java框架(如Spring .Struts等) ...

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

    java内存区域与内存溢出异常 一.运行时数据区域 1.程序计数器:线程私有,用于存储当前所执行的指令位置 2.Java虚拟机栈:线程私有,描叙Java方法执行模型:执行方法时都会创建一个栈帧,存储局 ...

随机推荐

  1. IDEA整合Junit详细步骤

    一.添加Junit插件. 1.file-->setting-->plugins-->搜索Junit-->安装插件(一般已默认安装,无需手动安装). 二.设置Junit测试参数: ...

  2. [CERC2014] Virus synthesis

    设f[i]为形成极长回文串i的最小操作数.答案为min f[i]+n-len[i]. 在不形成偶回文的情况下形成奇回文的最小操作数为该串长度.可以不考虑(但ans赋为len). 正确性基于: 1)奇. ...

  3. 一道关于:ArrayList、Vector、LinkedList的存储性能和特性 的面试题

    ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动等内存操作,所以索引数据快插入数据慢 ...

  4. CentOS7.0小随笔——运行级别

    一.Linux运行级别(通用) 0:关机(halt) 1:单用户模式(无需用户名和密码的登录,用于紧急维护系统时用,类似于Windows中的安全模式) 2:不启用网络功能的多用户模式 3:启用网络功能 ...

  5. Linux软件包管理之源码包、脚本安装包

    目录 1.源码包和RPM包的区别 RPM包和源码包默认安装位置: 由于安装位置不同带来的影响 2.源码包安装 ①.安装准备 ②.安装注意事项 ③.安装源码包 3.源码包卸载 4.脚本安装包 5.总结 ...

  6. Java BIO、NIO、AIO

    同步与异步 同步与异步的概念, 关注的是 消息通信机制 同步是指发出一个请求, 在没有得到结果之前该请求就不返回结果, 请求返回时, 也就得到结果了. 比如洗衣服, 把衣服放在洗衣机里, 没有洗好之前 ...

  7. spring-boot(二)

    学习文章来自:http://www.ityouknow.com/spring-boot.html web开发 spring boot web开发非常的简单,其中包括常用的json输出.filters. ...

  8. Go语言学习笔记(六) [包]

    日期:2014年7月30日   1.定义:包时函数和数据的集合.使用package关键字定义一个包,文件名不需要与包名一致,包名约定使用小写字符,Go包可以由多个文件组成,但是需要使用相同的packa ...

  9. Python面向对象基础:编码细节和注意事项

    在前面,我用了3篇文章解释python的面向对象: 面向对象:从代码复用开始 面向对象:设置对象属性 类和对象的名称空间 本篇是第4篇,用一个完整的示例来解释面向对象的一些细节. 例子的模型是父类Em ...

  10. Zookeeper(一) —— 环境搭建

    一.概述 集中式 向 分布式演变,高并发.海量存储 应用场景: * 数据发布.订阅的两种方式:推模式.拉模式 * 命名服务 * 分布式协调/通知(心跳检测) * 负载均衡 自增长id和uuid的缺点, ...