程序员登高之路——JAVA篇——1.JVM内存区域

程序员登高之路——JAVA篇——1.JVM内存区域

内存区域的组成

运行时数据区1.堆: 线程公有,对象实例的主要存放区域,也是GC的主要区域。
2.JAVA虚拟机栈: 线程私有,由栈帧构成,运行时生成的对象的引用存放区。
3.方法区: 又称为非堆,线程公有,存储已被虚拟机加载的类信息,常量,静态变量。
4.程序计数器: 线程私有,占用内存非常小,负责记录当前线程应执行的下一条字节码指令的位置,在当前线程被激活时,程序将从程序计数器记录的字节码指令继续执行。
5.本地方法栈: JVM运行本地方法的栈,功能与虚拟机栈类似。

详细说明:

JAVA虚拟机栈:

每个方法在运行时都会创建一个栈帧,栈帧在虚拟机栈中的入栈出栈对应着一个方法的开始和结束。如:

// 简单的方法调用
public static void A(){ B(); }

public static void B(){ C(); }

public static void C(){ ... }

在上面这段示例中,方法A调用了方法B,方法B又调用了方法C。那么此时虚拟机栈的结构如图
调用方法C后的虚拟机栈当方法C运行完后:
方法C运行完后的栈帧

栈帧的组成:

栈帧由四部分组成:
1.局部变量表: 一组变量值存储空间,用来存储方法的参数和方法内声明的变量(若为实例方法也会存本对象的实例引用this),以slot为最小单位,一个slot最多32位大小,对于long和double这种64位的类型,需要两个slot才可以存储,局部变量表所需的大小在编译时期就可以确定。
2.操作数栈: 大小也可在编译时期确定,在字节码执行时,用于充当运算以及传递参数的中介。有的虚拟机会令下面栈帧的操作数栈(如上面示例的A)和上面栈帧(如示例中的B)的局部变量表部分重合,以达到共用部分数据,避免参数传递。在方法执行完成后,也会将返回值压入方法调用方的操作数栈。
3.动态链接: 当前栈帧指向运行时常量池中该栈帧所属方法的引用,目的是为了支持方法调用中的动态链接。
上面是《深入理解JAVA虚拟机》中的定义,不是很懂,感觉是为了实现方法重写而存在
4.返回地址: 方法运行结束可能会有两种情况,其一是方法正常运行结束,其二是运行时出现了异常,导致方法结束。正常退出时,返回地址由程序计数器确定。异常退出时,返回地址由异常处理器来确定。

堆:

就像上面简介所说,堆是对象实例的主要生成区域。请一定要记住这个"主要"。在java1.7之后,已经默认开启了逃逸分析,逃逸分析允许无法逃出本方法的对象直接在栈中生成。

// 逃逸分析示例
public static Object example(){
	Object obj1 = new Object();
	Object obj2 = new Object();
	return obj2;
}

在上面的代码示例中,若开启了逃逸分析,则obj1会在栈帧中生成,obj2由于会将引用返回,所以JVM会认为obj2所引用的对象发生了逃逸,obj2的对象就会在堆中生成。因为对象obj1会直接生成在栈帧中,所以在方法结束后,obj1就会随着栈帧的出栈而消失。
逃逸分析相当于为GC分担了压力,不过对于会逃逸的对象如obj2,相当于做了一次无用功。对于是否开启逃逸分析,还是应该结合实际情况。

方法区:

用于存储已被虚拟机加载的类信息、常量和静态变量等数据,详细会在后面某章写。

第一次写文章,文笔不好还请多多包含,如有错误,欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值