一.概述

  我们在进行 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. javascript数组的属性、方法和清空-最全!!!(必看)

    今天经理要我从新看一遍js,当我再看<精通js和jquery>这本书时,发现关于数组的这章节讲的很少,于是想自己总结一下数组的常用方法. 定义数组: var arr = new Array ...

  2. 1.numpy的用法

    numpy创建ndarray对象的三种方法 1.1.list转化 In [8]: import numpy as np In [9]: a = [1,2,3,4] In [10]: x1 = np.a ...

  3. MySQL(5)---锁

    锁 一概述 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则.对于任何一种数据库来说都需要有相应的锁定机制. MySQL各存储引擎使用了三种 ...

  4. 设置build.gradle打包时自动加时间

    在build.gradle中添加以下函数: def releaseTime() { return new Date().format("yyyyMMddHHmm", TimeZon ...

  5. 解决运行nodejs代码Error: listen EADDRINUSE

    问题是什么 EADDRINUSE其实拆分来看就是error address use表示错误地址的使用,也代表着端口占用. 如何解决问题 那讲道理来说,接下来你就需要找到你要用的端口被哪一个进程所占用了 ...

  6. Hibernate学习(六)———— cascade(级联)和inverse关系详解

    序言 写这篇文章之前,自己也查了很多的资料来搞清楚这两者的关系和各自所做的事情,但是百度一搜,大多数博文感觉说的云里雾里,可能博主自己清楚是怎么一回事,但是给一个不懂的人或者一知半解的人看的话,别人也 ...

  7. 【Go】优雅的读取http请求或响应的数据-续

    原文链接:https://blog.thinkeridea.com/201902/go/you_ya_de_du_qu_http_qing_qiu_huo_xiang_ying_de_shu_ju_2 ...

  8. 跨域 webpack + vue-cil 中 proxyTable 处理跨域

    博客地址:https://ainyi.com/27 跨域 了解同源政策:所谓"同源"指的是"三个相同". 协议相同 域名相同 端口相同 解决跨域 jsonp 缺 ...

  9. 从零开始学安全(六)●黑客常用的Dos命令

    cd   文件路径                      要切换的路径cd \                                     直接回根目录dir              ...

  10. 1.shell学习之常用语句

    本章学习内容: 1.常见符号 2.命令分隔符-分号";" 3.双分号 ";;" 4. '单引号和"双引号 5.`反引号和$() 6.${}和$ 7.冒 ...