文档章节

01 Java 内存区域

fokYaland
 fokYaland
发布于 2015/06/04 17:26
字数 1398
阅读 34
收藏 1
     Java虚拟机在执行Java程序的过程中 会把它所管理的内存划分为若干个不同的数据区域。

程序计数器,是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器在虚拟机的概念模型里,字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。由于Java虚拟机的多线程是通过线程轮流切换实现的。为了保证线程切换后能恢复到正确的执行位置, 每条线程都需要有一个独立的程序计数器。如果正在执行的是java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果执行的是Native方法,这个计数器值为空。此内存区域是唯一一个没有OutOfMemoryError的区域。

Java虚拟机栈  是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧用于存储 局部变量表操作栈动态链接方法出口等信息。每一个方法被调用直至完成的过程,就对应一个栈帧在虚拟机栈中从入栈到出栈的过程。

通常说的Java内存分为 堆内存(Heap)栈内存(Stack), 这里的栈内存,其实就是 虚拟机栈中的局部变量表

局部变量表存放了编译期可知的各种 基本数据类型对象引用returnAddress类型(指向了一条字节码指令的地址)。

其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型只占用1个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

这个区域规定了两种异常情况:如果线程请求的栈深度大于虚拟机所运行的深度,将抛出 StackOverflowError;如果虚拟机栈可以动态扩展(当前大部分都可以),当在扩展时无法申请到足够的内存时会抛出 OutOfMemoryError

本地方法栈,与虚拟机栈的作用相似,区别是本地方法栈为虚拟机使用到的Native方法服务。虚拟机规范中对本地方法栈没有强制规定,具体的虚拟机可以自由实现,有的虚拟机甚至直接把本地方法栈和虚拟机栈合二为一。

Java堆 是虚拟机所管理的内存中最大的一块。java堆被 所有线程共享,在虚拟机启动时创建。此区域的目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。

Java堆是垃圾收集器管理的主要区域,从内存回收角度看,由于现在收集器基本都采用 分代收集算法,Java堆还可以细分为: 新生代老年代;再细致点有 Eden空间From Survivor空间, To Svrvivor空间。

当前主流的虚拟机都支持对Java堆的扩展( -Xmx-Xms控制)

当在扩展时无法申请到足够的内存时会抛出OutOfMemoryError

方法区,与Java堆一样,是线程共享的。用于存放已被虚拟机加载的 类信息常量静态变量即时编译器编译后的代码等。对于在HotSpot虚拟机上,有很多人习惯把方法区成为“ 永久代”(Permanent Generation),是因为HotSpot中把GC分代收集扩展至方法区,或者说使用永久代来实现方法区。对于其他虚拟机(BEA JRockit,IBM J9等)是不存在永久代的概念的。

Java虚拟机规范对这个区域的限制非常宽松,垃圾收集行为在这个区域是比较少见的。这个区域的内存回收主要是针对 常量池的回收和对 类型的卸载,一般来说这个区域的回收成绩比较难以令人满意,尤其是类型的卸载,条件相当苛刻
这个区域也会抛出OutOfMemoryError。

运行时常量池  方法区的一部分,Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是 常量池,用于存放编译期生成的 各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

对象访问
即使是最简单的访问,也会涉及 Java栈Java堆方法区这三个最重要的内存区域,如下的语句
Object   obj   = new  Object();
假设这句代码出现在方法体中,那   Object obj  将会反映到Java栈的本地变量表中,作为一个 reference 类型数据出现。
new Object() 会反映在Java 堆中,形成一块存储了Object 类型所有实例数据值的结构化内存。另外关于此对象类型数据(对象类型,父类,实现的接口,方法)的地址信息,保存在 方法区的运行时常量池


本文转载自:http://blog.csdn.net/yanliang1/article/details/12794179

fokYaland
粉丝 4
博文 68
码字总数 3062
作品 0
东城
私信 提问
初探 JVM 运行时数据区域

笔者作为Java小菜鸡,近期在看JVM时发现自己很容易忘记JVM最基础的部分:运行时数据区域大致划分,特此摘记下来以便将来重温。 话不多说,先上示意图![Java Virtual Machine Memory ](https...

孤独的岛_Bin
2018/07/31
19
0
JVM内存结构 VS Java内存模型 VS Java对象模型

Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模型和...

Java架构
2018/07/11
0
0
JVM快速调优手册01:内存结构(堆内存和非堆内存)

图为Java虚拟机运行时的数据区: 1.方法区 也称"永久代” 、“非堆”, 它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。默认最小值为16MB,最大值为64MB(未验证)...

GordonNemo
03/28
8
0
深入学习Java虚拟机——虚拟机内存区域与内存溢出异常

运行时数据区域 1.1 程序计数器 1. 程序计数器是一段较小的内存空间,可以看作为当前线程所执行字节码的行号指示器。通过改变这个计数器的值来选取下一条字节码指令,分支、循环、跳转、异常...

江左煤郎
2018/07/20
26
0
JVM 运行时数据区简介及堆与栈的区别

理解JVM运行时的数据区是Java编程中的进阶部分。我们在开发中都遇到过一个很头疼的问题就是OutOfMemoryError(内存溢出错误),但是如果我们了解JVM的内部实现和其运行时的数据区的工作机制,...

大数据之路
2015/08/02
4K
1

没有更多内容

加载失败,请刷新页面

加载更多

Rust:最小化窗口后 CPU占用率高 (winit,glutin,imgui-rust)

最近试着用 imgui-rust 绘制界面,发现窗口最小化后CPU占用会增大。 查询的资料如下: https://github.com/rust-windowing/winit/issues/783 https://github.com/ocornut/imgui/issues/1151 ...

reter
30分钟前
10
0
cloud-zuul路由网关

九、zuul路由网关 概述 1.1 能干嘛 路由、过滤 路由基本配置 路由访问映射规则 十、springCloud config分布式配置中心

榴莲黑芝麻糊
30分钟前
14
0
Circuit Breaker模式

Circuit Breaker模式会处理一些需要一定时间来重连远程服务和远端资源的错误。该模式可以提高一个应用的稳定性和弹性。 问题 在类似于云的分布式环境中,当一个应用需要执行一些访问远程资源...

mskk
43分钟前
16
0
写论文之前的准备都有哪些?干货来了!

原文链接:https://www.lwfdy.com/archives/144.html 之前跟大家谈了许多有关于初稿修改以及写作事项需要注意的问题,那么今天我们来说一说,在写之前,我们需要做哪些准备呢,为了做到下笔如...

辅导员
49分钟前
11
0
idea快捷键

Alt + Enter 引入类 Ctrl + O 查看我们继承的类或者接口中的方法,以及我们要实现的方法 Ctrl + Alt + b 查看接口实现类中方法(就是我们使用接口编程时,在调用实现类方法处直接Ctrl+鼠标左...

行者终成事
57分钟前
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部