1.java运行时数据区如图所示:

2.每个区域的功能

(1)程序计数器(寄存器)

当前线程所执行的字节码的行号指示器

为了线程切换后能够恢复到正确的执行位置,因此每个线程拥有自己独立的程序计数器

如果线程正在执行的是一个java方法,那么这个计数器记录的是正在执行的虚拟机字节码指令的地址

如果正在执行的是Native方法,这个计数器的值为空

这个区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

(2)java虚拟机栈

生命周期与线程相同

每个方法在执行的同时都会创建一个栈帧用来存储局部变量表、操作数表、方法出口等等。

(3)本地方法栈

源码中,很多的算法或者一个功能的实现,都被java封装到了本地方法中,程序直接通过调用本地的方法就行了,

本地方法就是用来存放这种方法的,可以是c或者c++等其它语言实现。

(4)堆

所有的线程共享这块内存区域,是虚拟机中最大的一块,用来存放对象实例

(5)方法区

所有线程共享这块内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、编译器编译后的代码等数据。

3、创建对象,在堆中开辟内存时是如何分配内存的?

两种方式:指针碰撞和空闲列表。我们具体使用的哪一种,就要看我们虚拟机中使用的是什么了。

指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存度放一边,空闲的内存放另一边,中间放着一个指针作为分界点的指示器,所分配内存就仅仅是把哪个指针向空闲空间那边挪动一段与对象大小相等的举例,这种分配方案就叫指针碰撞

空闲列表:有一个列表,其中记录中哪些内存块有用,在分配的时候从列表中找到一块足够大的空间划分给对象实例,然后更新列表中的记录。这就叫做空闲列表

4、对象引用是如何找到我们在堆中的对象实例的?     

这个问题也可以称为对象的访问定位问题,也有两种方式。句柄访问和直接指针访问。 画两张图就明白了。

句柄访问:Java堆中会划分出一块内存来作为句柄池,引用变量中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息

解释图:在栈中有一个引用变量指向句柄池中一个句柄的地址,这个句柄又包含了两个地址,一个对象实例数据,一个是对象类型数据(这个在方法区中,因为类字节码文件就放在方法区中),

      

直接指针访问:引用变量中存储的就直接是对象地址了,如图所示

解释:在堆中就不会分句柄池了,直接指向了对象的地址,对象中包含了对象类型数据的地址。

区别:这两种各有各的优势,

使用句柄来访问的最大好处就是引用变量中存储的是稳定的句柄地址,对象被移动(在垃圾收集时移动对象是很普通的行为)时就会改变句柄中实力数据指针,但是引用变量所指向的地址不用改变。

而使用直接指针访问方式最大的好处就是速度更快,节省了一次指针定位的时间开销,但是在对象被移动时,又需要改变引用变量的地址。在我们上面分析的例子中,就是使用的直接指针访问的方式。

5.OutOfMemoryError?

除了程序计数器区不会出现这个错误,其它的几个区都有可能出现这个错误。

(1)java堆溢出:只要不断的创建对象,并且保证GC Roots到对象之间有可达路径,就会在对象数量到达最大堆的容量限制后产生内存溢出异常。

当出现java堆内存溢出时怎么查修?

第一步:通过参数-xx:+HeapDumpOnOutOfMemoeyError可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆存储

快照以便事后进行分析。

第二步:通过内存映像分析工具(如Eclipse Memory Analyzer)对dump出来的堆转储快照进行分析,确认是不是内存泄漏导致的

第三步:如果是内存泄漏就需要通过与GC Roots的引用链定位到出现内存泄漏的地方,然后解决

第四步:如果不是内存泄漏,就看一下堆内存设置的大小,如果可以调大的话,就继续调大,然后就是从代码层面分析,看是否存在可以缩短对象生命

周期的地方,进行优化

(2)java虚拟机栈和本地方法栈溢出

可能是OutOfMemoryError,也可能是StackOverflowError

(3)运行时常量池溢出

可以通过配置修改相应的大小

(4)方法区溢出

1.java内存区域与内存溢出异常的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Scrum 项目6.0-展示Sprint回顾的过程及成果。

    6.0----------------------------------------------------- sprint演示 1.坚持所有的sprint都结束于演示. 团队的成果得到认可,会感觉 ...

  2. 20181120-6 Beta阶段第2周/共2周 Scrum立会报告+燃尽图 03

    此作业要求参见:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2411] 版本控制地址    [https://git.coding.n ...

  3. 作业三C++

    作业心得 1.本次作业开始使用C++编写了(面向过程的C++,2333) 2.粗略学习了一下文件输入输出,和项目的创建等(在大佬眼里最基本的操作QAQ,然而我还是有点晕晕的,平时都是ctrl+n新建源 ...

  4. 软工实践-Alpha 冲刺 (10/10)

    队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 完成所有界面的链接,整理与测试 展示GitHub当日代码/ ...

  5. HDU 5170 GTY's math problem 水题

    题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5170 bc(中文):http://bestcoder.hdu.edu.cn/contests ...

  6. erlang调优方法

    1. 来自Scaling Erlang的方法 内核调优: # Increase the ipv4 port range: sysctl -w net.ipv4.ip_local_port_range= ...

  7. get_list_by_where

    /** * 查询数据 * @param $param * @param bool $get_rows 或者总数 * @param bool $get_one 或者一条记录 * @param bool ...

  8. 【转】Linux C 网络编程——TCP套接口编程

    地址:http://blog.csdn.net/matrix_laboratory/article/details/13669211 2. socket() <span style=" ...

  9. 最大流算法-ISAP

    引入 最大流算法分为两类,一种是增广路算法,一种是预留推进算法.增广路算法包括时间复杂度\(O(nm^2)\)的EK算法,上界为\(O(n^2m)\)的Dinic算法,以及一些其他的算法.EK算法直接 ...

  10. [SCOI2016]幸运数字 线性基

    题面 题面 题解 题面意思非常明确:求树上一条链的最大异或和. 我们用倍增的思想. 将这条链分成2部分:x ---> lca , lca ---> y 分别求出这2个部分的线性基,然后合并 ...