一.运行时数据区

  共分为5块:

  • 程序计数器      (线程私有,当前线程所执行的字节码的行号指示器)
  • Java虚拟机栈  (线程私有,证明周期与线程相同,描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储:局部变量表、操作数栈、动态链接、方法出口等信息)
  • 本地方法栈      (线程私有,本地方法栈类似于虚拟机栈,只不过执行的是Native方法)
  • Java堆         (线程共享的一块内存区域,几乎所有的对象实例以及数组都要在堆上分配)
  • 方法区              (线程共享,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据)
  • 直接内存         (并不属于JVM但是需要讲一下)

1.1  Java虚拟机栈
    
局部变量表: 存放了编译期可知的基本数据类型和对象引用和returnAddress类型。

  局部变量表所需的内存空间在编译期完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全正确的,在方法运行期间不会改变局部变量表的大小。

  在Java虚拟机规范中,对这个区域规定了两种异常情况:

  • 如果线程请求的栈深度大于虚拟机所允许的栈深度,将抛出StackOverflowError异常
  • 如果虚拟机可以动态扩展,扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常

 1.2  Java堆

   因为几乎所有的对象实例都要分配到堆上,而GC的主要清理目标就是对象实例,所以,Java堆是GC的主要区域。

   由于现在的收集器大都采用分代收集算法,所以Java堆还可以细分:新生代和老年代;再细致一点还可以分为Eden空间,from Survivor空间 和 to Survivor空间。

   具体 回收算法和方案  稍后 详细讲解

 

 1.3 对象的创建

  1. 检查这个new  指令的参数是否能够在常量池定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有则执行类加载。
  2. 为新生对象分配内存-指针碰撞: 堆内存是规整的,则只需要移动指针获取相应大小的空间;空闲列表:堆内存不规整,需要维护一个列表记录哪些内存空间可用,从列表中获取然后分配。会产生同步问题,CAS +失败重试机制。
  3. 内存分配完成之后,给内存空间初始化为零值(不含对象头)。
  4. 设置必要信息(属于哪个类的实例,类的元数据,对象的哈希码).
  5. 虚拟机部分对象已完成,接下来按照程序构造,初始化对象

二. OutOfMemoryError 和  StackOverflowError

    

1.java堆溢出  示例:

  配置参数:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError(dump当前内存堆的转储快照)

public class LeetCode {

    // 堆溢出
static class OOMobject {} public static void main(String[] args){
// 堆溢出
List<OOMobject> list = new ArrayList<>(); while(true){
list.add(new OOMobject());
} }
}

使用Jhat查看解析快照文件。

  解决方案:1.查看是否是内存泄露,可以用工具查看GC Roots与对象的关联路径  判断哪些对象是无用的,什么原因导致GC无法回收

       2.如不存在泄露,应当查看 堆参数 也就是 -Xmx 和 -Xms,看一下物理内存是否还允许堆内存调大一些

       3.从代码上检查是否存在某些对象的生命周期过长、持有状态时间过长的情况,尝试优化代码减少内存消耗。 

       

2.虚拟机栈溢出

public class LeetCode {

    private int stackLength = 1;

    public static void main(String[] args) throws Throwable{
LeetCode leetCode = new LeetCode();
try{
leetCode.stackLeak();
} catch (Throwable e) {
System.out.println("stack length:" + leetCode.stackLength);
throw e;
}
}
  public void stackLeak() {
  stackLength++;
   stackLeak();
  }
}

  使用 -Xss参数,减小栈的内存容量。结果抛出StackOverFlowError异常。

  

JVM(一):Java内存区域与内存溢出异常的更多相关文章

  1. JVM内存区域与内存溢出异常

    Java虚拟机在执行java程序时会把它所管理的内存会分为若干个不同的数据区域,不同的区域在内存不足时会抛出不同的异常. >>运行时数据区域的划分 (1)程序计数器程序计数器(Progra ...

  2. JVM基础知识(1)-JVM内存区域与内存溢出

    JVM基础知识(1)-JVM内存区域与内存溢出 0. 目录 什么是JVM 运行时数据区域 HotSpot虚拟机对象探秘 OutOfMemoryError异常 1. 什么是JVM 1.1. 什么是JVM ...

  3. 深入理解jvm之内存区域与内存溢出

    文章目录 1. Java内存区域与内存溢出异常 1.1. 运行时数据区域 1.1.1. 程序计数器 1.1.2. java虚拟机栈 1.1.3. 本地方法栈 1.1.4. Java堆(Java Hea ...

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

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

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

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

  6. 第二章Java内存区域与内存溢出异常

    第二章 Java内存区域与内存溢出异常 一.概述 对与Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每个new操作去写delete/free代码,不容易出现内存泄露和内存溢出问 题, ...

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

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

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

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

  9. 2.1 自动内存管理机制--Java内存区域与内存溢出异常

    自动内存管理机制 第二章.Java内存区域与内存溢出异常 [虚拟机中内存如何划分,以及哪部分区域.什么样代码和操作会导致内存溢出.各区域内存溢出的原因] 一.运行时数据区域 Java虚拟机所管理的内存 ...

  10. 虚拟机--第二章java内存区域与内存溢出异常--(抄书)

    这是本人阅读周志明老师的<深入理解Java虚拟机>第二版抄写的,有很多省略,不适合直接阅读,需要阅读请出门左转淘宝,右转京东,支持周老师(侵权请联系删除) 第二章java内存区域与内存溢出 ...

随机推荐

  1. Python版的数据库查询构造器、ORM及动态迁移数据表。

    Orator Orator提供一个简单和方便的数据库数据处理库. 它的灵感来源于PHP的Laravel框架,借助其思想实现了python版的查询构造器和ORM. 这是完整的文档:http://orat ...

  2. XLua 基础

    一.Lua文件加载 1.Resources文件夹下加载  xxx.lua.txt  文件 1.)Resources加载xuaTest文件 // 1.Resources加载xuaTest文件 TextA ...

  3. 详细讲解MapReduce二次排序过程

    我在15年处理大数据的时候还都是使用MapReduce, 随着时间的推移, 计算工具的发展, 内存越来越便宜, 计算方式也有了极大的改变. 到现在再做大数据开发的好多同学都是直接使用spark, hi ...

  4. SpringBoot第五篇:整合Mybatis

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10869315.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   ORM框架 ...

  5. If,for,range混合使用笔记-(VBA视频教程2:使用IF进行逻辑判断)

    -- 新建表格:#单元格a1-a100全部等于1的代码 Sub test() Dim i As Integer For i = To Range( Next End Sub -- 新建表格:#单元格a ...

  6. ProtoBuf练习(三)

    任意类型 protobuf语言的任意字段类型相当于Boost库的boost::any类型数据,google.protobuf.Any是对protobuf语言的message进行封装,所以需要使用mes ...

  7. iscsi使用教程(中)

    服务端管理命令 ### tgtadm 是一个模式化的命令,其使用格式如下: # tgtadm --lld [driver] --op [operation] --mode [mode] [OPTION ...

  8. Linux系统及lvm知识

    一.磁盘分区是怎样表示的 IDE磁盘的设备文件采用/dev/hdx 来命名,分区则采用/dev/hdxy来命名,其中想表示磁盘(a是第一块磁盘,b是第二块磁盘,以此类推),与代表分区的号码(由1开始, ...

  9. cogs 915. 隐藏口令

    915. 隐藏口令 ★★☆   输入文件:hidden.in   输出文件:hidden.out   简单对比时间限制:1 s   内存限制:128 MB USACO/hidden(译 by Feli ...

  10. 浏览器Quirksmode(怪异模式)与标准模式

    由于历史的原因,各个浏览器在对页面的渲染上存在差异,甚至同一浏览器在不同版本中,对页面的渲染也不同.在W3C标准出台以前,浏览器在对页面的渲染上没有统一规范,产生了差异(Quirks mode或者称为 ...