文档章节

内存管理机制-内存模型与对象的访问

Garrry
 Garrry
发布于 2017/06/05 10:50
字数 1677
阅读 2
收藏 1
点赞 1
评论 0

 

RoadMap

 

虚拟机中的逻辑结构

虚拟机中的内存结构根据虚拟机规范划分出了五个常用区域,这些区域各自有各自的用途,有些随用户线程而存在,有些则随虚拟机进程而存在。 
五个区域分别为,虚拟机栈,本地方法栈,程序计数器,堆,方法区

 

程序计数器 (Program Counter Register, PCR)

程序计数器是随线程而生的,它是线程独立的,用来记录当前线程的字节码与指令,保证下一次线程唤醒之后,能回到正确的执行位置,说白了就是线程唤醒能继续执行。 
程序计数器是一块非常小的内存区域,也是唯一一个没有规定任何OutOfMemoryError的区域

虚拟机栈 (Virtual Machine Stack, VM Stack)

虚拟机栈也是线程私有的,它描述了Java方法执行的内存模型:每个方法被执行是都会创建一个帧栈(Stack Frame) 用于存储 局部变量表 操作数栈 动态链接 方法出口。每一个方法被调用直至执行完成的过程,就是对应着一个帧栈在虚拟机栈中从入栈到出栈的过程。 
局部变量表存放了编译期可知的基本类型和引用类型。 
在这个区域中,虚拟机规范规定了两种异常情况,StackOverflowError:当线程请求栈的深度大于虚拟机允许的深度,将会抛出此异常。 OutOfMemoryErro:当虚拟机栈在动态扩展长度时,无法申请到足够内存时将会抛出此异常

本地方法栈 (Native Method Stack, NM Stack)

本地方法栈与虚拟机栈发挥的作用非常类似,主要是为本地方法服务,虚拟机栈是为Java 方法服务的。 有些虚拟机实现 如 HotSpot 已经将NM Stack 和VM Stack 合二为一了

 

堆 (Heap)

heap 是java 虚拟机管理的内存中最大的一块,也是线程共享的。在虚拟机启动时 自动创建。 
除了JIT编译和逃逸分析技术下的对象,绝大多数的对象实例和数组都在堆上分配。 
同时 堆也是 垃圾收集器(Garbage Collection)主要工作的区域。 
如果堆中没有可分配的内存空间会抛出OutOfMemoryError

方法区

方法区与堆一样 是线程共享的,用于存储常量,静态变量,加载的类信息,即时编译的代码数据块。虽说 虚拟机规范把方法区化为堆的一部分,它却又一个别名non-heap,有意把它和堆区分开了,有些地方也把这地方称为,永久代,主要是因为把GC收集扩展至这个区域了或者说用永久代来实现方法区的功能。 
当方法去无法满足内存分配需求时,将会抛出OutOfMemoryError 
方法去主要存有: 
*类信息 
*类变量 
*类型常量池 
*方法信息 
String常量池便是其中之一。

直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java 
虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用,而且也可能导致 
OutOfMemoryError 异常出现,所以我们放到这里一起讲解。 
在JDK 1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel) 
与缓冲区(Buffer)的I/O 方式,它可以使用Native 函数库直接分配堆外内存,然 
后通过一个存储在Java 堆里面的DirectByteBuffer 对象作为这块内存的引用进行 
操作。这样能在一些场景中显著提高性能,因为避免了在Java 堆和Native 堆中来 
回复制数据。

堆中的分代划分

heap 中内存划分基于分代思想 主要分为 新生代,老年代和存活区。 

新生代 Eden

大多数情况下,对象在新生代中分配。当Eden区没有足够的空间的时候会发起一次MinorGC

老年代 Old Generation

大对象直接进入老年代,所谓大对象就是指需要大量连续内存空间的Java 对象,如数组,字符串等。 
同时基于分代思想,虚拟机给每个对象定义了一个对象年龄。当对象在Eden区经过MinorGC后还生存下来后,会被移动到Suivior Space中并记为年龄为1,并且在Suivior Space 每经过一次GC后 对其中存活的对象年龄加1,当对象年龄超过一定的阈值(默认为15)时,将会被移动到老年代。

存活区 Suivivor Space

存活区有点像青年代,用于那些新生代存活下来而未到达老年代的对象。 
同时 存活区分为From,to 两块空间相同的区域,作为复制回收算法的区域

如果只是按照对象年龄阀值来判断是否需要移动到老年代,难以应付多变的内存情况,加入在存活区有着非常大量的年轻对象(2,3,4,5,6,7岁等)以至于 存活区内存不太够用的情况。对于这种情况,survivor有一个动态年龄判定。在存活区中的相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就直接进入老年代。

对象访问方式

Object obj = new Object() 
Object obj 声明了一个引用对象 
new Object() 在堆中开辟了空间并生成对象 
所谓对象的访问方式是指,引用类型obj如何定位到堆中的具体对象Object()的。

虚拟机中主流的方式有两种直接指针和句柄池

句柄池

如果使用句柄访问方式,堆中会划分出一小块内存作为句柄池,reference存储的是对象的句柄地址,而句柄中包含了对象实例数据和各自数据的具体地址信息。优点在于,reference存储的是稳定的句柄地址,在对象被移动时,只会改变句柄中的实例数据指针,reference本身不需要改变。 

直接指针

如果使用饿了直接指针访问,reference中直接存储了对象的地址。次方式的优点在于节约对象访问方式,对于频繁的访问对象,直接指针节约了一个层级的访问时间。 

© 著作权归作者所有

共有 人打赏支持
Garrry
粉丝 20
博文 46
码字总数 48703
作品 0
浦东
技术主管
Java内存模型详解

内存模型 (memory model) 内存模型描述的是程序中各变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存取出变量这样的低层细节. 不同平台间的处理...

wersdffg ⋅ 2015/07/21 ⋅ 0

Android安全模型之介绍

从技术架构角度来看,Android安全模型基于强健的Linux操作系统内核安全性,通过进程沙箱机制隔离进程资源,并且辅以独特的内存管理技术与安全高效的进程间通信机制,适应嵌入式移动端处理器性...

柳哥 ⋅ 2014/11/30 ⋅ 0

Java 内存模型及GC原理

一个优秀Java程序员,必须了解Java内存模型、GC工作原理,以及如何优化GC的性能、与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统、实时系统等,只有全面提升内存的管理效...

长平狐 ⋅ 2013/01/06 ⋅ 0

JVM内存区域与多线程

Java并发的机制的背后是Java虚拟机(JVM)的工作机制,本文从几个关于并发和多线程的疑问开始,引出Java内存区域的介绍,希望能帮助大家更好的理解Java并发机制。 1. 线程创建和切换的代价—...

登高且赋 ⋅ 2017/12/08 ⋅ 0

Java 缓存框架--Imcache

Imcache是一个新的Java缓存库包,它支持各种已应用至今高速缓存模型。Imcache打算通过提供管理缓存数据的方法,以加快应用程序。它提供了从小型应用到大规模应用解决方案。 支持堆外off-hea...

欧德高 ⋅ 2014/01/24 ⋅ 0

Python内存管理机制

1 概述 对于Python这样的动态语言,如何高效的管理内存,是很重要的一部分,在很大程度上决定了Python的执行效率。与大多数编程语言不同,Python中的变量无需事先申明,变量无需指定类型,程...

guzhoujiexing ⋅ 2014/05/03 ⋅ 0

Java内存泄漏的理解与解决

Java内存管理机制 在C++语言中,如果需要动态分配一块内存,程序员需要负责这块内存的整个生命周期。从申请分配、到使用、再到最后的释放。这样的过程非常灵活,但是却十分繁琐,程序员很容易...

underA ⋅ 2013/09/16 ⋅ 1

ConcurrentHashMap实现机制

Java 内存模型 由于 ConcurrentHashMap 是建立在 Java 内存模型基础上的,为了更好的理解 ConcurrentHashMap,让我们首先来了解一下 Java 的内存模型。 Java 语言的内存模型由一些规则组成,...

zhangchd ⋅ 2015/04/28 ⋅ 0

Java多线程-带你认识Java内存模型,内存分区,从原理剖析Volatile关键字

写在前面(语句修改版) 读完本篇文章你将知道: Java的内存模型。 Java的内存分区。 全局变量、局部变量、对象、实例再内存中的位置。 JVM重排序机制。 JVM的原子性、可见性、有序性。 彻底...

那个人 ⋅ 2017/10/31 ⋅ 0

Android操作系统及内存管理

一、 操作系统 硬件体系 硬件是软件的基石,软件实现首先都是架构在硬件之上的,然后由此逐层不断抽象堆叠而成。所以要彻底理解软件,没有一定的硬件基础是不行的。 冯诺依曼结构如下。观点是...

liaowenhao ⋅ 2017/11/26 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring Cloud相关项目

Spring Cloud Config 配置管理工具包,让你可以把配置放到远程服务器,集中化管理集群配置,目前支持本地存储、Git以及Subversion。 Spring Cloud Bus 事件、消息总线,用于在集群(例如,配...

明理萝 ⋅ 30分钟前 ⋅ 1

更新队友POM文件后报错

打开报错的地方的pom及其引用方法所在文件的pom,观察其版本号是否一致,不一致进行更改

森火 ⋅ 36分钟前 ⋅ 0

IDEA使用sonarLint

一、IDEA如何安装SonarLint插件 1.打开 Idea 2.点击【File】 3.点击【Settings】 4.点击【Plugins】 5.在搜索栏中输入“sonarlint”关键字 6.点击【Install】进行安装 7.重启Idea 二、IDEA如...

开源中国成都区源花 ⋅ 41分钟前 ⋅ 0

Succinct Data Structure

作者:唐刘 最近看了一篇论文 SuRF: Practical Range Query Filtering with Fast Succinct Tries,里面提到使用一种新的数据结构 Succinct Range Filter(SuRF) 替换掉了 RocksDB 默认的 Bloo...

TiDB ⋅ 42分钟前 ⋅ 0

Java进阶之内存模型介绍

Java进阶之内存模型介绍 前言 不管在什么编程语言里面,读取和写入都是我们程序最普遍的操作,在单线程的程序里面我们可能不关注线程的读写问题,但是一旦到多线程的环境下,读和写就会变得非...

九劫散仙 ⋅ 43分钟前 ⋅ 0

在windows上搭建一个ftp服务器

一、关于ftp FTP 是File Transfer Protocol的英文简称,而中文简称为“文传协议”。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序。基于不同的操作系统有不同的FTP应用程序...

zctzl ⋅ 47分钟前 ⋅ 0

JDK8 排序

import java.util.Collections;import java.util.List;import java.util.ArrayList;import java.util.Comparator; public class JavaTest { public static void main(String......

Jeam_ ⋅ 57分钟前 ⋅ 0

api管理平台汇总

swagger crapApi RAP xxl-api apidoc

facula ⋅ 58分钟前 ⋅ 0

Java 11 快要来了,编译 & 运行一个命令搞定!

Java 11 马上要来了,原定于 9 月发布,还有不到 3 个月了,敬请期待更多新功能被加入到 11 当中,本文本讲的是 JEP 330 这个新特性。 化繁为简,一个命令编译运行源代码 看下面的代码。 //...

Java技术栈 ⋅ 今天 ⋅ 0

谷歌运营了一年多的无人出租车,得出了四条宝贵的经验

简评:并不是谷歌运营,不过国内对 Waymo 不敏感,就标题党了一下请多谅解。另外网友对于无人出租车是认可的,但是觉得如果价格没有优势,还是回去乘坐人类驾驶的汽车,毕竟这是人家的经济来...

极光推送 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部