上次课讲了Java的类装载和动态编译过程,回来后在网上搜集了些资料,然后整理了下
类装载:
(1)jvm的装载过程以及装载原理
所谓装载就是寻找一个类或是一个接口的二进制形式并用该二进制形式来构造代表这个类或是这个接口的class对象的过程,其中类或接口的名称是给定了的。当然名称也可以通过计算得到,但是更常见的是通过搜索源代码经过编译器编译后所得到的二进制形式来构造。 在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化,其中链接又可以分成校验、准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的,各个步骤的主要工作如下:
装载:查找和导入类或接口的二进制数据;
链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;
校验:检查导入类或接口的二进制数据的正确性;
准备:给类的静态变量分配并初始化存储空间;
解析:将符号引用转成直接引用;
初始化:激活类的静态变量的初始化Java代码和静态Java代码块。
(2):java的几种ClassLoader:
类装载器是用来把类(class)装载进JVM的。
JVM规范定义了两种类型的类装载器:启动内装载器(bootstrap)和用户自定义装载器(user-defined class loader)。
JVM在运行时会产生三个ClassLoader:Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader。
Bootstrap是用C++编写的,我们在Java中看不到它,是null,是JVM自带的类装载器,用来装载核心类库,如java.lang.*等。AppClassLoader的Parent是ExtClassLoader,而ExtClassLoader的Parent为Bootstrap ClassLoader。
Java提供了抽象类ClassLoader,所有用户自定义类装载器都实例化自ClassLoader的子类。 System Class Loader是一个特殊的用户自定义类装载器,由JVM的实现者提供,在编程者不特别指定装载器的情况下默认装载用户类。系统类装载器可以通过 ClassLoader.getSystemClassLoader() 方法得到。
测试你所使用的JVM的ClassLoader
public class LoaderSample1 {
public static void main(String[] args) {
Class c;
ClassLoader cl;
cl = ClassLoader.getSystemClassLoader ();
System.out.println(cl);
while (cl != null) {
cl = cl.getParent();
System.out.println(cl);
}
}
}
运行结果:
sun.misc.Launcher$AppClassLoader@addbf1
sun.misc.Launcher$ExtClassLoader@42e816
null
第一行表示,系统类装载器实例化自类sun.misc.Launcher$AppClassLoader
第二行表示,系统类装载器的parent实例化自类sun.misc.Launcher$ExtClassLoader
第三行表示,系统类装载器parent的parent为bootstrap
这三个ClassLoader类之间的父子关系(不是继承关系),父子关系在ClassLoader的实现中有一个 ClassLoader类型的属性,我们可以在自己实现自定义的ClassLoader的时候初始化定义,而这三个系统定义的ClassLoader的父子关系分别是
AppClassLoader——————》(Parent)ExtClassLoader——————————》(parent)BootClassLoader(null c++实现)
动态编译:运行时(RunningTime)确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性,即Class.forName(“ClassName”)应用。
动态编译需要注意的问题:
1、编译时输出路径问题,在相关集成开发环境下(Eclipse)测试环境与生产环境工作目录会不一样。
1.1、在eclipse下工作目录是项目目录。
1.2、生产环境下工作目录就要依情况而定了在没打成war包时会类是WEB-INF/classes
1.3、通过指定编译器参数(-d),标记编译字节码文件存储路径(见示例代码)。
2、要理解java、javac命令中的两个参数{classpath|sourcepath},加上verbose了解详细装载过程
2.1、classpath:搜索类路径(趋向与class文件),这块也可载入且编译相关java文件
2.2、sourcepath: 引用源文件路径,指定编译所关联的源文件(.java),在未打包情况下会直接将关联的源文件编译成.class
<!--EndFragment--> <!--EndFragment-->