自动内存管理机制之java内存区域与内存溢出异常
一、运行时数据区域
java虚拟机所管理的内存会包括下面的几个部分:
1.程序计数器:是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器。一般情况下,字节码解释器工作的时候就是通过改变计数器的之来选取需要执行的字节码指令。
(1)每条线程都有一个独立的程序计数器,每个线程都有一个独立的程序计数器,各个线程之间的计数器互不影响独立存储,这类内存区是线程私有的。
(2)此内存区域没有任何OutOfMemoryError的情况。
2.java虚拟机栈
(1)线程私有,生命周期与线程相同
(2)描述的是java方法执行的内存模型:每个方法在执行的时候都会创建一个栈帧,用于存储局部变量、操作数栈、动态链接、方法出口等信息,每个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
(3)java内存一般分法:堆内存(heap);栈内存。这里的栈就是虚拟机栈或者说是虚拟机中局部变量的部分。局部变量存放了各种基本的数据类型。局部变量所需的内存空间是在编译期完成分配的
(4)线程请求深度大于虚拟机所允许的深度,将会抛出StackOverflowError异常;
如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。
3.本地方法栈(Native Method Stack)
(1)本地方法栈与虚拟机栈所发挥的作用是非常相似的,区别是:虚拟机栈为虚拟机执行java方法服务,本地方法栈则为虚拟机使用到的Native方法服务
4.java堆(java Heap)
(1)java虚拟机中管理内存中最大的一块。被所有线程贡献的内存区域,在虚拟机启动的时候创建。java堆得唯一目的是存放对象实例,几乎所有的对象实例都在这里分配内存。
(2)java堆是垃圾收集器管理的主要区域,很多时候被称为GC堆。分代收集算法划分java堆:新生代和老年代,Eden空间、From Survivor空间、To Survivor空间。在java堆中无论怎么划分空间,存放的都是对象实例。对java堆进一步划分的目的是为了更好的回收内存。
(3)java堆可以处于物理上不连续的内存空间,只要逻辑上连续就可以,当前主流的虚拟机都是可以扩展的。
5.方法区
(1)各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、编辑器编译后的代码等。
(2)方法区有个别名:Non-Heap(非堆)。不连续内存和可以选择固定大小或者可扩展,还可以不识闲垃圾收集
6.运行时常量池(Runtime COnstant Pool):方法区的一部分
7.直接内存
三、HotSpot虚拟机对象探秘
1.对象的创建。
(1)对象的创建过程:首先检查指令的参数是否能在常量池中定位到一个类的符号的引用,并且检查这个符号的引用代表的类是否已被加载、解析和初始化过。如果没有那就先要执行相应的类加载的过程。
(2)为新生对象分配内存:在类加载完成后,对象所需的内存大小就可以完全确定。内存分配方式是指针碰撞。
2.对象的内存布局
(1)对象在内存中的布局分为3块区域:对象头(Header)、实例数据(Instance Data)和对其填充(Padding)
(2)对象头包括两部分:第一部分是存储对象自身的运行时数据;第二部分时类型指针,虚拟机通过这个指针确定对象是哪个类的实例。
(3)实例数据是对象真正存储有效信息,即在程序代码中定义的各种类型的字段内容。
3.对象的访问定位
(1)目前主流的访问方式是有使用句柄和直接指针两种。
(2)句柄访问。java堆中会划出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。这种方式的好处是reference中存储的是稳定的句柄地址,在对象被移动的时候只会改变句柄中实例数据指针,而reference本身不会修改
四、OutOfMemoryError异常
1.java堆溢出
(1)只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量达到最大堆得容量限制之后就会产生内存溢出异常,如下所示的代码中
import java.util.ArrayList;
import java.util.List; public class HeapOOM {
static class OOMObject{}
public static void main(String[] args){
List<OOMObject> list = new ArrayList<>();
while(true){
list.add(new OOMObject());
}
}
}
//java堆内存溢出的时候,异常信息是
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
对于上面的问题,要解决堆内存溢出的问题,一般手段是通过内存分析工具堆溢出的堆转储快照进行分析。如果时内存泄漏就找出相应的位置;如果不存在内存的泄漏,就应该检查虚拟机的堆参数,与机器的物理内存看看是否还可以继续调大。
2.虚拟机栈与本地栈溢出
(1)栈容量的设置:由-Xss参数设定。
(2)关于虚拟机栈和本地方法栈有两种异常:
线程请求的栈深度大于虚拟机所允许的最大深度,就会抛出StackOverflowError异常(栈空间太小还是已经使用的栈空间太大?)
如果虚拟机在扩展栈的时候无法申请到足够的内存空间,那么会抛出OutOfMemoryErroer异常()
public class JavaVMStackSOF {
private int stackLength=;
public void stackLeak(){
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable{
JavaVMStackSOF oom = new JavaVMStackSOF();
try {
oom.stackLeak();
}catch (Throwable e){
System.out.println("stack length"+oom.stackLength);
} }
}
//在单个线程的情况下,无论是栈帧太大还是虚拟机容量太小,当内存无法分配的时候,虚拟机跑出的都是StackOverflowError
3.方法区和运行时常量池溢出
4.本机直接内存溢出
自动内存管理机制之java内存区域与内存溢出异常的更多相关文章
- 【iOS开发-35】有了ARC内存管理机制,是否还须要操心内存溢出等问题?——面试必备
答案:必需要操心啊,ARC也不是万能的. 这里主要是涉及到集合类的数据类型. 比方数组,我们定义了一个可变数组muarr1,然后把一个对象p1加到muarr1中,此时会对这个对象retain一次,相当 ...
- Linux内存管理机制简析
Linux内存管理机制简析 本文对Linux内存管理机制做一个简单的分析,试图让你快速理解Linux一些内存管理的概念并有效的利用一些管理方法. NUMA Linux 2.6开始支持NUMA( Non ...
- 从内存管理原理,窥探OS内存管理机制
摘要:本文将从最简单的内存管理原理说起,带大家一起窥探OS的内存管理机制,由此熟悉底层的内存管理机制,写出高效的应用程序. 本文分享自华为云社区<探索OS的内存管理原理>,作者:元闰子 . ...
- JVM自动内存管理机制——Java内存区域(下)
一.虚拟机参数配置 在上一篇<Java自动内存管理机制——Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...
- JVM自动内存管理机制——Java内存区域(上)
一.JVM运行时数据区域概述 Java相比较于C/C++的一个特点就是,在虚拟机自动内存管理机制的帮助下,我们不需要为每一个操作都写像C/C++一样的delete/free代码,所以也不容易出现内存泄 ...
- 【深入理解Java虚拟机】自动内存管理机制——内存区域划分
Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...
- 2.1 自动内存管理机制--Java内存区域与内存溢出异常
自动内存管理机制 第二章.Java内存区域与内存溢出异常 [虚拟机中内存如何划分,以及哪部分区域.什么样代码和操作会导致内存溢出.各区域内存溢出的原因] 一.运行时数据区域 Java虚拟机所管理的内存 ...
- 【深入理解Java虚拟机】自动内存管理机制——垃圾回收机制
Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...
- 深入理解Java虚拟机(自动内存管理机制)
文章首发于公众号:BaronTalk 书籍真的是常读常新,古人说「书读百遍其义自见」还是很有道理的.周志明老师的这本<深入理解 Java 虚拟机>我细读了不下三遍,每一次阅读都有新的收获, ...
随机推荐
- [CSP-S模拟测试]:硬币(博弈论+DP+拓展域并查集)
题目传送门(内部题135) 输入格式 第一行包含一个整数$T$,表示数据组数. 对于每组数据,第一行两个整数$h,w$,表示棋盘大小. 接下来$h$行,每行一个长度为$w$的字符串,每个位置由为$o, ...
- BootStrap之X-editable插件使用
项目背景 刚加入公司的新项目,主要在做开发工作.由于是新手,本周的工作是配合另外一个同事写前台页面.前台框架是Bootstrap,本文主要介绍一下项目需求的一个功能——表格行内编辑事件. 使用X-ed ...
- LeetCode 55. 跳跃游戏(Jump Game)
题目描述 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个位置. 示例 1: 输入: [2,3,1,1,4] 输出: ...
- DeepFaceLab:手动提取高精度脸图,减少抖动!
DeepFaceLab默认情况下都都是自动提取脸部,整体来说效果不错,脸部曲线识别度也比较高.但是自动不是万能的,有些图片的轮廓识别并不好.而识别不好最直接的结果就是合成的视频可能会出现抖动. 也就是 ...
- [flask]jinjia2-模板 url_for的使用
url_for是什么? url_for()用于生成URL的函数,是Flask内置模板的1个全局函数 url_for()用来获取URL,用法和在Python脚本中相同.url_for的参数是视图的端点( ...
- 通过BDC批量修改物料文档信息 MM02
*&---------------------------------------------------------------------* *& Report ZMM_03 * ...
- java: (正则表达式,XML文档,DOM和DOM4J解析方法)
常见的XML解析技术: 1.DOM(基于XML树结构,比较耗资源,适用于多次访问XML): 2.SAX(基于事件,消耗资源小,适用于数量较大的XML): 3.JDOM(比DOM更快,JDOM仅使用具体 ...
- eventfd(2) 结合 select(2) 分析
本文代码选自内核 4.17 eventfd(2) - 创建一个文件描述符用于事件通知. 使用 源码分析 参考 #include <sys/eventfd.h> int eventfd(un ...
- C++编译错误提示 [Error] name lookup of 'i' changed for ISO '
在VC 6 中,i的作用域范围是函数作用域,在for循环外仍能使用变量i 即: for (int i = 0; i < n; ++i) { //…… } cout<< ...
- 使用 Python* 的英特尔® 分发版实现 Unity* 机器学习入门(第 1 部分)
本文将向游戏开发人员介绍如何使用强化学习创建更好的人工智能 (AI) 行为.使用Python* 的英特尔® 分发版 — 常用面向对象的高级编程语言的进阶版 — 读者可收集关于如何训练预先存在的机器语言 ...