类加载与方法调用

1.jvm是啥

jvm 是java语言的运行平台,写c/c++就要知道cpu和内存管理,csapp是本好书,那么,想知道java是怎么实施内存管理和内存回收的呢,在聊此二者前,先知道java是怎么在jvm上运行的,为什么会有多态、匿名类、static field、final为什么很特殊背后的实现原理又是什么?并发的时候为什么要做thread-safe的code,thread-safe 的代码是指 "the state of an object is always accessible and same to all threads."我自己的理解,有Lock和synchronize机制,建立在这个complex os上的JMM模块。先从java代码如何在jvm中表示和被调用的。

从java文件到.class文件,从词法、语法、语义组织成二进制流文件(可执行目标文件),该文件被加载到run-time data area,你的一个个java文件如A.java,B.java的各个部分,经过loading,verify,prepare,reslove,initialize,最终被分解了,而在heap中存放了最终的java.lang.Class文件,被分解的部分被保存在了一个叫run-time constant pool的地方,那些被分解的部分分别是1.对这个class/interface的描述2.对这个method的描述3.对field的描述等,并且他们表示方式是symbolic reference,那么你在用他们的时候,用就是比方说我要调用一个方法method1(以下简称m1)怎么个流程呢?

执行m1,首先会resolve这个methodref,就是从run-time constant pool 中取出这个方法的描述,这个methodref中描述了几部分:1.这个方法属于哪个class,他会记录一个classref。2.方法名字,那么resolve这个method的流程就是先resolve这个class,(resolve这个class的流程就是通过这个classref的symbolic reference去heap中找出对应的java.lang.Class就算是这个class的distinct reference了,这里可以说明虚拟机不会一开始就将所有的symbolic reference转为 distinct reference而是等你去调的时候再做这一步,体现了什么思想?static,final,private,constructor方法是编译后已是distinct reference,所以不需要new instance就可以调用static方法,只要Class.m1()即可。final 的线程安全性可具体看link)如果这个class resolve 不throw exception 的话,把这个类记为c1(否则 ClassNotFound exception),从这个c1里找m1,找到m1,ok,结束。如果没有,去c1的superclass找,再没有,去superclass的superInterface找,再没有就gg。原文在这里jvm specification。得到这个m1之后,再checkAuth,有没有权限访问这个方法。有这个权限继续执行,我们还有故事,没有就再见了。

怎么执行方法?为什么没有stack、native method stack、pc、frame(method执行在这个上面,计算也是)?为什么不提垃圾回收?

2.怎么调方法

方法解析完之后,可以调用这个方法了,在vm stack上分配一个frame,在frame上保存了local variable table,该frame对应方法在运行时常量池中的引用(支持动态链接),operand stack,return address,这里说下普通的方法分为instance method 和class method,顾名思义,前者需要有实例才能调到具体的方法,后者只需要根据class的类型就可以调到具体的方法,static就是instance 方法,只需要一个class就可以invoke。前面讲解加载类的时候到说了,一些method是在编译时将符号引用(symbolic reference)转为了直接引用(district reference),故不需要实例化到heap再去调。调不同的方法执行的instructions也不同,invokestatic指令为调static、private、init、constructor方法,invokevirtual指令调实例方法需要传递objref--即调用的对象(也就是this,thinking in java讲this的时候提到),args参数。而类方法只需要参数不需要调用对象。

接下去就是将参数入栈出栈的过程了,比如将int a = 1,int b =2 ,return a+b*2;执行这段代码,在栈顶把2压入栈顶,执行*2的指令,再将1压入栈顶,执行1+4,并返回结果。这些计算的过程在operand stack进行。

================================================================================================

编辑于2019.03.22

方法调用与多态的理解看这篇文章,需要总结的地方很多。

https://blog.csdn.net/huangrunqing/article/details/51996424

 

双亲委派模型

三种类加载器:1.bootstrap classloader 加载 java_home\lib下的jar包

2.extention classloader 加载 java_home\lib\ext下的jar包

3.application classloader 加载classpath下的所有target下的所有编译后的文件

除了bootstrap外所有的加载器都要有父加载器,判断是否已经加载该类,否则通过通过父加载器,没有就用bootstrap加载器。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章