一.概述

  我们在进行 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. HTML一些有趣的东西

    1.<head>标签里: <meta http-equiv="Refresh" content="3"/><!--三秒自动刷新-- ...

  2. Redis 如何分析慢查询操作?

    什么是慢查询 和mysql的慢SQL日志分析一样,redis也有类似的功能,来帮助定位一些慢查询操作. Redis slowlog是Redis用来记录查询执行时间的日志系统. 查询执行时间指的是不包括 ...

  3. dedecms中arclist标签做分页以及分页点击模块样式错乱问题

    in 使用织梦建站,通常会调用到一个文章列表,dedecms官网list标签没有提供typeid的属性,首页或多列表部分情况下使用分页并不方便,这就需要用arclist标签实现一个分页功能:以下还是展 ...

  4. 【log4j2】log4j的升级版log4j2的简单入门使用

    1.jar包 log4j-api.jar    +    log4j-core.jar maven仓库配置: <dependency> <groupId>org.apache. ...

  5. java提高(4)---数组增删 list删除 map删除

    数组增删 集合删除 一.数组增删 package com.test; import java.util.List; import java.util.ArrayList; import java.ut ...

  6. Nexus私服搭建

    maven私服的搭建 --> maven -->{ 1,本地仓库(从中央仓库下载保存到本地的或者自己到网上下载的jar文件包) 2,远程仓库 -->{ 1,中央仓库(maven官方j ...

  7. java设定一个日期时间,加几分钟(小时或者天)后得到新的日期

    //返回的是字符串型的时间,输入的 //是String day, int x public static String addDateMinut(String day, int x){ SimpleD ...

  8. 求一个Map中最大的value值,同时列出键,值

    求一个Map中最大的value值,同时列出键,值 方法1. public static void main(String[] args){  Map map=new HashMap();  map.p ...

  9. 剑指offer例题分享--8

    前言:继续分享,加油! 面试题44: 代码如下: #include<iostream> #include<stdlib.h> using namespace std; int ...

  10. 搭建 MobileNet-SSD 开发环境并使用 VOC 数据集训练 TensorFlow 模型

    原文地址:搭建 MobileNet-SSD 开发环境并使用 VOC 数据集训练 TensorFlow 模型 0x00 环境 OS: Ubuntu 1810 x64 Anaconda: 4.6.12 P ...