文档章节

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

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

 

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
粉丝 22
博文 46
码字总数 48703
作品 0
浦东
技术主管
再有人问你Java内存模型是什么,就把这篇文章发给他!

前几天,发了一篇文章,介绍了一下JVM内存结构、Java内存模型以及Java对象模型之间的区别。有很多小伙伴反馈希望可以深入的讲解下每个知识点。Java内存模型,是这三个知识点当中最晦涩难懂的...

技术小能手
09/30
0
0
Java 内存模型及GC原理

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

长平狐
2013/01/06
155
0
Android安全模型之介绍

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

柳哥
2014/11/30
0
0
再有人问你Java内存模型是什么,就把这篇文章发给他。

前几天,发了一篇文章,介绍了一下JVM内存结构、Java内存模型以及Java对象模型之间的区别。有很多小伙伴反馈希望可以深入的讲解下每个知识点。Java内存模型,是这三个知识点当中最晦涩难懂的...

Java架构
07/11
0
0
Java 缓存框架--Imcache

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

欧德高
2014/01/24
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

一个可能的NEO链上安全随机数解决方案

0x00 困境 链上安全随机数生成应该算是一个比较蛋疼的问题,哪怕你的系统再牛逼,合约程序困在小小的虚拟机里,哪怕天大的本事也施展不开。 更悲催的是,交易执行的时候,是在每一个节点都执...

暖冰
22分钟前
0
0
【大福利】极客时间专栏返现二维码大汇总

我已经购买了如下专栏,大家通过我的二维码你可以获得一定额度的返现! 然后,再给大家来个福利,只要你通过我的二维码购买,并且关注了【飞鱼说编程】公众号,可以加我微信或者私聊我,我再...

飞鱼说编程
今天
1
0
Spring5对比Spring3.2源码之容器的基本实现

最近看了《Spring源码深度解析》,该书是基于Spring3.2版本的,其中关于第二章容器的基本实现部分,目前spring5的实现方式已有较大改变。 Spring3.2的实现: public void testSimpleLoad(){...

Ilike_Java
今天
1
0
【王阳明心学语录】-001

1.“破山中贼易,破心中贼难。” 2.“夫万事万物之理不外于吾心。” 3.“心即理也。”“心外无理,心外无物,心外无事。” 4.“人心之得其正者即道心;道心之失其正者即人心。” 5.“无...

卯金刀GG
今天
2
0
OSChina 周三乱弹 —— 我们无法成为野兽

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ _刚刚好: 霸王洗发水这波很骚 手机党少年们想听歌,请使劲儿戳(这里) hahahahahahh @嘻酱:居然忘了喝水。 让你喝可乐的话, 你准忘不了...

小小编辑
今天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部