阅读更多
jvm标准结构
class的执行在Sun JDK中有解释执行和编译为机器码执行两种方式,其中编译为机器码分为client和server两种模式。Sun JDK为了提升class的执行效率,对于解释执行和编译为机器码执行都设置了很多的优化策略。
类加载机制
JVM将类加载过程划分为三个步骤:装载、链接和初始化,装载和链接过程完成后,即将二进制的字节码转换为class对象;初始化过程不是加载类是必须触发的,但最迟必须在初次主动使用对象前执行。
类加载:Bootstrap ClassLoader、Extension ClassLoader、System ClassLoader以及User-Defined ClassLoader
JavaHome/jre/lib/rt.jar JavaHome/jre/lib/ext/*.jar ClassPath
1、ClassNotFoundException
执行Class.forName("com.bluedavy.A"),而当前类的classloder下根本就没有该类所在的jar或者没有该Class文件,就会抛该异常。
2、NoClassDefFoundError
该异常较之ClassNotFoundException更难处理一些,造成此异常的主要原因是加载的类中引用到的另外的类不存在,例如要加载A,而A中调用了B,B不存在或当前CalssLoader没法加载B,就会抛出这个异常。
eg:public class A {
private B b= new B();
}
因此,对于这个异常,须先查看是加载那个类时报报出的,然后再确认该类中引用的类是否存在于当前ClassLoader能加载到的位置。
3、LinkageError
该异常在自定义ClassLoader的情况下出更容易出现,主要原因是此类已经在ClassLoader记载过了,重复地加载会造成该异常,因此要注意避免在并发的清空下出现这样的问题。
JVM中没办法直接更新一个已经load的class,只能创建一个新的ClassLoader类加载更新的Class,然后将新的请求转入该ClassLoader中获取类,这也是JVM中不好实现动态更新的原因之一,而其他更多的原因是对象状态的复制、依赖设置等等。
4、ClassCastException
Sun JDK基于栈的体系结构
线程在创建后,都会产生程序计数器(PC)(或者称PC registers)和栈(Stack);PC存放了下一条要执行的指令在方法内的偏移量;栈中存放了栈帧(StackFrame),每个方法每次调用都会产生栈帧。栈帧主要分为局部变量区和操作数栈两个部分,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果,栈帧中还会有一些杂用空间,例如指向方法已解析的常量池的引用、其他一些VM内部实现需要的数据等。结构如下: