上面我们说了native这个关键字,我觉得我们学习jvm脑子里面一定要有这张图吧,根据这个图一个个学。
这次先看下程序计数器(也可以叫PC寄存器),我在学习这个的时候,可能是为了便于自己的理解吧,我是看成一个数组吧,虽然这个是错误的,但是有些就是便于自己理解吧。
程序计数器是一个内存比较小的空间,存放了线程当前所执行字节码的行号指示器。
因为我们都知道CPU是很忙的,我们都是多线程的执行的任务,不可能一直把资源全部放给一个线程去执行,其余的线程都在等待,所以CPU采用了线程轮流切换去执行线程,这时候有人可能有疑问,为什么我感觉我的任务执行的很快呢?没有感觉把资源给了别人线程啊,其实这个时间是很短的都是几百ms,甚至更短,所以我们察觉不出来是很正常的。
从上面我们也能明白一点点为什么需要这个程序计数器,比如我们现在有两个线程A和B,前提这两个线程或不干扰,A执行到了100行,这时候资源需要放行给B,如果我们没有这个程序计数器,当B执行完或者执行了一定的步数,又将资源给了A,这时候A又得从头开始执行,如果不幸的话,这时候又是执行到了100行,又把资源放行给了B,B也没有程序计数器,这时候很可能两者都在等。
个人觉得程序计数器吧,就是当A线程执行到了100行的时候,我们给他一个程序计数器,标注下我这次资源在我这里的时候,我执行到了100行,下次来就从100行开始在执行吧,同理B也是这样的,这也从侧面反应一个问题,程序计数器是线程私有的。
说完了这第一线程私有的,我们在来说说第二个线程私有的吧,那是啥呢?
我们先来看一个数据结构吧,栈(stack),记得我上课的时候,老师给我们讲的有关栈的例子就是大家都熟知的枪的弹夹,现在你需要上战场了,你肯定需要把弹夹里面装好子弹吧,你一颗颗的装,那个被你首先装进去的第一颗的子弹,被第二颗,第三颗。。。一直向下面压进去,终于你装好了,这时候敌人发起了进攻,你扣动扳机,这时候被你最后装进去的那颗子弹首先被射出去,最后一课子弹肯定是第一颗,。
上面那个例子很多老师都是拿来讲栈的,其实我们也可以从上面看出来一个问题就是栈是先进后出的,大家应该都记得我们第一节课写HelloWorld的时候,老师说过一句话,程序的入口是main方法,那这个到底怎么执行的呢?
我们现在假设有这样的三个方法,(这里为了方便,没有去写具体的实现)
那么这个执行的顺序是什么呢?
这里我们就可以结合栈来说下,根据刚才的那句话,程序的入口是main()方法,我们把main()入栈,但是在他里面还有个test1这个方法,我们在将test1入栈,tets1里面执行了test2,在将test2入栈,那么出来的结果是不是就是这样呢?
那么执行的时候,根据栈的先进后出,我们这也是先进栈的后执行,所以这个方法的执行顺序就是先执行test2,再是test1,再是main方法。
这里有个我们熟悉的,如果我在test1里面在调用test1呢?那是不是就是我们熟悉的递归了。test1入栈,在调用test1,依次这这样的入栈,直到达到了递归的某个条件,这样的才可以处理。
那么栈主要存放些什么呢?现在我们还要了解一个知识,就是我们写的程序的每一个方法在执行的时候都会去创建一个栈帧,迎来存放局部变量表,方法出口等信息,每一个方法的执行都对一个着这个方法的进栈和出栈。
栈中主要存放着8种基本类型的变量+对象的引用变量+实例方法都是在函数的栈内存中分配。·