JVM学习笔记一——内存区域

作者: tcxurun 分类: Java 发布时间: 2014-03-10 22:48 ė 6 没有评论

JVM是java知识体系的基石之一,任何一个java程序的运行,都要借助于他。或许对于我这种初级程序员而言,工作中很少有必要刻意去关注JVM,然而如果能对这块知识有所了解,就能够更清晰的明白程序的运行机制,从而写出更为健壮的代码,也能更好的理解java中很多处理方式的原因。周志明的深入理解Java虚拟机刚出版的时候就买了,可是一直没有看,中间偶尔抽空翻了一下,但是一直没有认真系统的看,现在终于决定来认真系统看一下,战胜拖延症,从现在开始。jvm知识比一般java相关知识还要枯燥,刘未鹏说过:书写是为了更好的思考。虽然我这个只能算笔记,但是比默默看书效果应该要好。准备把看这本写一系列读书笔记。

一、Java内存区域与内存溢出异常

jvm

1、程序计数器:是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器。Java每个线程都有一个独立的程序计数器,故称为“线程私有”内存。
(Java虚拟机规范中没有规定任何OutOfMenmoryError情况的域)
2、Java虚拟机栈:描述的是Java方法执行的内存模型。每个方法被执行的时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。有两种异常状况:(1):如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;(2)如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),当扩展无法申请到足够的内存时会抛出OutOfMemoryError异常。
3、本地方法栈:为虚拟机使用到的Native方法服务,有的虚拟机(如Sun HotSpot虚拟机)直接把本地方法栈和虚拟机栈合二为一。异常同java虚拟机栈。
4、Java堆:Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。虚拟机规范中描述:所有的对象实例以及数组都要在堆上分配。(JIT技术:栈上分配、标量替换优化技术导致一些 变化,这句话不再“绝对”)Java堆还可以细分为新生代和老年代。(新生代可以分为Eden空间、From Survivor空间、To Survivor空间)如果堆中没有内存完成实例分配,并且堆也无法再扩展,将会抛OutOfMemoryError异常。
5、方法区(Method Area):与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后代码等数据。异常:OutOfMemoryError。
6、运行时常量池:是方法区的一部分。Class文件中的常量池,用于存放编译期生成的各种字面量和符号引用。运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性。利用的比较 多的是String类的intern()方法。受到内存限制,因此会抛出OutOfMemoryError异常。
7、直接内存:不会受到Java堆大小的限制,但受到本机总内存限制,会抛出OutOfMemoryError异常。

二、对象访问

主流的访问方式有两种:使用句柄和直接指针。
1、句柄访问方式:Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体的地址信息。

jvm2
2、指针访问方式:java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的是对象地址。
使用句柄好处是存储的是稳定的句柄地址,在对象被移动的时候只需要改变句柄中实例数据指针,而reference本身不需要被修改;
使用直接指针访问方式的最大好处就是速度更快,节省了一次指针定位的时间。(Sun HotSpot使用此种方式)。

本文出自天一直很蓝,转载时请注明出处及相应链接。

本文永久链接: http://www.tcxurun.cn/archives/112

0

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Ɣ回顶部