上一篇玩完类加载器、双亲委派机制之后,咱们知道了:
-
类加载器就是用来将类整理验证…,然后将字节码文件送到JVM去处理
- (记得咱们的民政&局小故事嘛,说白了类加载器就是一个贴心中间处理机构,怕你送到JVM的东西:
- 有可能太大了
- 有可能携带啥病毒
- 有可能格式不正确,不符合jvm处理规范
- 有可能得先进行初始化赋值等操作处理一下才能继续往下送等等
- …
- (记得咱们的民政&局小故事嘛,说白了类加载器就是一个贴心中间处理机构,怕你送到JVM的东西:
-
双亲委派机制,就是用来保证安全的,至于具体工作过程以及实际分类等知识,敬请收看上一篇,保证有所收获:玩转~类加载器&双亲委派机制
话说字节码文件进入到java内存(运行时数据区域)中,咱擅闯龙潭是不是得先知道龙潭里面的分布是怎样的吧。
- 哪里有鳄鱼潭?
- 哪里有会把人吸进去的沼泽地?
- 哪里有毒区?
为了保命并能顺利闯关成功,所以咱们得先扒光java内存区域。
大家都知道,从电脑的角度讲:
- 进程,当咱们用咱们的window10(或其他版本…)启动一个应用程序或者叫应用,就相当于启动了一个进程。一个进程中有好多线程。
- 线程大小可以想象成为迷你版的进程,是由进程中千千万万个线程来执行自己寄宿的进程里面的各个应用程序的任务的。(比如说咱们启动了QQ,那就相当于启动了一个QQ_进程,对吧。然后当咱们在qq中同时挂着qq邮箱,又打开消息和qq好友聊天时,那么qq邮箱和聊天窗口可以说是由两个线程处理的…)。大家就记得最终线程是用来执行具体任务的,是个打手。
当然,java内存区域(运行时数据区域)里面的打手(线程)也肯定会有自己的一些私人领人区域,别的进入java内存中的东东或者西西是不能随便访问和乱动的,比如:
- 程序计数器(相当于打手房间墙上挂的一个屏幕,上面不间断滚动播放着,这个打手明天去干谁、后天去干哪个对手(这里的干指的是线程执行任务哦))
-
java虚拟机栈,这个相当于打手的一个储物柜(大超市里面那种分好多小柜子那种),里面的每个小柜子就叫做栈帧Frame
- 每个java方法在执行时都会为自己创建一个栈帧,用来存储线程私有的局部变量(表)、操作数栈、常量池引用等。(大家可以理解成为打手用来记录自己哪天打哪个对手,要用的不同的拳击手套、穿的衣服、牙套的不同尺寸大小以及存放的位置等等,说不定扔到哪里去了,找不到不就糟了)
- 栈帧在java虚拟机栈中入栈到出栈刚好对应于这个方法从调用到执行完成的过程。
- 本地方法栈。这个是打手在自己私有内存区域中专门开辟的,用来登记native方法(相当于打手虽然肌肉发达,但是人家可是很细心的哟,人家给自己私有领地中开辟了一个小空间,用来放他借用别人的手套呀、衣服呀这些工具(下面也会再将,因为java有时会调用到C、C++等语言写的其他方法,这些不是你java写的(对于我这个java从业者而言哈)方法而是别人写的方法就是本地方法))
(图片里面的字大家也可以好好看看,都是正经文字)
买一个图赠送一个图
Notes:大家可能也听过这个PC程序计数器,此处可以解释一下为什么将程序计数器设置为私有的。OS将CPU之外的其他资源分配给了进程,而单独把CPU资源分配给了线程(因为线程是来执行任务的打手,进程又不具体执行任务,CPU给你干啥)。线程们是通过时间片轮转的方式来轮流占用并使用CPU的(那CPU分配给线程们你一个他一个时间片让去按照时间片执行任务,但是线程的任务不一定在指定时间内执行完毕,执行到一半有可能就被CPU喊出去了让另一个线程按照自己的时间片接着执行,这是不是线程们在不断切换呀)。比如打手在每个关卡指定时间内打倒不同的敌人就可以闯关,但是打到一半时间到了,CPU得找个线程私有的地方(就是程序计数器)来记录某个线程让出CPU时之前的执行地址,待再次该线程被分配到时间片时该线程就可以从自己私有的计数器存的指定地址继续执行,继续打人闯关。
- 至于说为什么要把这个记录上次结束时线程执行到哪里的地方设置为私有的,我个人觉的可能就是方便或者安全,自己心里的小九九嘛,放自己心里合适。如果有其他原因希望大家评论供我学习一下,灰常感谢。
- 这里执行的任务,就是java代码指令
- 如果正在执行的是本地方法(人家别人写的方法),那么程序计数器则为空,记录undefined
总体而言,人家这个打手自理能力还是比较强的,人家比赛呀、闯关呀完成后,人家会把自己私有的:
- 用来记录自己要闯关或者比赛的对手、地址等信息的大屏幕,人家会每天自己更新一下、维护一下、擦洗一下,不用别人帮我打扫处理
- 自己存货的有很多小柜子的大储物柜,人家会每天自己更新一下、维护一下、擦洗一下,不用别人帮我打扫处理
- 还有自己私有领地中开辟的一个小空间(用来放他借用别人的手套呀、衣服呀这些工具),人家会每天自己更新一下、维护一下、擦洗一下,不用别人帮我打扫处理
当然,说完了打手(线程)的私有领地,得说说打手们可以共享的领地了。(可能不全,希望大家评论区指正,共勉)
-
堆(Heap)
- 这个领地,一个字,大,两个字,真大,三个字,他很大。不错, 堆是进程中最大的一块内存(进程是线程寄存的地方,别忘了哦。)。我愿称堆为打手们的拳台,懂我的意思吧,你不大点都站不下打手们咋打。
- 堆这个领地是在进程创建时分配的
- 所有实例化出来的对象(类中的方法、常量)都在队内分配内存
- 这个舞台,打手们刚相互打完,也都没力气了,那舞台上舞台下打出来的汗渍、xue迹、用过的脏牙套、脏毛巾、脏衣服、脏水杯…,这个舞台也算是一个主要的垃圾来源,得让别人帮我打扫处理了,来回收一下相关的垃圾。
买一个图赠送一个图
-
方法区
- 民政&局办完事的剩下来的材料废物:那些信息呀、证书呀、照片呀、文字呀啥的都放在这块区域里面(这块不太理解可以看看这篇,保证你恍然大悟玩转~类加载器&双亲委派机制)
- 用于存放已被加载的类的类信息(构造方法、接口定义等)、常量、静态变量(类变量,也就是static修饰的变量)、运行时的常量池、即时编译器编译后的代码等数据。(现在知道咱从民政&局出来后,原来咱们小胡和言小敏这对夫妻以及其他的新人们被人家民政&局是当作一个一个类的呀,新人办理结婚证时在局子里面涉及到的那些信息呀、证书呀、照片呀、文字呀,都跑哪去了,都放到方法去里面来了)
老规矩,买一赠一
说到这,大家就知道,
-
我打手(线程)私有的三个区域我自己打扫处理好,不用别人帮我打扫。
-
然后拳台(堆)、方法区(民政&局办完事的剩下来的材料废物啥的)需要专人帮我打扫一下,
- 因为呀,新人办理结婚证时在局子里面涉及到的那些信息呀、证书呀、照片呀、文字呀;舞台上舞台下打出来的汗渍、xue迹、用过的脏牙套、脏毛巾、脏衣服、脏水杯…太多了,只能别人帮我打扫,别人比我专业,自己的私人领地扫不好也没啥大关系,拳台以及民政&局办完事的剩下来的材料废物啥的得专人来处理好。
- 当然,很明显,大部分要回收的还是在堆里面(打手的垃圾占整个回收过程的90%左右哟)
- 因为呀,新人办理结婚证时在局子里面涉及到的那些信息呀、证书呀、照片呀、文字呀;舞台上舞台下打出来的汗渍、xue迹、用过的脏牙套、脏毛巾、脏衣服、脏水杯…太多了,只能别人帮我打扫,别人比我专业,自己的私人领地扫不好也没啥大关系,拳台以及民政&局办完事的剩下来的材料废物啥的得专人来处理好。
当然,这是java内存中的剩余的最后一块领地,还没说呢:
- 直接内存(直接上图,大家看看即可)
ps.上面不是提到了咱们打手会调用到别人C或者C++写的一些拳套呀、牙套呀等工具(本地方法)等等,这些就是这么实现的,一句话:
-
线程私有的本地方法栈里面发起调用,通过本地接口调用本地方法库(库嘛,就是存别人牙套】拳套的库呀)里面的本地方法,让咱们这个打手使用自己原来没有的东西。
大家有兴趣想了解更详细一点,可以看看下面我画好的框图。
大体上了解java内存之后,你光说专人专人来帮我们打扫拳台(垃圾多)和民政&局剩余垃圾(垃圾少)
- 到底是谁来帮咱们打扫呀?
- 他咋扫呢?我不信我扫不过他!
下集再见,今天写多了,看都不想看了,这么多,谁想往下一直翻…(白眼一个,言小敏最喜欢的那个翻给小胡的那个白眼)