一.概述

  我们在进行 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. mysql 开发进阶篇系列 47 物理备份与恢复(xtrabackup 的完全备份恢复,恢复后重启失败总结)

    一. 完全备份恢复说明 xtrabackup二进制文件有一个xtrabackup --copy-back选项,它将备份复制到服务器的datadir目录下.下面是通过 --target-dir 指定完全 ...

  2. Spring Boot SOAP Webservice例子

    前言 本文将学习如何利用Spring boot快速创建SOAP webservice服务: 虽然目前REST和微服务越来越流行,但是SOAP在某些情况下,仍然有它的用武之地: 在本篇 spring b ...

  3. MySQL中支持emoji表情的存储

    由于需要实现emoji表情评论的功能,所以数据库需要支持emoji表情的存储,根据查询的资料最终实现了该功能,现将实现的过程以及过程遇到的一些问题记录下来,供大家参考和交流. mysql的utf8编码 ...

  4. 第6章 LVM详解

    6.1 LVM相关概念和机制 LVM(Logical Volume Manager)可以让分区变得弹性,可以随时随地的扩大和缩小分区大小,前提是该分区是LVM格式的. lvm需要使用的软件包为lvm2 ...

  5. MySQL中间件之ProxySQL(10):读写分离方法论

    返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.html 1.不同类型的读写分离 数据库中间件最基本的功能就是实现读写分离,Pr ...

  6. MySQL中间件之ProxySQL(14):ProxySQL+PXC

    返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.html 1.ProxySQL+PXC 本文演示ProxySQL代理PXC(Pe ...

  7. js如何获取url参数

    匹配URL参数的正则是: var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", ...

  8. 分部视图(Partial View)及Html.Partial和Html.Action差异

    参考资料:  https://www.cnblogs.com/Leon-Hu/p/5575311.html

  9. Oracle 数据库导出数据泵(EXPDP)文件存放的位置

    数据泵是服务器端工具,导出的文件是放在数据库所在的服务器上,当然我们知道可以通过directory目录对象来控制.目录对象默认有四个级别,当然是有优先级顺序的,优先级从上往下 1.每个文件单独的指定具 ...

  10. 扩展RBAC用户角色权限设计方案(转载)

    扩展RBAC用户角色权限设计方案  来源:https://www.cnblogs.com/zwq194/archive/2011/03/07/1974821.html https://blog.csd ...