JVM--基本原理,
JVM--基本原理,
java程序的执行过程:
Java编译器:将Java源文件(.java文件)编译成字节码文件(.class文件,是特殊的二进制文件,二进制字节码文件),这种字节码就是JVM的“机器语言”。javac.exe可以简单看成是Java编译器。
Java解释器:是JVM的一部分。Java解释器用来解释执行Java编译器编译后的程序。java.exe可以简单看成是Java解释器。
JVM解释执行字节码文件就是JVM操作Java解释器进行解释执行字节码文件的过程。
ps:字节码文件并不等于二进制机器语言文件,JVM解释器就是将字节码转换为机器码执行。它每翻译一行程序叙述就立刻运行,然后再翻译下一行,再运行,如此不停地进行下去。它会先将源码翻译成另一种语言,以供多次运行而无需再经编译。其制成品无需依赖编译器而运行,程序运行速度比较快。
(1)Bootstrap class loader(引导类装入器)
运行java虚拟机时,加载<java_RunTime_Home>/lib/rt.jar,或者被-Xbootclasspath参数所指定路径中以rt.jar命名的文件。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
(2)Extension Class Loader(拓展类加载器)
负责将< Java_Runtime_Home >/lib/ext/*.jar类库加载到内存中,或者被java.ext.dirs系统变量所指定的路径中的所有类库。开发者可以直接使用标准扩展类加载器。
(3)System Class Loader(系统类加载器)
负责将系统类路径$classpath变量所指的目录下的类库加载到内存中。开发者可以直接使用系统类加载器。
(4)User Defined Class Loader(自定义类加载器)
这是开发人员通过拓展ClassLoader类定义的自定义加载器,加载程序员定义的一些类。
3、类加载机制–双亲委派机制
双亲委派机制:class loader要加载特定的类时,会首先将任务委托给父类加载器,如果父类可以加载,则返回,若不行,则继续递归,只有所有父类都不能加载时,才自己去加载。
因此,java类随着它的类加载器一起具备了一种带有优先级的层次关系,如Object只会由bootstrap class loader层的类加载器进行加载,当用户再定义一个Object类时,会依然还是由同一个类加载器进行加载,避免了会同时存在多个Object类。
此方法负责加载指定名字的类,首先会从已加载的类中去寻找,如果没有找到;从parent ClassLoader[ExtClassLoader]中加载;如果没有加载到,则从Bootstrap ClassLoader中尝试加载(findBootstrapClassOrNull方法), 如果还是加载失败,则抛出异常findLoadedClass方法:调用native方法从当前的ClassLoader实例对象的缓存中寻找已加载的类。
findClass 此方法直接抛出ClassNotFoundException异常,因此要通过覆盖loadClass或此方法来以自定义的方式加载相应的类。
findSystemClass 此方法是从sun.misc.Launcher$AppClassLoader中寻找类,如果未找到,则继续从BootstrapClassLoader中寻找,如果仍然未找到,返回null
defineClass 此方法负责将二进制字节流转换为Class对象,这个方法对于自定义类加载器而言非常重要。如果二进制的字节码的格式不符合jvm class文件格式规范,则抛出ClassFormatError异常;如果生成的类名和二进制字节码不同,则抛出NoClassDefFoundError;如果加载的class是受保护的、采用不同签名的,或者类名是以java.开头的,则抛出SecurityException异常。
ps: ClassNotFoundException 这是最常见的异常,产生这个异常的原因为在当前的ClassLoader 中加载类时,未找到类文件,
NoClassDefFoundError 这个异常是因为 加载到的类中引用到的另外类不存在,例如要加载A,而A中盗用了B,B不存在或当前的ClassLoader无法加载B,就会抛出这个异常。
LinkageError 该异常在自定义ClassLoader的情况下更容易出现,主要原因是此类已经在ClassLoader加载过了,重复的加载会造成该异常。
相关文章
- 暂无相关文章
用户点评