一、jvm内存模型整体图
二、概念
栈、
1、.class文件是什么不多解释了, 作为java程序员肯定是在脑海里根深蒂固的(排除字节码文件如何解读,只是单纯的理解.class文件是做什么的)。
2、装载子系统:简单说就是加载器,上一篇博文已经复习到。
3、运行时区域中的线程独享区,栈、本地栈以及程序计数器。
栈: 每个线程都会在内存中开辟一块栈空间(线程独享),每个方法又会分配各自的栈帧,栈帧分为:局部变量表、操作数栈,动态连接以及方法出口。
局部变量表: 存放代码中局部变量。
操作数栈:当一个方法刚刚开始执行时,其操作数栈是空的,随着方法执行和字节码指令的执行,会从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者,也就是出栈/入栈操作。一个完整的方法执行期间往往包含多个这样出栈/入栈的过程。
动态连接:比如:运行时调用某个方法时,才会进行加载,在方法区中运行时常量池分配内存地址指向这个引用。
方法出口:记录者一个方法执行完毕后,返回到调用者调用这个方法的下一行准备要执行代码的位置,也就是保护现场,保护调用方法前的现场(白话叙述,好理解)
根据上面java代码和class字节码我们分析下面(栈)流程图
1、Java代码中又一个main方法,当每个线程进来后,jvm就会给当前线程开辟一块栈空间(注:有多少线程就会开辟多少个栈空间)
2、每个方法都会在栈中生成各自栈帧;(局部变量表、操作数栈、动态连接、方法入口)(先进后出的规则)mian方法(栈帧先进后出),comoute方法(栈帧后进先出)
3、查看class字节码文件与Java代码我们来分析下面的步骤(jvm字节码指令百度查)(我们通过compute()方法来分析)
第一步: 0: iconst_1 将int类型常量1压入操作数栈;
第二步: 1: istore_1 将int类型值存入局部变量a;
第三步: 2: iconst_2 将int类型常量2压入操作数栈;
第四步: 3: istore_2 将int类型值存入局部变量b;
第五步: 4: iload_1 从局部变量1中装载int类型值;(这个1是局部变量表中索引)
第六步: 5: iload_2 从局部变量2中装载int类型值;(这个2是局部变量表中索引)
第七步: 6: iadd 执行int类型的加法;
第八步: 7: bipush 10 将一个8位带符号整数压入栈;
第九步: 9: imul 执行int类型的乘法;
第十步:10: istore_3 将int类型值存入局部变量c;
第十一步:11: iload_3 从局部变量3中装载int类型值;(这个3是局部变量表中索引)
第十二步:12: ireturn 从方法中返回int类型的数据 (这部不用多说了,就是把c=30 return返回)
(说白了 操作数栈 就是给一些运算值进行运算的临时内存空间中转站)
上面的十二步骤和图就是解释了局部变量和操作数栈的关系
本地栈、
调用本地方法,c++编写的代码时会开辟本地栈(native修饰的方法),同时它也是线程独占,一个线程开辟一块栈空间 ;
程序计数器、
程序计数器也是线程独享的,主要就是记录当前线程执行代码的的位置(那class字节码文件来分析)
方法区、
方法区,存放的类信息,静态变量,常量
堆、(这块内容挺多,下一文章在复习记录)
本人工作3年中级菜鸟程序员, 最近想回顾一下知识,做了一些简单总结同时也为了自己今后复习方便,如果有逻辑错误,大家体谅,同时也希望大牛们能给出正确答案让我改正,谢谢!
原文:https://www.cnblogs.com/ryaisxj1314/p/14279657.html